/** * @brief Lock a recursive mutex * @ingroup globus_mutex * * @details * The globus_rmutex_lock() function acquires the lock controlled by * @a rmutex. This may be called multiple times in a single thread without * causing deadlock, provided that a call to globus_rmutex_unlock() is * called the same number of times as globus_rmutex_lock(). Once acquired, * all other threads calling this function will be blocked until the * mutex is completely unlocked. * * @param rmutex * A pointer to the mutex to lock * * @return * On success, globus_rmutex_init() increases the lock level for the * mutex, blocks other threads trying to acquire the same mutex, and * returns GLOBUS_SUCCESS; otherwise, it returns a non-zero error code. */ int globus_rmutex_lock( globus_rmutex_t * rmutex) { globus_thread_t thread_id; thread_id = globus_thread_self(); globus_mutex_lock(&rmutex->mutex); { globus_assert(rmutex->level >= 0); if(rmutex->level > 0 && !globus_thread_equal(rmutex->thread_id, thread_id)) { rmutex->waiting++; do { globus_cond_wait(&rmutex->cond, &rmutex->mutex); } while(rmutex->level > 0); rmutex->waiting--; } rmutex->level++; rmutex->thread_id = thread_id; } globus_mutex_unlock(&rmutex->mutex); return 0; }
/** * @brief Unlock a recursive mutex * @ingroup globus_mutex * * @details * The globus_rmutex_unlock() function decrements the lock count for * the lock pointed to by @a rmutex. If the lock count is reduced to * zero, it also unblocks a thread which is trying to acquire the lock * if there is one. * * @param rmutex * Mutex to unlock * * @return GLOBUS_SUCCESS */ int globus_rmutex_unlock( globus_rmutex_t * rmutex) { globus_mutex_lock(&rmutex->mutex); { /* I don't fail here because this is being used with libtool and it * unlocks a mutex that was never locked */ if(rmutex->level > 0) { globus_assert( globus_thread_equal(rmutex->thread_id, globus_thread_self())); rmutex->level--; if(rmutex->level == 0) { memset(&rmutex->thread_id,0,sizeof(rmutex->thread_id)); if(rmutex->waiting) { globus_cond_signal(&rmutex->cond); } } } } globus_mutex_unlock(&rmutex->mutex); return 0; }
/* * globus_l_module_mutex_lock() */ static void globus_l_module_mutex_lock( globus_l_module_mutex_t * mutex) { globus_mutex_lock(&mutex->mutex); { globus_assert(mutex->level >= 0); while (mutex->level > 0 && !globus_thread_equal( mutex->thread_id, globus_thread_self()) ) { globus_cond_wait(&mutex->cond, &mutex->mutex); } mutex->level++; mutex->thread_id = globus_thread_self(); } globus_mutex_unlock(&mutex->mutex); }
/** * OpenSSL thread id callback * */ static unsigned long globus_l_openssl_thread_id(void) { globus_thread_t self = globus_thread_self(); unsigned long rc; memcpy(&rc, &self.dummy, sizeof(unsigned long)); return rc; }
/* * globus_l_module_mutex_unlock() */ static void globus_l_module_mutex_unlock( globus_l_module_mutex_t * mutex) { globus_mutex_lock(&mutex->mutex); { globus_assert(mutex->level > 0); globus_assert( globus_thread_equal( mutex->thread_id, globus_thread_self() ) ); mutex->level--; if (mutex->level == 0) { globus_cond_signal(&mutex->cond); } } globus_mutex_unlock(&mutex->mutex); }
/** * ObserveThread: EventTime change request */ static int ngcllObserveThreadEventTimeChangeRequest( ngclContext_t *context, ngcliObserveThread_t *observe, ngcliObserveItem_t *observeItem, int *error) { static const char fName[] = "ngcllObserveThreadEventTimeChangeRequest"; int requireLock, result; ngLog_t *log; /* Check the arguments */ assert(context != NULL); assert(observe != NULL); assert(observeItem != NULL); log = context->ngc_log; requireLock = 1; /** * Tell the Observe thread that event time was changed */ /* Check if this thread is Observe thread */ result = globus_thread_equal( observe->ngot_thread, globus_thread_self()); if (result != 0) { /** * This thread is Observe thread itself, * and executing ngcllObserveThreadProceedEvents(). * Thus, no need to lock and cond_signal. */ requireLock = 0; } /* Lock */ if (requireLock != 0) { result = ngiMutexLock(&observe->ngot_mutex, log, error); if (result == 0) { ngclLogPrintfContext(context, NG_LOG_CATEGORY_NINFG_PURE, NG_LOG_LEVEL_ERROR, NULL, "%s: Can't lock the Mutex.\n", fName); return 0; } } /* Set the status */ observeItem->ngoi_eventTimeChangeRequested = 1; /* Notify signal */ if (requireLock != 0) { result = ngiCondSignal(&observe->ngot_cond, log, error); if (result == 0) { ngclLogPrintfContext(context, NG_LOG_CATEGORY_NINFG_PURE, NG_LOG_LEVEL_ERROR, NULL, "%s: Can't signal the Condition Variable.\n", fName); goto error; } } /* Unlock */ if (requireLock != 0) { result = ngiMutexUnlock(&observe->ngot_mutex, log, error); if (result == 0) { ngclLogPrintfContext(context, NG_LOG_CATEGORY_NINFG_PURE, NG_LOG_LEVEL_ERROR, NULL, "%s: Can't unlock the Mutex.\n", fName); return 0; } } /* Success */ return 1; error: /* Unlock */ if (requireLock != 0) { result = ngiMutexUnlock(&observe->ngot_mutex, log, NULL); if (result == 0) { ngclLogPrintfContext(context, NG_LOG_CATEGORY_NINFG_PURE, NG_LOG_LEVEL_ERROR, NULL, "%s: Can't unlock the Mutex.\n", fName); return 0; } } /* Failed */ return 0; }