/**
 * @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);
}
Beispiel #6
0
/**
 * 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;
}