diff options
-rw-r--r-- | configure.in | 5 | ||||
-rw-r--r-- | locks/unix/misc.c | 193 | ||||
-rw-r--r-- | locks/unix/proc_mutex.c | 479 | ||||
-rw-r--r-- | locks/unix/thread_mutex.c | 67 | ||||
-rw-r--r-- | test/testprocmutex.c | 27 |
5 files changed, 301 insertions, 470 deletions
diff --git a/configure.in b/configure.in index 29fd00d85..cfd79e85b 100644 --- a/configure.in +++ b/configure.in @@ -2297,11 +2297,6 @@ APR_IFALLYES(header:pthread.h define:PTHREAD_PROCESS_SHARED dnl hasprocpthreadser="1", hasprocpthreadser="0") APR_IFALLYES(header:OS.h func:create_sem, hasbeossem="1", hasbeossem="0") -AC_CHECK_FUNCS(pthread_condattr_setpshared) -APR_IFALLYES(header:pthread.h func:pthread_condattr_setpshared, - have_pthread_condattr_setpshared="1", have_pthread_condattr_setpshared="0") -AC_SUBST(have_pthread_condattr_setpshared) - # See which lock mechanism we'll select by default on this system. # The last APR_DECIDE to execute sets the default. # At this stage, we match the ordering in Apache 1.3 diff --git a/locks/unix/misc.c b/locks/unix/misc.c new file mode 100644 index 000000000..d7018fc3a --- /dev/null +++ b/locks/unix/misc.c @@ -0,0 +1,193 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_private.h" +#include "apr_arch_thread_mutex.h" +#define APR_WANT_MEMFUNC +#include "apr_want.h" + +#if APR_HAS_THREADS +#if APR_HAS_SYSVSEM_SERIALIZE +#if !HAVE_SEMTIMEDOP +#include <sys/sem.h> +#endif +#endif +#define SLEEP_TIME_NS 10000000 +#define NANOSECS_PER_SEC 1000000000 +extern int errno; + +#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK +extern int pthread_mutex_timedlock(pthread_mutex_t * mutex, + const struct timespec *abs_timeout); +/* + * A pthread_mutex_timedlock() impl for OSX/macOS, which lacks the + * real thing. + * NOTE: Unlike the real McCoy, won't return EOWNERDEAD, EDEADLK + * or EOWNERDEAD + */ +int pthread_mutex_timedlock(pthread_mutex_t * mutex, + const struct timespec *abs_timeout) +{ + int rv; + struct timespec remaining, ts, tod; + apr_time_t now; + + remaining = *abs_timeout; + now = apr_time_now(); + tod.tv_sec = apr_time_sec(now); + tod.tv_nsec = apr_time_usec(now) * 1000; /* nanoseconds */ + + remaining.tv_sec -= tod.tv_sec; + if (tod.tv_nsec <= remaining.tv_nsec) { + remaining.tv_nsec -= tod.tv_nsec; + } + else { + remaining.tv_sec--; + remaining.tv_nsec = + (NANOSECS_PER_SEC - (tod.tv_nsec - remaining.tv_nsec)); + } + /* If we had a REALLY small timeout ;) */ + if (remaining.tv_sec < 0) { + return ETIMEDOUT; + } + while ((rv = pthread_mutex_trylock(mutex)) == EBUSY) { + ts.tv_sec = 0; + ts.tv_nsec = (remaining.tv_sec > 0 ? SLEEP_TIME_NS : + (remaining.tv_nsec < + SLEEP_TIME_NS ? remaining.tv_nsec : SLEEP_TIME_NS)); + nanosleep(&ts, &ts); + if (ts.tv_nsec <= remaining.tv_nsec) { + remaining.tv_nsec -= ts.tv_nsec; + } + else { + remaining.tv_sec--; + remaining.tv_nsec = + (NANOSECS_PER_SEC - (ts.tv_nsec - remaining.tv_nsec)); + } + if (remaining.tv_sec < 0 + || (!remaining.tv_sec && remaining.tv_nsec <= SLEEP_TIME_NS)) { + return ETIMEDOUT; + } + } + + return rv; +} +#endif /* HAVE_PTHREAD_MUTEX_TIMEDLOCK */ + +#if APR_HAS_POSIXSEM_SERIALIZE +#if !HAVE_SEM_TIMEDWAIT +extern int sem_timedwait(sem_t * sem, const struct timespec *abs_timeout); +/* + * A sem_timedwait() impl for OSX/macOS, which lacks the + * real thing. + */ +int sem_timedwait(sem_t * sem, const struct timespec *abs_timeout) +{ + int rv; + struct timespec remaining, ts, tod; + apr_time_t now; + + remaining = *abs_timeout; + now = apr_time_now(); + tod.tv_sec = apr_time_sec(now); + tod.tv_nsec = apr_time_usec(now) * 1000; /* nanoseconds */ + + remaining.tv_sec -= tod.tv_sec; + if (tod.tv_nsec <= remaining.tv_nsec) { + remaining.tv_nsec -= tod.tv_nsec; + } + else { + remaining.tv_sec--; + remaining.tv_nsec = + (NANOSECS_PER_SEC - (tod.tv_nsec - remaining.tv_nsec)); + } + /* If we had a REALLY small timeout ;) */ + if (remaining.tv_sec < 0) { + return ETIMEDOUT; + } + errno = 0; + while (((rv = sem_trywait(sem)) != 0) && (errno == EAGAIN)) { + ts.tv_sec = 0; + ts.tv_nsec = (remaining.tv_sec > 0 ? SLEEP_TIME_NS : + (remaining.tv_nsec < + SLEEP_TIME_NS ? remaining.tv_nsec : SLEEP_TIME_NS)); + nanosleep(&ts, &ts); + if (ts.tv_nsec <= remaining.tv_nsec) { + remaining.tv_nsec -= ts.tv_nsec; + } + else { + remaining.tv_sec--; + remaining.tv_nsec = + (NANOSECS_PER_SEC - (ts.tv_nsec - remaining.tv_nsec)); + } + if (remaining.tv_sec < 0 + || (!remaining.tv_sec && remaining.tv_nsec <= SLEEP_TIME_NS)) { + return ETIMEDOUT; + } + } + return rv; +} +#endif /* HAVE_SEM_TIMEDWAIT */ +#endif /* APR_HAS_POSIXSEM_SERIALIZE */ + +#if APR_HAS_SYSVSEM_SERIALIZE +#if !HAVE_SEMTIMEDOP +extern int semtimedop(int semid, struct sembuf *sops, unsigned nsops, + const struct timespec *timeout); +/* + * A semtimedop() impl for OSX/macOS, which lacks the + * real thing. + */ +int semtimedop(int semid, struct sembuf *sops, unsigned nsops, + const struct timespec *timeout) +{ + int rv; + struct timespec remaining, ts; + struct sembuf proc_mutex_op_try; + + proc_mutex_op_try.sem_num = 0; + proc_mutex_op_try.sem_op = -1; + proc_mutex_op_try.sem_flg = SEM_UNDO | IPC_NOWAIT; + + remaining = *timeout; + errno = 0; + while (((rv = semop(semid, &proc_mutex_op_try, nsops)) != 0) + && (errno == EAGAIN)) { + ts.tv_sec = 0; + ts.tv_nsec = (remaining.tv_sec > 0 ? SLEEP_TIME_NS : + (remaining.tv_nsec < + SLEEP_TIME_NS ? remaining.tv_nsec : SLEEP_TIME_NS)); + nanosleep(&ts, &ts); + if (ts.tv_nsec <= remaining.tv_nsec) { + remaining.tv_nsec -= ts.tv_nsec; + } + else { + remaining.tv_sec--; + remaining.tv_nsec = + (NANOSECS_PER_SEC - (ts.tv_nsec - remaining.tv_nsec)); + } + if (remaining.tv_sec < 0 + || (!remaining.tv_sec && remaining.tv_nsec <= SLEEP_TIME_NS)) { + return ETIMEDOUT; + } + } + return rv; +} +#endif /* HAVE_SEMTIMEDOP */ +#endif /* APR_HAS_SYSVSEM_SERIALIZE */ + + +#endif /* APR_HAS_THREADS */ diff --git a/locks/unix/proc_mutex.c b/locks/unix/proc_mutex.c index 3508b4f04..c4ec910ee 100644 --- a/locks/unix/proc_mutex.c +++ b/locks/unix/proc_mutex.c @@ -46,56 +46,6 @@ static apr_status_t proc_mutex_no_perms_set(apr_proc_mutex_t *mutex, } #endif -#if APR_HAS_FCNTL_SERIALIZE \ - || APR_HAS_FLOCK_SERIALIZE \ - || (APR_HAS_SYSVSEM_SERIALIZE \ - && !defined(HAVE_SEMTIMEDOP)) \ - || (APR_HAS_POSIXSEM_SERIALIZE \ - && !defined(HAVE_SEM_TIMEDWAIT)) \ - || (APR_HAS_PROC_PTHREAD_SERIALIZE \ - && !defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK) \ - && !defined(HAVE_PTHREAD_CONDATTR_SETPSHARED)) -static apr_status_t proc_mutex_spinsleep_timedacquire(apr_proc_mutex_t *mutex, - apr_time_t timeout, - int absolute) -{ - apr_status_t rv; - if (absolute) { - timeout -= apr_time_now(); - if (timeout < 0) { - timeout = 0; - } - } - if (timeout < 0) { - rv = apr_proc_mutex_lock(mutex); - } - else { -#define SLEEP_TIME apr_time_from_msec(10) - for (;;) { - rv = apr_proc_mutex_trylock(mutex); - if (!APR_STATUS_IS_EBUSY(rv)) { - if (rv == APR_SUCCESS) { - mutex->curr_locked = 1; - } - break; - } - if (!timeout) { - rv = APR_TIMEUP; - break; - } - if (timeout > SLEEP_TIME) { - apr_sleep(SLEEP_TIME); - timeout -= SLEEP_TIME; - } - else { - apr_sleep(timeout); - timeout = 0; - } - } - } - return rv; -} -#endif #if APR_HAS_POSIXSEM_SERIALIZE @@ -233,11 +183,13 @@ static apr_status_t proc_mutex_posix_tryacquire(apr_proc_mutex_t *mutex) return APR_SUCCESS; } -#if defined(HAVE_SEM_TIMEDWAIT) static apr_status_t proc_mutex_posix_timedacquire(apr_proc_mutex_t *mutex, apr_time_t timeout, int absolute) { +#if !HAVE_SEM_TIMEDWAIT +extern int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); +#endif if (timeout < 0) { return proc_mutex_posix_acquire(mutex); } @@ -264,7 +216,6 @@ static apr_status_t proc_mutex_posix_timedacquire(apr_proc_mutex_t *mutex, mutex->curr_locked = 1; return APR_SUCCESS; } -#endif static apr_status_t proc_mutex_posix_release(apr_proc_mutex_t *mutex) { @@ -287,11 +238,7 @@ static const apr_proc_mutex_unix_lock_methods_t mutex_posixsem_methods = proc_mutex_posix_create, proc_mutex_posix_acquire, proc_mutex_posix_tryacquire, -#if defined(HAVE_SEM_TIMEDWAIT) proc_mutex_posix_timedacquire, -#else - proc_mutex_spinsleep_timedacquire, -#endif proc_mutex_posix_release, proc_mutex_posix_cleanup, proc_mutex_no_child_init, @@ -390,28 +337,28 @@ static apr_status_t proc_mutex_sysv_tryacquire(apr_proc_mutex_t *mutex) return APR_SUCCESS; } -#if defined(HAVE_SEMTIMEDOP) static apr_status_t proc_mutex_sysv_timedacquire(apr_proc_mutex_t *mutex, apr_time_t timeout, int absolute) { +#if !HAVE_SEMTIMEDOP +extern int semtimedop(int semid, struct sembuf *sops, unsigned nsops, + const struct timespec *timeout); +#endif if (timeout < 0) { return proc_mutex_sysv_acquire(mutex); } else { int rc; - struct timespec reltime; - if (absolute) { - timeout -= apr_time_now(); - if (timeout < 0) { - return proc_mutex_sysv_tryacquire(mutex); - } + struct timespec abstime; + if (!absolute) { + timeout += apr_time_now(); } - reltime.tv_sec = apr_time_sec(timeout); - reltime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */ + abstime.tv_sec = apr_time_sec(timeout); + abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */ do { rc = semtimedop(mutex->os.crossproc, &proc_mutex_op_on, 1, - &reltime); + &abstime); } while (rc < 0 && errno == EINTR); if (rc < 0) { if (errno == EAGAIN) { @@ -423,7 +370,6 @@ static apr_status_t proc_mutex_sysv_timedacquire(apr_proc_mutex_t *mutex, mutex->curr_locked = 1; return APR_SUCCESS; } -#endif static apr_status_t proc_mutex_sysv_release(apr_proc_mutex_t *mutex) { @@ -467,11 +413,7 @@ static const apr_proc_mutex_unix_lock_methods_t mutex_sysv_methods = proc_mutex_sysv_create, proc_mutex_sysv_acquire, proc_mutex_sysv_tryacquire, -#if defined(HAVE_SEMTIMEDOP) proc_mutex_sysv_timedacquire, -#else - proc_mutex_spinsleep_timedacquire, -#endif proc_mutex_sysv_release, proc_mutex_sysv_cleanup, proc_mutex_no_child_init, @@ -484,12 +426,6 @@ static const apr_proc_mutex_unix_lock_methods_t mutex_sysv_methods = #if APR_HAS_PROC_PTHREAD_SERIALIZE -#ifndef APR_USE_PROC_PTHREAD_MUTEX_COND -#define APR_USE_PROC_PTHREAD_MUTEX_COND \ - (defined(HAVE_PTHREAD_CONDATTR_SETPSHARED) \ - && !defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK)) -#endif - /* The mmap()ed pthread_interproc is the native pthread_mutex_t followed * by a refcounter to track children using it. We want to avoid calling * pthread_mutex_destroy() on the shared mutex area while it is in use by @@ -500,31 +436,12 @@ static const apr_proc_mutex_unix_lock_methods_t mutex_sysv_methods = * destroy it. */ typedef struct { -#define proc_pthread_cast(m) \ - ((proc_pthread_mutex_t *)(m)->os.pthread_interproc) pthread_mutex_t mutex; -#define proc_pthread_mutex(m) \ - (proc_pthread_cast(m)->mutex) -#if APR_USE_PROC_PTHREAD_MUTEX_COND - pthread_cond_t cond; -#define proc_pthread_mutex_cond(m) \ - (proc_pthread_cast(m)->cond) - apr_int32_t cond_locked; -#define proc_pthread_mutex_cond_locked(m) \ - ((m)->pthread_refcounting ? proc_pthread_cast(m)->cond_locked : -1) - apr_uint32_t cond_num_waiters; -#define proc_pthread_mutex_cond_num_waiters(m) \ - (proc_pthread_cast(m)->cond_num_waiters) -#endif /* APR_USE_PROC_PTHREAD_MUTEX_COND */ apr_uint32_t refcount; -#define proc_pthread_mutex_refcount(m) \ - (proc_pthread_cast(m)->refcount) } proc_pthread_mutex_t; - -static apr_status_t proc_mutex_pthread_timedacquire(apr_proc_mutex_t *mutex, - apr_time_t timeout, - int absolute); +#define proc_pthread_mutex_refcount(m) \ + (((proc_pthread_mutex_t *)(m)->os.pthread_interproc)->refcount) static APR_INLINE int proc_pthread_mutex_inc(apr_proc_mutex_t *mutex) { @@ -548,14 +465,8 @@ static apr_status_t proc_pthread_mutex_unref(void *mutex_) apr_proc_mutex_t *mutex=mutex_; apr_status_t rv; -#if APR_USE_PROC_PTHREAD_MUTEX_COND - if (proc_pthread_mutex_cond_locked(mutex) != -1) { - mutex->curr_locked = 0; - } - else -#endif /* APR_USE_PROC_PTHREAD_MUTEX_COND */ if (mutex->curr_locked == 1) { - if ((rv = pthread_mutex_unlock(&proc_pthread_mutex(mutex)))) { + if ((rv = pthread_mutex_unlock(mutex->os.pthread_interproc))) { #ifdef HAVE_ZOS_PTHREADS rv = errno; #endif @@ -563,17 +474,7 @@ static apr_status_t proc_pthread_mutex_unref(void *mutex_) } } if (!proc_pthread_mutex_dec(mutex)) { -#if APR_USE_PROC_PTHREAD_MUTEX_COND - if (proc_pthread_mutex_cond_locked(mutex) != -1 && - (rv = pthread_cond_destroy(&proc_pthread_mutex_cond(mutex)))) { -#ifdef HAVE_ZOS_PTHREADS - rv = errno; -#endif - return rv; - } -#endif /* APR_USE_PROC_PTHREAD_MUTEX_COND */ - - if ((rv = pthread_mutex_destroy(&proc_pthread_mutex(mutex)))) { + if ((rv = pthread_mutex_destroy(mutex->os.pthread_interproc))) { #ifdef HAVE_ZOS_PTHREADS rv = errno; #endif @@ -625,9 +526,6 @@ static apr_status_t proc_mutex_pthread_create(apr_proc_mutex_t *new_mutex, new_mutex->pthread_refcounting = 1; new_mutex->curr_locked = -1; /* until the mutex has been created */ -#if APR_USE_PROC_PTHREAD_MUTEX_COND - proc_pthread_mutex_cond_locked(new_mutex) = -1; -#endif if ((rv = pthread_mutexattr_init(&mattr))) { #ifdef HAVE_ZOS_PTHREADS @@ -665,7 +563,7 @@ static apr_status_t proc_mutex_pthread_create(apr_proc_mutex_t *new_mutex, } #endif /* HAVE_PTHREAD_MUTEX_ROBUST */ - if ((rv = pthread_mutex_init(&proc_pthread_mutex(new_mutex), &mattr))) { + if ((rv = pthread_mutex_init(new_mutex->os.pthread_interproc, &mattr))) { #ifdef HAVE_ZOS_PTHREADS rv = errno; #endif @@ -706,269 +604,112 @@ static apr_status_t proc_mutex_pthread_child_init(apr_proc_mutex_t **mutex, static apr_status_t proc_mutex_pthread_acquire(apr_proc_mutex_t *mutex) { - return proc_mutex_pthread_timedacquire(mutex, -1, 0); -} - -static apr_status_t proc_mutex_pthread_tryacquire(apr_proc_mutex_t *mutex) -{ - apr_status_t rv = proc_mutex_pthread_timedacquire(mutex, 0, 0); - return (rv == APR_TIMEUP) ? APR_EBUSY : rv; -} - -static apr_status_t proc_mutex_pthread_timedacquire(apr_proc_mutex_t *mutex, - apr_time_t timeout, - int absolute) -{ -#if !APR_USE_PROC_PTHREAD_MUTEX_COND && !defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK) - return proc_mutex_spinsleep_timedacquire(mutex, timeout, absolute); -#else apr_status_t rv; -#if APR_USE_PROC_PTHREAD_MUTEX_COND - if (proc_pthread_mutex_cond_locked(mutex) != -1) { - if ((rv = pthread_mutex_lock(&proc_pthread_mutex(mutex)))) { -#ifdef HAVE_ZOS_PTHREADS - rv = errno; -#endif -#ifdef HAVE_PTHREAD_MUTEX_ROBUST - /* Okay, our owner died. Let's try to make it consistent again. */ - if (rv == EOWNERDEAD) { - proc_pthread_mutex_dec(mutex); - pthread_mutex_consistent_np(&proc_pthread_mutex(mutex)); - } - else -#endif - return rv; - } - - if (!proc_pthread_mutex_cond_locked(mutex)) { - proc_pthread_mutex_cond_locked(mutex) = 1; - } - else if (!timeout) { - rv = APR_TIMEUP; - } - else { - proc_pthread_mutex_cond_num_waiters(mutex)++; - if (timeout < 0) { - rv = pthread_cond_wait(&proc_pthread_mutex_cond(mutex), - &proc_pthread_mutex(mutex)); + if ((rv = pthread_mutex_lock(mutex->os.pthread_interproc))) { #ifdef HAVE_ZOS_PTHREADS - if (rv) { - rv = errno; - } -#endif - } - else { - struct timespec abstime; - if (!absolute) { - timeout += apr_time_now(); - } - abstime.tv_sec = apr_time_sec(timeout); - abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */ - rv = pthread_cond_timedwait(&proc_pthread_mutex_cond(mutex), - &proc_pthread_mutex(mutex), - &abstime); - if (rv) { -#ifdef HAVE_ZOS_PTHREADS - rv = errno; + rv = errno; #endif - if (rv == ETIMEDOUT) { - rv = APR_TIMEUP; - } - } - } - proc_pthread_mutex_cond_num_waiters(mutex)--; - } - if (rv) { - pthread_mutex_unlock(&proc_pthread_mutex(mutex)); - return rv; +#ifdef HAVE_PTHREAD_MUTEX_ROBUST + /* Okay, our owner died. Let's try to make it consistent again. */ + if (rv == EOWNERDEAD) { + proc_pthread_mutex_dec(mutex); + pthread_mutex_consistent_np(mutex->os.pthread_interproc); } - - rv = pthread_mutex_unlock(&proc_pthread_mutex(mutex)); - if (rv) { -#ifdef HAVE_ZOS_PTHREADS - rv = errno; + else #endif - return rv; - } + 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 { - struct timespec abstime; - if (!absolute) { - 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) { + mutex->curr_locked = 1; + return APR_SUCCESS; +} + +static apr_status_t proc_mutex_pthread_tryacquire(apr_proc_mutex_t *mutex) +{ + apr_status_t rv; + + if ((rv = pthread_mutex_trylock(mutex->os.pthread_interproc))) { #ifdef HAVE_ZOS_PTHREADS - rv = errno; + rv = errno; #endif - if (rv == ETIMEDOUT) { - return APR_TIMEUP; - } - } + if (rv == EBUSY) { + return APR_EBUSY; } - if (rv) { #ifdef HAVE_PTHREAD_MUTEX_ROBUST - /* Okay, our owner died. Let's try to make it consistent again. */ - if (rv == EOWNERDEAD) { - proc_pthread_mutex_dec(mutex); - pthread_mutex_consistent_np(&proc_pthread_mutex(mutex)); - } - else -#endif - return rv; + /* Okay, our owner died. Let's try to make it consistent again. */ + if (rv == EOWNERDEAD) { + proc_pthread_mutex_dec(mutex); + pthread_mutex_consistent_np(mutex->os.pthread_interproc); } + else +#endif + return rv; } - mutex->curr_locked = 1; return APR_SUCCESS; -#endif } -static apr_status_t proc_mutex_pthread_release(apr_proc_mutex_t *mutex) +static apr_status_t proc_mutex_pthread_timedacquire(apr_proc_mutex_t *mutex, + apr_time_t timeout, + int absolute) { - apr_status_t rv; +#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK +extern int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abs_timeout); +#endif + if (timeout < 0) { + return proc_mutex_pthread_acquire(mutex); + } + else { + apr_status_t rv; + struct timespec abstime; -#if APR_USE_PROC_PTHREAD_MUTEX_COND - if (proc_pthread_mutex_cond_locked(mutex) != -1) { - if ((rv = pthread_mutex_lock(&proc_pthread_mutex(mutex)))) { + if (!absolute) { + timeout += apr_time_now(); + } + abstime.tv_sec = apr_time_sec(timeout); + abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */ + + if ((rv = pthread_mutex_timedlock(mutex->os.pthread_interproc, + &abstime))) { #ifdef HAVE_ZOS_PTHREADS rv = errno; #endif + if (rv == ETIMEDOUT) { + return APR_TIMEUP; + } #ifdef HAVE_PTHREAD_MUTEX_ROBUST /* Okay, our owner died. Let's try to make it consistent again. */ if (rv == EOWNERDEAD) { proc_pthread_mutex_dec(mutex); - pthread_mutex_consistent_np(&proc_pthread_mutex(mutex)); + pthread_mutex_consistent_np(mutex->os.pthread_interproc); } else #endif return rv; } - - if (!proc_pthread_mutex_cond_locked(mutex)) { - rv = APR_EINVAL; - } - else if (proc_pthread_mutex_cond_num_waiters(mutex)) { - rv = pthread_cond_signal(&proc_pthread_mutex_cond(mutex)); - if (rv) { -#ifdef HAVE_ZOS_PTHREADS - rv = errno; -#endif - } - } - else { - proc_pthread_mutex_cond_locked(mutex) = 0; - rv = APR_SUCCESS; - } - if (rv) { - pthread_mutex_unlock(&proc_pthread_mutex(mutex)); - return rv; - } - } -#endif /* APR_USE_PROC_PTHREAD_MUTEX_COND */ - - mutex->curr_locked = 0; - if ((rv = pthread_mutex_unlock(&proc_pthread_mutex(mutex)))) { -#ifdef HAVE_ZOS_PTHREADS - rv = errno; -#endif - return rv; } - + mutex->curr_locked = 1; return APR_SUCCESS; } -static const apr_proc_mutex_unix_lock_methods_t mutex_proc_pthread_methods = -{ - APR_PROCESS_LOCK_MECH_IS_GLOBAL, - proc_mutex_pthread_create, - proc_mutex_pthread_acquire, - proc_mutex_pthread_tryacquire, - proc_mutex_pthread_timedacquire, - proc_mutex_pthread_release, - proc_mutex_pthread_cleanup, - proc_mutex_pthread_child_init, - proc_mutex_no_perms_set, - APR_LOCK_PROC_PTHREAD, - "pthread" -}; - -#if APR_USE_PROC_PTHREAD_MUTEX_COND -static apr_status_t proc_mutex_pthread_cond_create(apr_proc_mutex_t *new_mutex, - const char *fname) +static apr_status_t proc_mutex_pthread_release(apr_proc_mutex_t *mutex) { apr_status_t rv; - pthread_condattr_t cattr; - - rv = proc_mutex_pthread_create(new_mutex, fname); - if (rv != APR_SUCCESS) { - return rv; - } - if ((rv = pthread_condattr_init(&cattr))) { -#ifdef HAVE_ZOS_PTHREADS - rv = errno; -#endif - apr_pool_cleanup_run(new_mutex->pool, new_mutex, - apr_proc_mutex_cleanup); - return rv; - } - if ((rv = pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED))) { -#ifdef HAVE_ZOS_PTHREADS - rv = errno; -#endif - pthread_condattr_destroy(&cattr); - apr_pool_cleanup_run(new_mutex->pool, new_mutex, - apr_proc_mutex_cleanup); - return rv; - } - if ((rv = pthread_cond_init(&proc_pthread_mutex_cond(new_mutex), - &cattr))) { + mutex->curr_locked = 0; + if ((rv = pthread_mutex_unlock(mutex->os.pthread_interproc))) { #ifdef HAVE_ZOS_PTHREADS rv = errno; #endif - pthread_condattr_destroy(&cattr); - apr_pool_cleanup_run(new_mutex->pool, new_mutex, - apr_proc_mutex_cleanup); return rv; } - pthread_condattr_destroy(&cattr); - - proc_pthread_mutex_cond_locked(new_mutex) = 0; - proc_pthread_mutex_cond_num_waiters(new_mutex) = 0; - return APR_SUCCESS; } -static const apr_proc_mutex_unix_lock_methods_t mutex_proc_pthread_cond_methods = +static const apr_proc_mutex_unix_lock_methods_t mutex_proc_pthread_methods = { APR_PROCESS_LOCK_MECH_IS_GLOBAL, - proc_mutex_pthread_cond_create, + proc_mutex_pthread_create, proc_mutex_pthread_acquire, proc_mutex_pthread_tryacquire, proc_mutex_pthread_timedacquire, @@ -979,7 +720,6 @@ static const apr_proc_mutex_unix_lock_methods_t mutex_proc_pthread_cond_methods APR_LOCK_PROC_PTHREAD, "pthread" }; -#endif #endif @@ -1096,6 +836,13 @@ static apr_status_t proc_mutex_fcntl_tryacquire(apr_proc_mutex_t *mutex) return APR_SUCCESS; } +static apr_status_t proc_mutex_fcntl_timedacquire(apr_proc_mutex_t *mutex, + apr_time_t timeout, + int absolute) +{ + return APR_ENOTIMPL; +} + static apr_status_t proc_mutex_fcntl_release(apr_proc_mutex_t *mutex) { int rc; @@ -1136,7 +883,7 @@ static const apr_proc_mutex_unix_lock_methods_t mutex_fcntl_methods = proc_mutex_fcntl_create, proc_mutex_fcntl_acquire, proc_mutex_fcntl_tryacquire, - proc_mutex_spinsleep_timedacquire, + proc_mutex_fcntl_timedacquire, proc_mutex_fcntl_release, proc_mutex_fcntl_cleanup, proc_mutex_no_child_init, @@ -1240,6 +987,13 @@ static apr_status_t proc_mutex_flock_tryacquire(apr_proc_mutex_t *mutex) return APR_SUCCESS; } +static apr_status_t proc_mutex_flock_timedacquire(apr_proc_mutex_t *mutex, + apr_time_t timeout, + int absolute) +{ + return APR_ENOTIMPL; +} + static apr_status_t proc_mutex_flock_release(apr_proc_mutex_t *mutex) { int rc; @@ -1310,7 +1064,7 @@ static const apr_proc_mutex_unix_lock_methods_t mutex_flock_methods = proc_mutex_flock_create, proc_mutex_flock_acquire, proc_mutex_flock_tryacquire, - proc_mutex_spinsleep_timedacquire, + proc_mutex_flock_timedacquire, proc_mutex_flock_release, proc_mutex_flock_cleanup, proc_mutex_flock_child_init, @@ -1417,43 +1171,6 @@ static apr_status_t proc_mutex_choose_method(apr_proc_mutex_t *new_mutex, return APR_ENOTIMPL; #endif break; - case APR_LOCK_DEFAULT_TIMED: -#if APR_HAS_PROC_PTHREAD_SERIALIZE \ - && (APR_USE_PROC_PTHREAD_MUTEX_COND \ - || defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK)) \ - && defined(HAVE_PTHREAD_MUTEX_ROBUST) -#if APR_USE_PROC_PTHREAD_MUTEX_COND - new_mutex->meth = &mutex_proc_pthread_cond_methods; -#else - new_mutex->meth = &mutex_proc_pthread_methods; -#endif - if (ospmutex) { - if (ospmutex->pthread_interproc == NULL) { - return APR_EINVAL; - } - new_mutex->os.pthread_interproc = ospmutex->pthread_interproc; - } - break; -#elif APR_HAS_SYSVSEM_SERIALIZE && defined(HAVE_SEMTIMEDOP) - new_mutex->meth = &mutex_sysv_methods; - if (ospmutex) { - if (ospmutex->crossproc == -1) { - return APR_EINVAL; - } - new_mutex->os.crossproc = ospmutex->crossproc; - } - break; -#elif APR_HAS_POSIXSEM_SERIALIZE && defined(HAVE_SEM_TIMEDWAIT) - new_mutex->meth = &mutex_posixsem_methods; - if (ospmutex) { - if (ospmutex->psem_interproc == NULL) { - return APR_EINVAL; - } - new_mutex->os.psem_interproc = ospmutex->psem_interproc; - } - break; -#endif - /* fall trough */ case APR_LOCK_DEFAULT: #if APR_USE_FLOCK_SERIALIZE new_mutex->meth = &mutex_flock_methods; @@ -1499,6 +1216,18 @@ static apr_status_t proc_mutex_choose_method(apr_proc_mutex_t *new_mutex, return APR_ENOTIMPL; #endif break; + case APR_LOCK_DEFAULT_TIMED: +#if APR_HAS_PROC_PTHREAD_SERIALIZE \ + && defined(HAVE_PTHREAD_MUTEX_ROBUST) + new_mutex->meth = &mutex_proc_pthread_methods; +#elif APR_HAS_SYSVSEM_SERIALIZE + new_mutex->meth = &mutex_sysv_methods; +#elif APR_HAS_POSIXSEM_SERIALIZE + new_mutex->meth = &mutex_posixsem_methods; +#else + return APR_ENOTIMPL; +#endif + break; default: return APR_ENOTIMPL; } diff --git a/locks/unix/thread_mutex.c b/locks/unix/thread_mutex.c index fe515b2e6..5c6716658 100644 --- a/locks/unix/thread_mutex.c +++ b/locks/unix/thread_mutex.c @@ -77,19 +77,6 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex, return rv; } -#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK - if (flags & APR_THREAD_MUTEX_TIMED) { - rv = apr_thread_cond_create(&new_mutex->cond, pool); - if (rv) { -#ifdef HAVE_ZOS_PTHREADS - rv = errno; -#endif - pthread_mutex_destroy(&new_mutex->mutex); - return rv; - } - } -#endif - apr_pool_cleanup_register(new_mutex->pool, new_mutex, thread_mutex_cleanup, apr_pool_cleanup_null); @@ -195,7 +182,10 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex, { apr_status_t rv = APR_ENOTIMPL; -#ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK +#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK +extern int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abs_timeout); +#endif + if (timeout < 0) { rv = pthread_mutex_lock(&mutex->mutex); if (rv) { @@ -223,55 +213,6 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex, } } } - -#else /* HAVE_PTHREAD_MUTEX_TIMEDLOCK */ - - if (mutex->cond) { - apr_status_t rv2; - - rv = pthread_mutex_lock(&mutex->mutex); - if (rv) { -#ifdef HAVE_ZOS_PTHREADS - rv = errno; -#endif - return rv; - } - - if (mutex->locked) { - mutex->num_waiters++; - if (timeout < 0) { - rv = apr_thread_cond_wait(mutex->cond, mutex); - } - else { - if (absolute) { - apr_time_t now = apr_time_now(); - if (timeout > now) { - timeout -= now; - } - else { - timeout = 0; - } - } - rv = apr_thread_cond_timedwait(mutex->cond, mutex, timeout); - } - mutex->num_waiters--; - } - else { - mutex->locked = 1; - } - - rv2 = pthread_mutex_unlock(&mutex->mutex); - if (rv2 && !rv) { -#ifdef HAVE_ZOS_PTHREADS - rv = errno; -#else - rv = rv2; -#endif - } - } - -#endif /* HAVE_PTHREAD_MUTEX_TIMEDLOCK */ - return rv; } diff --git a/test/testprocmutex.c b/test/testprocmutex.c index 3aff25b88..599d58520 100644 --- a/test/testprocmutex.c +++ b/test/testprocmutex.c @@ -20,7 +20,6 @@ #include "apr_proc_mutex.h" #include "apr_errno.h" #include "apr_general.h" -#include "apr_strings.h" #include "apr_getopt.h" #include <stdio.h> #include <stdlib.h> @@ -156,19 +155,6 @@ static void test_exclusive(abts_case *tc, const char *lockname, else { APR_ASSERT_SUCCESS(tc, "check for trylock", rv); - for (n = 0; n < 2; n++) { - rv = apr_proc_mutex_trylock(proc_lock); - /* Some mech (eg. flock or fcntl) may succeed when the - * lock is re-acquired in the same process. - */ - if (rv != APR_SUCCESS) { - ABTS_ASSERT(tc, - apr_psprintf(p, "%s_trylock() should be busy => %pm", - mech->name, &rv), - APR_STATUS_IS_EBUSY(rv)); - } - } - rv = apr_proc_mutex_unlock(proc_lock); APR_ASSERT_SUCCESS(tc, "unlock after trylock check", rv); @@ -193,19 +179,6 @@ static void test_exclusive(abts_case *tc, const char *lockname, else { APR_ASSERT_SUCCESS(tc, "check for timedlock", rv); - for (n = 0; n < 2; n++) { - rv = apr_proc_mutex_timedlock(proc_lock, 1, 0); - /* Some mech (eg. flock or fcntl) may succeed when the - * lock is re-acquired in the same process. - */ - if (rv != APR_SUCCESS) { - ABTS_ASSERT(tc, - apr_psprintf(p, "%s_timedlock() should time out => %pm", - mech->name, &rv), - APR_STATUS_IS_TIMEUP(rv)); - } - } - rv = apr_proc_mutex_unlock(proc_lock); APR_ASSERT_SUCCESS(tc, "unlock after timedlock check", rv); |