root/opal/mca/pmix/pmix4x/pmix/src/threads/wait_sync.c

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

DEFINITIONS

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

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