summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam A. Rowe Jr <wrowe@apache.org>2017-05-23 18:43:15 +0000
committerWilliam A. Rowe Jr <wrowe@apache.org>2017-05-23 18:43:15 +0000
commit243be9ccfbd4ff2d78a5b163e73b7b44d431cd1b (patch)
tree0d667885fc0b74a75d0db117218fdfaaef78aa4b
parent98ac3d7b8f5ffb937e8cb329be6f85cc16ed6483 (diff)
downloadapr-243be9ccfbd4ff2d78a5b163e73b7b44d431cd1b.tar.gz
Revert 1790474 (r1790296, r1790302, r1790303, r1790304, r1790330, r1790331, r1790436, r1790439, r1790444, r1790446 from trunk), was:
Follow up to r1667900: semtimedop() should be passed a relative timeout rather then absolute. semtimedop() takes a delta time, so accept what is given as the "time remaining" rr1790301 Use our "portable" versions Make clear this is a delta timeout locks: when pthread_mutex_timedlock() isn't available, fall back to an implementation based on pthread_cond_timedwait() when possible. Avoid a compiler warning by using system's errno. locks: follow up to r1790330. When no native timedlock is available, fall back to a common/generic spin sleep proc_mutex_spinsleep_timedacquire() based on the configured APR_USE_*_SERIALIZE trylock. Otherwise, choose the best timedlock mechanism in the following order: 1. PTHREAD if HAVE_PTHREAD_MUTEX_ROBUST && (HAVE_PTHREAD_MUTEX_TIMEDLOCK || HAVE_PTHREAD_CONDATTR_SETPSHARED) 2. SYSV if HAVE_SEMTIMEDOP 3. POSIX if HAVE_SEM_TIMEDWAIT 4. The one of APR_USE_*_SERIALIZE, hence possibly non-robust and/or spinning with the same robustness as the underlying apr_proc_mutex_trylock() call. apr_proc_mutex_timedlock() won't return ENOTIMPL anymore. locks: follow up to r1790330 and r1790436. unix/misc.c is not needed anymore since we use apr_proc_mutex_trylock() directly. locks: follow up to r1790330. No functional change, more helpers/macros to help identify struct proc_pthread_mutex_t members. locks: follow up to r1790330. Don't try to access proc_pthread_mutex_t's condvar if the mutex was _put[_ex]() and not _create()d, this is a real pthread_mutex_t. Submitted by: ylavic, jim, jim, jim, ylavic, ylavic, ylavic, ylavic, ylavic, ylavic git-svn-id: https://svn.apache.org/repos/asf/apr/apr/branches/1.6.x@1795945 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--configure.in5
-rw-r--r--locks/unix/misc.c193
-rw-r--r--locks/unix/proc_mutex.c479
-rw-r--r--locks/unix/thread_mutex.c67
-rw-r--r--test/testprocmutex.c27
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);