root/opal/threads/wait_sync.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. sync_wait_st
  2. wait_sync_update

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2014-2016 The University of Tennessee and The University
   4  *                         of Tennessee Research Foundation.  All rights
   5  *                         reserved.
   6  * Copyright (c) 2016      Los Alamos National Security, LLC. All rights
   7  *                         reserved.
   8  * Copyright (c) 2016      Mellanox Technologies. All rights reserved.
   9  * Copyright (c) 2016      Research Organization for Information Science
  10  *                         and Technology (RIST). All rights reserved.
  11  * Copyright (c) 2017      IBM Corporation. All rights reserved.
  12  * $COPYRIGHT$
  13  *
  14  * Additional copyrights may follow
  15  *
  16  * $HEADER$
  17  */
  18 
  19 #if !defined(OPAL_THREADS_WAIT_SYNC_H)
  20 #define OPAL_THREADS_WAIT_SYNC_H
  21 
  22 #include "opal/sys/atomic.h"
  23 #include "opal/threads/condition.h"
  24 #include <pthread.h>
  25 
  26 BEGIN_C_DECLS
  27 
  28 extern int opal_max_thread_in_progress;
  29 
  30 typedef struct ompi_wait_sync_t {
  31     opal_atomic_int32_t count;
  32     int32_t status;
  33     pthread_cond_t condition;
  34     pthread_mutex_t lock;
  35     struct ompi_wait_sync_t *next;
  36     struct ompi_wait_sync_t *prev;
  37     volatile bool signaling;
  38 } ompi_wait_sync_t;
  39 
  40 #define REQUEST_PENDING        (void*)0L
  41 #define REQUEST_COMPLETED      (void*)1L
  42 
  43 #define SYNC_WAIT(sync)                 (opal_using_threads() ? ompi_sync_wait_mt (sync) : sync_wait_st (sync))
  44 
  45 /* The loop in release handles a race condition between the signaling
  46  * thread and the destruction of the condition variable. The signaling
  47  * member will be set to false after the final signaling thread has
  48  * finished operating on the sync object. This is done to avoid
  49  * extra atomics in the signalling function and keep it as fast
  50  * as possible. Note that the race window is small so spinning here
  51  * is more optimal than sleeping since this macro is called in
  52  * the critical path. */
  53 #define WAIT_SYNC_RELEASE(sync)                       \
  54     if (opal_using_threads()) {                       \
  55         while ((sync)->signaling) {                   \
  56             continue;                                 \
  57         }                                             \
  58         pthread_cond_destroy(&(sync)->condition);     \
  59         pthread_mutex_destroy(&(sync)->lock);         \
  60     }
  61 
  62 #define WAIT_SYNC_RELEASE_NOWAIT(sync)                \
  63     if (opal_using_threads()) {                       \
  64         pthread_cond_destroy(&(sync)->condition);     \
  65         pthread_mutex_destroy(&(sync)->lock);         \
  66     }
  67 
  68 
  69 #define WAIT_SYNC_SIGNAL(sync)                        \
  70     if (opal_using_threads()) {                       \
  71         pthread_mutex_lock(&(sync->lock));            \
  72         pthread_cond_signal(&sync->condition);        \
  73         pthread_mutex_unlock(&(sync->lock));          \
  74         sync->signaling = false;                      \
  75     }
  76 
  77 #define WAIT_SYNC_SIGNALLED(sync){                    \
  78         (sync)->signaling = false;                    \
  79 }
  80 
  81 OPAL_DECLSPEC int ompi_sync_wait_mt(ompi_wait_sync_t *sync);
  82 static inline int sync_wait_st (ompi_wait_sync_t *sync)
  83 {
  84     while (sync->count > 0) {
  85         opal_progress();
  86     }
  87 
  88     return sync->status;
  89 }
  90 
  91 
  92 #define WAIT_SYNC_INIT(sync,c)                                  \
  93     do {                                                        \
  94         (sync)->count = (c);                                    \
  95         (sync)->next = NULL;                                    \
  96         (sync)->prev = NULL;                                    \
  97         (sync)->status = 0;                                     \
  98         (sync)->signaling = (0 != (c));                         \
  99         if (opal_using_threads()) {                             \
 100             pthread_cond_init (&(sync)->condition, NULL);       \
 101             pthread_mutex_init (&(sync)->lock, NULL);           \
 102         }                                                       \
 103     } while(0)
 104 
 105 /**
 106  * Update the status of the synchronization primitive. If an error is
 107  * reported the synchronization is completed and the signal
 108  * triggered. The status of the synchronization will be reported to
 109  * the waiting threads.
 110  */
 111 static inline void wait_sync_update(ompi_wait_sync_t *sync, int updates, int status)
 112 {
 113     if( OPAL_LIKELY(OPAL_SUCCESS == status) ) {
 114         if( 0 != (OPAL_THREAD_ADD_FETCH32(&sync->count, -updates)) ) {
 115             return;
 116         }
 117     } else {
 118         /* this is an error path so just use the atomic */
 119         sync->status = OPAL_ERROR;
 120         opal_atomic_wmb ();
 121         opal_atomic_swap_32 (&sync->count, 0);
 122     }
 123     WAIT_SYNC_SIGNAL(sync);
 124 }
 125 
 126 END_C_DECLS
 127 
 128 #endif /* defined(OPAL_THREADS_WAIT_SYNC_H) */

/* [<][>][^][v][top][bottom][index][help] */