root/opal/threads/wait_sync.c

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

DEFINITIONS

This source file includes following definitions.
  1. ompi_sync_wait_mt

   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) 2017      IBM Corporation. All rights reserved.
   9  * $COPYRIGHT$
  10  *
  11  * Additional copyrights may follow
  12  *
  13  * $HEADER$
  14  */
  15 #include "wait_sync.h"
  16 
  17 static opal_mutex_t wait_sync_lock = OPAL_MUTEX_STATIC_INIT;
  18 static ompi_wait_sync_t* wait_sync_list = NULL;
  19 
  20 static opal_atomic_int32_t num_thread_in_progress = 0;
  21 
  22 #define WAIT_SYNC_PASS_OWNERSHIP(who)                  \
  23     do {                                               \
  24         pthread_mutex_lock( &(who)->lock);             \
  25         pthread_cond_signal( &(who)->condition );      \
  26         pthread_mutex_unlock( &(who)->lock);           \
  27     } while(0)
  28 
  29 int ompi_sync_wait_mt(ompi_wait_sync_t *sync)
  30 {
  31     /* Don't stop if the waiting synchronization is completed. We avoid the
  32      * race condition around the release of the synchronization using the
  33      * signaling field.
  34      */
  35     if(sync->count <= 0)
  36         return (0 == sync->status) ? OPAL_SUCCESS : OPAL_ERROR;
  37 
  38     /* lock so nobody can signal us during the list updating */
  39     pthread_mutex_lock(&sync->lock);
  40 
  41     /* Now that we hold the lock make sure another thread has not already
  42      * call cond_signal.
  43      */
  44     if(sync->count <= 0) {
  45         pthread_mutex_unlock(&sync->lock);
  46         return (0 == sync->status) ? OPAL_SUCCESS : OPAL_ERROR;
  47     }
  48 
  49     /* Insert sync on the list of pending synchronization constructs */
  50     OPAL_THREAD_LOCK(&wait_sync_lock);
  51     if( NULL == wait_sync_list ) {
  52         sync->next = sync->prev = sync;
  53         wait_sync_list = sync;
  54     } else {
  55         sync->prev = wait_sync_list->prev;
  56         sync->prev->next = sync;
  57         sync->next = wait_sync_list;
  58         wait_sync_list->prev = sync;
  59     }
  60     OPAL_THREAD_UNLOCK(&wait_sync_lock);
  61 
  62     /**
  63      * If we are not responsible for progresing, go silent until something worth noticing happen:
  64      *  - this thread has been promoted to take care of the progress
  65      *  - our sync has been triggered.
  66      */
  67  check_status:
  68     if( sync != wait_sync_list && num_thread_in_progress >= opal_max_thread_in_progress) {
  69         pthread_cond_wait(&sync->condition, &sync->lock);
  70 
  71         /**
  72          * At this point either the sync was completed in which case
  73          * we should remove it from the wait list, or/and I was
  74          * promoted as the progress manager.
  75          */
  76 
  77         if( sync->count <= 0 ) {  /* Completed? */
  78             pthread_mutex_unlock(&sync->lock);
  79             goto i_am_done;
  80         }
  81         /* either promoted, or spurious wakeup ! */
  82         goto check_status;
  83     }
  84     pthread_mutex_unlock(&sync->lock);
  85 
  86     OPAL_THREAD_ADD_FETCH32(&num_thread_in_progress, 1);
  87     while(sync->count > 0) {  /* progress till completion */
  88         opal_progress();  /* don't progress with the sync lock locked or you'll deadlock */
  89     }
  90     OPAL_THREAD_ADD_FETCH32(&num_thread_in_progress, -1);
  91 
  92  i_am_done:
  93     /* My sync is now complete. Trim the list: remove self, wake next */
  94     OPAL_THREAD_LOCK(&wait_sync_lock);
  95     sync->prev->next = sync->next;
  96     sync->next->prev = sync->prev;
  97     /* In case I am the progress manager, pass the duties on */
  98     if( sync == wait_sync_list ) {
  99         wait_sync_list = (sync == sync->next) ? NULL : sync->next;
 100         if( NULL != wait_sync_list )
 101             WAIT_SYNC_PASS_OWNERSHIP(wait_sync_list);
 102     }
 103     OPAL_THREAD_UNLOCK(&wait_sync_lock);
 104 
 105     return (0 == sync->status) ? OPAL_SUCCESS : OPAL_ERROR;
 106 }

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