static apr_status_t proc_mutex_pthread_acquire_ex()

in locks/unix/proc_mutex.c [700:848]


static apr_status_t proc_mutex_pthread_acquire_ex(apr_proc_mutex_t *mutex,
                                                  apr_interval_time_t timeout)
{
    apr_status_t rv;

#if APR_USE_PROC_PTHREAD_MUTEX_COND
    if (proc_pthread_mutex_is_cond(mutex)) {
        if ((rv = pthread_mutex_lock(&proc_pthread_mutex(mutex)))) {
#ifdef HAVE_ZOS_PTHREADS
            rv = errno;
#endif
#if defined(HAVE_PTHREAD_MUTEX_ROBUST) || defined(HAVE_PTHREAD_MUTEX_ROBUST_NP)
            /* Okay, our owner died.  Let's try to make it consistent again. */
            if (rv == EOWNERDEAD) {
                proc_pthread_mutex_dec(mutex);
#ifdef HAVE_PTHREAD_MUTEX_ROBUST
                pthread_mutex_consistent(&proc_pthread_mutex(mutex));
#else
                pthread_mutex_consistent_np(&proc_pthread_mutex(mutex));
#endif
            }
            else
#endif
            return rv;
        }

        if (!proc_pthread_mutex_cond_locked(mutex)) {
            rv = APR_SUCCESS;
        }
        else if (!timeout) {
            rv = APR_TIMEUP;
        }
        else {
            struct timespec abstime;

            if (timeout > 0) {
                timeout += apr_time_now();
                abstime.tv_sec = apr_time_sec(timeout);
                abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */
            }

            proc_pthread_mutex_cond_num_waiters(mutex)++;
            do {
                if (timeout < 0) {
                    rv = pthread_cond_wait(&proc_pthread_mutex_cond(mutex),
                                           &proc_pthread_mutex(mutex));
                    if (rv) {
#ifdef HAVE_ZOS_PTHREADS
                        rv = errno;
#endif
                        break;
                    }
                }
                else {
                    rv = pthread_cond_timedwait(&proc_pthread_mutex_cond(mutex),
                                                &proc_pthread_mutex(mutex),
                                                &abstime);
                    if (rv) {
#ifdef HAVE_ZOS_PTHREADS
                        rv = errno;
#endif
                        if (rv == ETIMEDOUT) {
                            rv = APR_TIMEUP;
                        }
                        break;
                    }
                }
            } while (proc_pthread_mutex_cond_locked(mutex));
            proc_pthread_mutex_cond_num_waiters(mutex)--;
        }
        if (rv != APR_SUCCESS) {
            pthread_mutex_unlock(&proc_pthread_mutex(mutex));
            return rv;
        }

        proc_pthread_mutex_cond_locked(mutex) = 1;

        rv = pthread_mutex_unlock(&proc_pthread_mutex(mutex));
        if (rv) {
#ifdef HAVE_ZOS_PTHREADS
            rv = errno;
#endif
            return rv;
        }
    }
    else
#endif /* APR_USE_PROC_PTHREAD_MUTEX_COND */
    {
        if (timeout < 0) {
            rv = pthread_mutex_lock(&proc_pthread_mutex(mutex));
            if (rv) {
#ifdef HAVE_ZOS_PTHREADS
                rv = errno;
#endif
            }
        }
        else if (!timeout) {
            rv = pthread_mutex_trylock(&proc_pthread_mutex(mutex));
            if (rv) {
#ifdef HAVE_ZOS_PTHREADS
                rv = errno;
#endif
                if (rv == EBUSY) {
                    return APR_TIMEUP;
                }
            }
        }
        else
#if defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK)
        {
            struct timespec abstime;

            timeout += apr_time_now();
            abstime.tv_sec = apr_time_sec(timeout);
            abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */

            rv = pthread_mutex_timedlock(&proc_pthread_mutex(mutex), &abstime);
            if (rv) {
#ifdef HAVE_ZOS_PTHREADS
                rv = errno;
#endif
                if (rv == ETIMEDOUT) {
                    return APR_TIMEUP;
                }
            }
        }
        if (rv) {
#if defined(HAVE_PTHREAD_MUTEX_ROBUST) || defined(HAVE_PTHREAD_MUTEX_ROBUST_NP)
            /* Okay, our owner died.  Let's try to make it consistent again. */
            if (rv == EOWNERDEAD) {
                proc_pthread_mutex_dec(mutex);
#ifdef HAVE_PTHREAD_MUTEX_ROBUST
                pthread_mutex_consistent(&proc_pthread_mutex(mutex));
#else
                pthread_mutex_consistent_np(&proc_pthread_mutex(mutex));
#endif
            }
            else
#endif
            return rv;
        }
#else /* !HAVE_PTHREAD_MUTEX_TIMEDLOCK */
        return proc_mutex_spinsleep_timedacquire(mutex, timeout);
#endif
    }

    mutex->curr_locked = 1;
    return APR_SUCCESS;
}