summaryrefslogtreecommitdiff
path: root/locks
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2016-03-05 01:40:58 +0000
committerYann Ylavic <ylavic@apache.org>2016-03-05 01:40:58 +0000
commite547c8577920802132994329ca50a554571fd308 (patch)
tree893502b6a98b9a3eb26821534f45db589cf0c67e /locks
parent878278c3c98ab6c43ed645fef25d116dde16f22c (diff)
downloadapr-e547c8577920802132994329ca50a554571fd308.tar.gz
Merge r930508, r1667900, r1667901, r1667903, r1667962, r1669077, r1671292, r1732582 from trunk:
OS/2: Add an implementation of condition variables, derived from the Win32 implementation. locks: introduce apr_{thread,proc,global}_mutex_timedlock(). For proc mutexes, the new mechanism APR_LOCK_DEFAULT_TIMED usable at creation time allows for the best mechanism to be elected (unixes: 1 to 3, or specific: 4 to 7): 1. PROC_PTHREAD if pthread_mutex_timedlock() and pthread_mutex_set_robust_np() are both available, 2. SYSV if semtimedop() is availale, 3. POSIXSEM if sem_timedwait() is available, 4. BeOS' acquire_sem_etc() if available, 5. NetWare falls back to apr_thread_mutex_timedlock() as for others functions, 6. OS2's DosRequestMutexSem(), 7. Windows' WaitForSingleObject(). Otherwise (like when fcntl and flock only are availble, if that's ever possible), APR_ENOTIMPL is returned. For thread mutexes, the new flag APR_THREAD_MUTEX_TIMED, usable at create() time still, allows to switch to an implementation using a condition variable and apr_thread_cond_timedwait() when if no native mechanism is available (eg. NetWare, pthreads but without pthread_mutex_timedlock() available). On windows, this initializes a WaitForSingleObject()able handle (Mutex) instead of the fastest (but not timeout-able) CRITICAL_SECTION used by default. All apr_{thread,proc,global}_mutex_timedlock() functions can take a relative or absolute time, thanks to the last (boolean) argument. Test suite updated accordingly. Follow up to r1667900: revert spurious change on test/abts_tests.h. Follow up to r1667900: fix comments. Follow up to r1667900: handle negative (infinite) timeout in mutex/cond timedlock/timedwait. locks: follow up to r1667900. In apr_global_mutex_timedlock(), we can avoid converting from relative to absolute time if thread locking is not needed. make internal function static to avoid a warning Follow up to r1667900: Avoid a circular reference (PR 59068). Submitted by: bjh, ylavic, ylavic, ylavic, ylavic, ylavic, trawick, ylavic Reviewed/backported by: ylavic git-svn-id: https://svn.apache.org/repos/asf/apr/apr/branches/1.6.x@1733684 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'locks')
-rw-r--r--locks/beos/proc_mutex.c82
-rw-r--r--locks/beos/thread_cond.c2
-rw-r--r--locks/beos/thread_mutex.c99
-rw-r--r--locks/netware/proc_mutex.c26
-rw-r--r--locks/netware/thread_cond.c19
-rw-r--r--locks/netware/thread_mutex.c109
-rw-r--r--locks/os2/proc_mutex.c38
-rw-r--r--locks/os2/thread_cond.c150
-rw-r--r--locks/os2/thread_mutex.c30
-rw-r--r--locks/unix/global_mutex.c34
-rw-r--r--locks/unix/proc_mutex.c155
-rw-r--r--locks/unix/thread_cond.c32
-rw-r--r--locks/unix/thread_mutex.c209
-rw-r--r--locks/win32/proc_mutex.c31
-rw-r--r--locks/win32/thread_cond.c13
-rw-r--r--locks/win32/thread_mutex.c44
16 files changed, 995 insertions, 78 deletions
diff --git a/locks/beos/proc_mutex.c b/locks/beos/proc_mutex.c
index a02668add..4408df094 100644
--- a/locks/beos/proc_mutex.c
+++ b/locks/beos/proc_mutex.c
@@ -27,13 +27,13 @@ static apr_status_t _proc_mutex_cleanup(void * data)
apr_proc_mutex_t *lock = (apr_proc_mutex_t*)data;
if (lock->LockCount != 0) {
/* we're still locked... */
- while (atomic_add(&lock->LockCount , -1) > 1){
- /* OK we had more than one person waiting on the lock so
- * the sem is also locked. Release it until we have no more
- * locks left.
- */
+ while (atomic_add(&lock->LockCount , -1) > 1){
+ /* OK we had more than one person waiting on the lock so
+ * the sem is also locked. Release it until we have no more
+ * locks left.
+ */
release_sem (lock->Lock);
- }
+ }
}
delete_sem(lock->Lock);
return APR_SUCCESS;
@@ -47,7 +47,7 @@ APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex,
apr_proc_mutex_t *new;
apr_status_t stat = APR_SUCCESS;
- if (mech != APR_LOCK_DEFAULT) {
+ if (mech != APR_LOCK_DEFAULT && mech != APR_LOCK_DEFAULT_TIMED) {
return APR_ENOTIMPL;
}
@@ -82,25 +82,77 @@ APR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex)
{
int32 stat;
- if (atomic_add(&mutex->LockCount, 1) > 0) {
- if ((stat = acquire_sem(mutex->Lock)) < B_NO_ERROR) {
- atomic_add(&mutex->LockCount, -1);
- return stat;
- }
- }
+ if (atomic_add(&mutex->LockCount, 1) > 0) {
+ if ((stat = acquire_sem(mutex->Lock)) < B_NO_ERROR) {
+ atomic_add(&mutex->LockCount, -1);
+ return stat;
+ }
+ }
return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex)
{
- return APR_ENOTIMPL;
+ int32 stat;
+
+ if (atomic_add(&mutex->LockCount, 1) > 0) {
+ stat = acquire_sem_etc(mutex->Lock, 1, 0, 0);
+ if (stat < B_NO_ERROR) {
+ atomic_add(&mutex->LockCount, -1);
+ if (stat == B_WOULD_BLOCK) {
+ stat = APR_EBUSY;
+ }
+ return stat;
+ }
+ }
+ return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_mutex_timedlock(apr_proc_mutex_t *mutex,
+ apr_time_t timeout,
+ int absolute)
+{
+ int32 stat;
+
+ if (atomic_add(&mutex->LockCount, 1) > 0) {
+ if (timeout < 0) {
+ stat = acquire_sem(mutex->Lock);
+ }
+ else {
+ int flag = 0;
+ if (timeout > 0) {
+ if (absolute) {
+ apr_time_t now = apr_time_now();
+ if (timeout > now) {
+ timeout -= now;
+ }
+ else {
+ timeout = 0;
+ }
+ flag = B_ABSOLUTE_TIMEOUT;
+ }
+ else {
+ flag = B_RELATIVE_TIMEOUT;
+ }
+ }
+ stat = acquire_sem_etc(mutex->Lock, 1, flag, timeout);
+ }
+ if (stat < B_NO_ERROR) {
+ atomic_add(&mutex->LockCount, -1);
+ if (stat == B_TIMED_OUT) {
+ stat = APR_TIMEUP;
+ }
+ return stat;
+ }
+ }
+ return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex)
{
int32 stat;
- if (atomic_add(&mutex->LockCount, -1) > 1) {
+ if (atomic_add(&mutex->LockCount, -1) > 1) {
if ((stat = release_sem(mutex->Lock)) < B_NO_ERROR) {
atomic_add(&mutex->LockCount, 1);
return stat;
diff --git a/locks/beos/thread_cond.c b/locks/beos/thread_cond.c
index 44189d908..a0978c008 100644
--- a/locks/beos/thread_cond.c
+++ b/locks/beos/thread_cond.c
@@ -81,7 +81,7 @@ APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond,
static apr_status_t do_wait(apr_thread_cond_t *cond, apr_thread_mutex_t *mutex,
- int timeout)
+ apr_interval_time_t timeout)
{
struct waiter_t *wait;
thread_id cth = find_thread(NULL);
diff --git a/locks/beos/thread_mutex.c b/locks/beos/thread_mutex.c
index b87f76606..2fa1bc70b 100644
--- a/locks/beos/thread_mutex.c
+++ b/locks/beos/thread_mutex.c
@@ -27,13 +27,13 @@ static apr_status_t _thread_mutex_cleanup(void * data)
apr_thread_mutex_t *lock = (apr_thread_mutex_t*)data;
if (lock->LockCount != 0) {
/* we're still locked... */
- while (atomic_add(&lock->LockCount , -1) > 1){
- /* OK we had more than one person waiting on the lock so
- * the sem is also locked. Release it until we have no more
- * locks left.
- */
+ while (atomic_add(&lock->LockCount , -1) > 1){
+ /* OK we had more than one person waiting on the lock so
+ * the sem is also locked. Release it until we have no more
+ * locks left.
+ */
release_sem (lock->Lock);
- }
+ }
}
delete_sem(lock->Lock);
return APR_SUCCESS;
@@ -91,13 +91,13 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex)
return APR_SUCCESS;
}
- if (atomic_add(&mutex->LockCount, 1) > 0) {
- if ((stat = acquire_sem(mutex->Lock)) < B_NO_ERROR) {
+ if (atomic_add(&mutex->LockCount, 1) > 0) {
+ if ((stat = acquire_sem(mutex->Lock)) < B_NO_ERROR) {
/* Oh dear, acquire_sem failed!! */
- atomic_add(&mutex->LockCount, -1);
- return stat;
- }
- }
+ atomic_add(&mutex->LockCount, -1);
+ return stat;
+ }
+ }
mutex->owner = me;
mutex->owner_ref = 1;
@@ -107,7 +107,78 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex)
APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex)
{
- return APR_ENOTIMPL;
+ int32 stat;
+ thread_id me = find_thread(NULL);
+
+ if (mutex->nested && mutex->owner == me) {
+ mutex->owner_ref++;
+ return APR_SUCCESS;
+ }
+
+ if (atomic_add(&mutex->LockCount, 1) > 0) {
+ if ((stat = acquire_sem_etc(mutex->Lock, 1, 0, 0)) < B_NO_ERROR) {
+ atomic_add(&mutex->LockCount, -1);
+ if (stat == B_WOULD_BLOCK) {
+ stat = APR_EBUSY;
+ }
+ return stat;
+ }
+ }
+
+ mutex->owner = me;
+ mutex->owner_ref = 1;
+
+ return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex,
+ apr_time_t timeout,
+ int absolute)
+{
+ int32 stat;
+ thread_id me = find_thread(NULL);
+
+ if (mutex->nested && mutex->owner == me) {
+ mutex->owner_ref++;
+ return APR_SUCCESS;
+ }
+
+ if (atomic_add(&mutex->LockCount, 1) > 0) {
+ if (timeout < 0) {
+ stat = acquire_sem(mutex->Lock);
+ }
+ else {
+ int flag = 0;
+ if (timeout > 0) {
+ if (absolute) {
+ apr_time_t now = apr_time_now();
+ if (timeout > now) {
+ timeout -= now;
+ }
+ else {
+ timeout = 0;
+ }
+ flag = B_ABSOLUTE_TIMEOUT;
+ }
+ else {
+ flag = B_RELATIVE_TIMEOUT;
+ }
+ }
+ stat = acquire_sem_etc(mutex->Lock, 1, flag, timeout);
+ }
+ if (stat < B_NO_ERROR) {
+ atomic_add(&mutex->LockCount, -1);
+ if (stat == B_TIMED_OUT) {
+ stat = APR_TIMEUP;
+ }
+ return stat;
+ }
+ }
+
+ mutex->owner = me;
+ mutex->owner_ref = 1;
+
+ return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex)
@@ -120,7 +191,7 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex)
return APR_SUCCESS;
}
- if (atomic_add(&mutex->LockCount, -1) > 1) {
+ if (atomic_add(&mutex->LockCount, -1) > 1) {
if ((stat = release_sem(mutex->Lock)) < B_NO_ERROR) {
atomic_add(&mutex->LockCount, 1);
return stat;
diff --git a/locks/netware/proc_mutex.c b/locks/netware/proc_mutex.c
index 097914645..4217b1cf0 100644
--- a/locks/netware/proc_mutex.c
+++ b/locks/netware/proc_mutex.c
@@ -26,15 +26,24 @@ APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex,
apr_pool_t *pool)
{
apr_status_t ret;
- apr_proc_mutex_t *new_mutex = NULL;
+ apr_proc_mutex_t *new_mutex;
+ unsigned int flags = APR_THREAD_MUTEX_DEFAULT;
+
+ *mutex = NULL;
+ if (mech == APR_LOCK_DEFAULT_TIMED) {
+ flags |= APR_THREAD_MUTEX_TIMED;
+ }
+ else if (mech != APR_LOCK_DEFAULT) {
+ return APR_ENOTIMPL;
+ }
+
new_mutex = (apr_proc_mutex_t *)apr_pcalloc(pool, sizeof(apr_proc_mutex_t));
-
- if(new_mutex ==NULL) {
+ if (new_mutex == NULL) {
return APR_ENOMEM;
}
new_mutex->pool = pool;
- ret = apr_thread_mutex_create(&(new_mutex->mutex), APR_THREAD_MUTEX_DEFAULT, pool);
+ ret = apr_thread_mutex_create(&(new_mutex->mutex), flags, pool);
if (ret == APR_SUCCESS)
*mutex = new_mutex;
@@ -63,6 +72,15 @@ APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex)
return APR_ENOLOCK;
}
+APR_DECLARE(apr_status_t) apr_proc_mutex_timedlock(apr_thread_mutex_t *mutex,
+ apr_time_t timeout,
+ int absolute)
+{
+ if (mutex)
+ return apr_thread_mutex_timedlock(mutex->mutex, timeout, absolute);
+ return APR_ENOLOCK;
+}
+
APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex)
{
if (mutex)
diff --git a/locks/netware/thread_cond.c b/locks/netware/thread_cond.c
index dcb21edc9..da1162bc2 100644
--- a/locks/netware/thread_cond.c
+++ b/locks/netware/thread_cond.c
@@ -66,10 +66,21 @@ APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond,
APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond,
apr_thread_mutex_t *mutex,
- apr_interval_time_t timeout){
- if (NXCondTimedWait(cond->cond, mutex->mutex,
- (timeout*1000)/NXGetSystemTick()) == NX_ETIMEDOUT) {
- return APR_TIMEUP;
+ apr_interval_time_t timeout)
+{
+ int rc;
+ if (timeout < 0) {
+ rc = NXCondWait(cond->cond, mutex->mutex);
+ }
+ else {
+ timeout = timeout * 1000 / XGetSystemTick();
+ rc = NXCondTimedWait(cond->cond, mutex->mutex, timeout);
+ if (rc == NX_ETIMEDOUT) {
+ return APR_TIMEUP;
+ }
+ }
+ if (rc != 0) {
+ return APR_EINTR;
}
return APR_SUCCESS;
}
diff --git a/locks/netware/thread_mutex.c b/locks/netware/thread_mutex.c
index 98bf33bd2..a11ad8345 100644
--- a/locks/netware/thread_mutex.c
+++ b/locks/netware/thread_mutex.c
@@ -19,6 +19,7 @@
#include "apr_general.h"
#include "apr_strings.h"
#include "apr_arch_thread_mutex.h"
+#include "apr_thread_cond.h"
#include "apr_portable.h"
static apr_status_t thread_mutex_cleanup(void *data)
@@ -41,8 +42,8 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex,
return APR_ENOTIMPL;
}
new_mutex = (apr_thread_mutex_t *)apr_pcalloc(pool, sizeof(apr_thread_mutex_t));
-
- if(new_mutex ==NULL) {
+
+ if (new_mutex == NULL) {
return APR_ENOMEM;
}
new_mutex->pool = pool;
@@ -52,6 +53,14 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex,
if(new_mutex->mutex == NULL)
return APR_ENOMEM;
+ if (flags & APR_THREAD_MUTEX_TIMED) {
+ apr_status_t rv = apr_thread_cond_create(&new_mutex->cond, pool);
+ if (rv != SUCCESS) {
+ NXMutexFree(new_mutex->mutex);
+ return rv;
+ }
+ }
+
apr_pool_cleanup_register(new_mutex->pool, new_mutex,
(void*)thread_mutex_cleanup,
apr_pool_cleanup_null);
@@ -61,29 +70,117 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex,
APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex)
{
+ if (mutex->cond) {
+ apr_status_t rv;
+ NXLock(mutex->mutex);
+ if (mutex->locked) {
+ mutex->num_waiters++;
+ rv = apr_thread_cond_wait(mutex->cond, mutex);
+ mutex->num_waiters--;
+ }
+ else {
+ mutex->locked = 1;
+ rv = APR_SUCCESS;
+ }
+ NXUnlock(mutex->mutex);
+ return rv;
+ }
+
NXLock(mutex->mutex);
return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex)
{
+ if (mutex->cond) {
+ apr_status_t rv;
+ NXLock(mutex->mutex);
+ if (mutex->locked) {
+ rv = APR_EBUSY;
+ }
+ else {
+ mutex->locked = 1;
+ rv = APR_SUCCESS;
+ }
+ NXUnlock(mutex->mutex);
+ return rv;
+ }
+
if (!NXTryLock(mutex->mutex))
return APR_EBUSY;
return APR_SUCCESS;
}
+APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex,
+ apr_time_t timeout,
+ int absolute)
+{
+ if (mutex->cond) {
+ apr_status_t rv;
+ NXLock(mutex->mutex);
+ if (mutex->locked) {
+ mutex->num_waiters++;
+ if (timeout < 0) {
+ rv = apr_thread_cond_dwait(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;
+ rv = APR_SUCCESS;
+ }
+ NXUnlock(mutex->mutex);
+ return rv;
+ }
+
+ return APR_ENOTIMPL;
+}
+
APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex)
{
+ if (mutex->cond) {
+ apr_status_t rv;
+ NXLock(mutex->mutex);
+ if (!mutex->locked) {
+ rv = APR_EINVAL;
+ }
+ else if (mutex->num_waiters) {
+ rv = apr_thread_cond_signal(mutex->cond);
+ }
+ else {
+ mutex->locked = 0;
+ rv = APR_SUCCESS;
+ }
+ NXUnlock(mutex->mutex);
+ return rv;
+ }
+
NXUnlock(mutex->mutex);
return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_thread_mutex_destroy(apr_thread_mutex_t *mutex)
{
- apr_status_t stat;
- if ((stat = thread_mutex_cleanup(mutex)) == APR_SUCCESS) {
- apr_pool_cleanup_kill(mutex->pool, mutex, thread_mutex_cleanup);
- return APR_SUCCESS;
+ apr_status_t stat, rv = APR_SUCCESS;
+ if (mutex->cond) {
+ rv = apr_thread_cond_destroy(mutex->cond);
+ mutex->cond = NULL;
+ }
+ stat = apr_pool_cleanup_run(mutex->pool, mutex, thread_mutex_cleanup);
+ if (stat == APR_SUCCESS && rv) {
+ stat = rv;
}
return stat;
}
diff --git a/locks/os2/proc_mutex.c b/locks/os2/proc_mutex.c
index 9b53c0bef..e873963f2 100644
--- a/locks/os2/proc_mutex.c
+++ b/locks/os2/proc_mutex.c
@@ -80,7 +80,7 @@ APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex,
ULONG rc;
char *semname;
- if (mech != APR_LOCK_DEFAULT) {
+ if (mech != APR_LOCK_DEFAULT && mech != APR_LOCK_DEFAULT_TIMED) {
return APR_ENOTIMPL;
}
@@ -156,6 +156,42 @@ APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex)
+APR_DECLARE(apr_status_t) apr_proc_mutex_timedlock(apr_proc_mutex_t *mutex,
+ apr_time_t timeout,
+ int absolute)
+{
+ ULONG rc;
+
+ if (timeout < 0) {
+ rc = DosRequestMutexSem(mutex->hMutex, SEM_INDEFINITE_WAIT);
+ }
+ else {
+ if (absolute) {
+ apr_time_t now = apr_time_now();
+ if (timeout > now) {
+ timeout -= now;
+ }
+ else {
+ timeout = 0;
+ }
+ }
+
+ rc = DosRequestMutexSem(mutex->hMutex, apr_time_as_msec(timeout));
+ if (rc == ERROR_TIMEOUT) {
+ return APR_TIMEUP;
+ }
+ }
+
+ if (rc == 0) {
+ mutex->owner = CurrentTid;
+ mutex->lock_count++;
+ }
+
+ return APR_FROM_OS_ERROR(rc);
+}
+
+
+
APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex)
{
ULONG rc;
diff --git a/locks/os2/thread_cond.c b/locks/os2/thread_cond.c
index ec6034f55..1b8698e7a 100644
--- a/locks/os2/thread_cond.c
+++ b/locks/os2/thread_cond.c
@@ -23,38 +23,172 @@
#include "apr_arch_file_io.h"
#include <string.h>
+#ifndef DCE_POSTONE
+#define DCE_POSTONE 0x0800 // Post one flag
+#endif
+
+static apr_status_t thread_cond_cleanup(void *data)
+{
+ apr_thread_cond_t *cv = data;
+
+ if (cv->semaphore) {
+ DosCloseEventSem(cv->semaphore);
+ }
+
+ if (cv->mutex) {
+ DosCloseMutexSem(cv->mutex);
+ }
+
+ return APR_SUCCESS;
+}
+
+
+
APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond,
apr_pool_t *pool)
{
- return APR_ENOTIMPL;
+ int rc;
+ apr_thread_cond_t *cv;
+
+ cv = apr_pcalloc(pool, sizeof(**cond));
+ rc = DosCreateEventSem(NULL, &cv->semaphore, DCE_POSTONE, FALSE);
+
+ if (rc == 0) {
+ rc = DosCreateMutexSem(NULL, &cv->mutex, 0, FALSE);
+ }
+
+ *cond = cv;
+ cv->pool = pool;
+ apr_pool_cleanup_register(cv->pool, cv, thread_cond_cleanup,
+ apr_pool_cleanup_null);
+
+ return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+static apr_status_t thread_cond_timedwait(apr_thread_cond_t *cond,
+ apr_thread_mutex_t *mutex,
+ ULONG timeout_ms )
+{
+ ULONG rc;
+ apr_status_t rv = APR_SUCCESS;
+ int wake = FALSE;
+ unsigned long generation;
+
+ DosRequestMutexSem(cond->mutex, SEM_INDEFINITE_WAIT);
+ cond->num_waiting++;
+ generation = cond->generation;
+ DosReleaseMutexSem(cond->mutex);
+
+ apr_thread_mutex_unlock(mutex);
+
+ do {
+ rc = DosWaitEventSem(cond->semaphore, timeout_ms);
+
+ DosRequestMutexSem(cond->mutex, SEM_INDEFINITE_WAIT);
+
+ if (cond->num_wake) {
+ if (cond->generation != generation) {
+ cond->num_wake--;
+ cond->num_waiting--;
+ rv = APR_SUCCESS;
+ break;
+ } else {
+ wake = TRUE;
+ }
+ }
+ else if (rc != 0) {
+ cond->num_waiting--;
+ rv = APR_TIMEUP;
+ break;
+ }
+
+ DosReleaseMutexSem(cond->mutex);
+
+ if (wake) {
+ wake = FALSE;
+ DosPostEventSem(cond->semaphore);
+ }
+ } while (1);
+
+ DosReleaseMutexSem(cond->mutex);
+ apr_thread_mutex_lock(mutex);
+ return rv;
}
+
+
APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond,
apr_thread_mutex_t *mutex)
{
- return APR_ENOTIMPL;
+ return thread_cond_timedwait(cond, mutex, SEM_INDEFINITE_WAIT);
}
+
+
APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond,
apr_thread_mutex_t *mutex,
- apr_interval_time_t timeout){
- return APR_ENOTIMPL;
+ apr_interval_time_t timeout)
+{
+ ULONG timeout_ms = (timeout >= 0) ? apr_time_as_msec(timeout)
+ : SEM_INDEFINITE_WAIT;
+ return thread_cond_timedwait(cond, mutex, timeout_ms);
}
+
+
APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond)
{
- return APR_ENOTIMPL;
+ int wake = FALSE;
+
+ DosRequestMutexSem(cond->mutex, SEM_INDEFINITE_WAIT);
+
+ if (cond->num_waiting > cond->num_wake) {
+ wake = TRUE;
+ cond->num_wake++;
+ cond->generation++;
+ }
+
+ DosReleaseMutexSem(cond->mutex);
+
+ if (wake) {
+ DosPostEventSem(cond->semaphore);
+ }
+
+ return APR_SUCCESS;
}
+
+
APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond)
{
- return APR_ENOTIMPL;
+ unsigned long num_wake = 0;
+
+ DosRequestMutexSem(cond->mutex, SEM_INDEFINITE_WAIT);
+
+ if (cond->num_waiting > cond->num_wake) {
+ num_wake = cond->num_waiting - cond->num_wake;
+ cond->num_wake = cond->num_waiting;
+ cond->generation++;
+ }
+
+ DosReleaseMutexSem(cond->mutex);
+
+ for (; num_wake; num_wake--) {
+ DosPostEventSem(cond->semaphore);
+ }
+
+ return APR_SUCCESS;
}
+
+
APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond)
{
- return APR_ENOTIMPL;
+ return apr_pool_cleanup_run(cond->pool, cond, thread_cond_cleanup);
}
-APR_POOL_IMPLEMENT_ACCESSOR(thread_cond)
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread_cond)
diff --git a/locks/os2/thread_mutex.c b/locks/os2/thread_mutex.c
index 5d8436be4..26245839d 100644
--- a/locks/os2/thread_mutex.c
+++ b/locks/os2/thread_mutex.c
@@ -71,6 +71,36 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex)
+APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex,
+ apr_time_t timeout,
+ int absolute)
+{
+ ULONG rc;
+
+ if (timeout < 0) {
+ rc = DosRequestMutexSem(mutex->hMutex, SEM_INDEFINITE_WAIT);
+ }
+ else {
+ if (absolute) {
+ apr_time_t now = apr_time_now();
+ if (timeout > now) {
+ timeout -= now;
+ }
+ else {
+ timeout = 0;
+ }
+ }
+ rc = DosRequestMutexSem(mutex->hMutex, apr_time_as_msec(usec));
+ if (rc == ERROR_TIMEOUT) {
+ return APR_TIMEUP;
+ }
+ }
+
+ return APR_FROM_OS_ERROR(rc);
+}
+
+
+
APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex)
{
ULONG rc = DosReleaseMutexSem(mutex->hMutex);
diff --git a/locks/unix/global_mutex.c b/locks/unix/global_mutex.c
index ca3b86e46..19485c487 100644
--- a/locks/unix/global_mutex.c
+++ b/locks/unix/global_mutex.c
@@ -141,6 +141,40 @@ APR_DECLARE(apr_status_t) apr_global_mutex_trylock(apr_global_mutex_t *mutex)
return rv;
}
+APR_DECLARE(apr_status_t) apr_global_mutex_timedlock(apr_global_mutex_t *mutex,
+ apr_time_t timeout,
+ int absolute)
+{
+ apr_status_t rv;
+
+#if APR_HAS_THREADS
+ if (mutex->thread_mutex) {
+ if (timeout >= 0 && !absolute) {
+ timeout += apr_time_now();
+ absolute = 1;
+ }
+ rv = apr_thread_mutex_timedlock(mutex->thread_mutex, timeout,
+ absolute);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ }
+#endif /* APR_HAS_THREADS */
+
+ rv = apr_proc_mutex_timedlock(mutex->proc_mutex, timeout,
+ absolute);
+
+#if APR_HAS_THREADS
+ if (rv != APR_SUCCESS) {
+ if (mutex->thread_mutex) {
+ (void)apr_thread_mutex_unlock(mutex->thread_mutex);
+ }
+ }
+#endif /* APR_HAS_THREADS */
+
+ return rv;
+}
+
APR_DECLARE(apr_status_t) apr_global_mutex_unlock(apr_global_mutex_t *mutex)
{
apr_status_t rv;
diff --git a/locks/unix/proc_mutex.c b/locks/unix/proc_mutex.c
index 7eff5e3f3..0a4cf180d 100644
--- a/locks/unix/proc_mutex.c
+++ b/locks/unix/proc_mutex.c
@@ -184,6 +184,41 @@ static apr_status_t proc_mutex_posix_tryacquire(apr_proc_mutex_t *mutex)
return APR_SUCCESS;
}
+static apr_status_t proc_mutex_posix_timedacquire(apr_proc_mutex_t *mutex,
+ apr_time_t timeout,
+ int absolute)
+{
+#if HAVE_SEM_TIMEDWAIT
+ if (timeout < 0) {
+ return proc_mutex_posix_acquire(mutex);
+ }
+ else {
+ int rc;
+ 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 */
+
+ do {
+ rc = sem_timedwait(mutex->psem_interproc, &abstime);
+ } while (rc < 0 && errno == EINTR);
+ if (rc < 0) {
+ if (errno == ETIMEDOUT) {
+ return APR_TIMEUP;
+ }
+ return errno;
+ }
+ }
+ mutex->curr_locked = 1;
+ return APR_SUCCESS;
+#else
+ return APR_ENOTIMPL;
+#endif
+}
+
static apr_status_t proc_mutex_posix_release(apr_proc_mutex_t *mutex)
{
mutex->curr_locked = 0;
@@ -205,6 +240,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,
+ proc_mutex_posix_timedacquire,
proc_mutex_posix_release,
proc_mutex_posix_cleanup,
proc_mutex_no_child_init,
@@ -303,6 +339,40 @@ static apr_status_t proc_mutex_sysv_tryacquire(apr_proc_mutex_t *mutex)
return APR_SUCCESS;
}
+static apr_status_t proc_mutex_sysv_timedacquire(apr_proc_mutex_t *mutex,
+ apr_time_t timeout,
+ int absolute)
+{
+#if HAVE_SEMTIMEDOP
+ if (timeout < 0) {
+ return proc_mutex_sysv_acquire(mutex);
+ }
+ else {
+ int rc;
+ 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 */
+ do {
+ rc = semtimedop(mutex->interproc->filedes, &proc_mutex_op_on, 1,
+ &abstime);
+ } while (rc < 0 && errno == EINTR);
+ if (rc < 0) {
+ if (errno == EAGAIN) {
+ return APR_TIMEUP;
+ }
+ return errno;
+ }
+ }
+ mutex->curr_locked = 1;
+ return APR_SUCCESS;
+#else
+ return APR_ENOTIMPL;
+#endif
+}
+
static apr_status_t proc_mutex_sysv_release(apr_proc_mutex_t *mutex)
{
int rc;
@@ -345,6 +415,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,
+ proc_mutex_sysv_timedacquire,
proc_mutex_sysv_release,
proc_mutex_sysv_cleanup,
proc_mutex_no_child_init,
@@ -518,7 +589,50 @@ static apr_status_t proc_mutex_proc_pthread_tryacquire(apr_proc_mutex_t *mutex)
#endif
}
mutex->curr_locked = 1;
- return rv;
+ return APR_SUCCESS;
+}
+
+static apr_status_t
+proc_mutex_proc_pthread_timedacquire(apr_proc_mutex_t *mutex,
+ apr_time_t timeout,
+ int absolute)
+{
+ if (timeout < 0) {
+ return proc_mutex_proc_pthread_acquire(mutex);
+ }
+ else {
+ apr_status_t rv;
+ 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 */
+
+ if ((rv = pthread_mutex_timedlock(mutex->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) {
+ pthread_mutex_consistent_np(mutex->pthread_interproc);
+ rv = APR_SUCCESS;
+ }
+ else
+ return rv;
+#else
+ return rv;
+#endif
+ }
+ }
+ mutex->curr_locked = 1;
+ return APR_SUCCESS;
}
static apr_status_t proc_mutex_proc_pthread_release(apr_proc_mutex_t *mutex)
@@ -541,6 +655,7 @@ static const apr_proc_mutex_unix_lock_methods_t mutex_proc_pthread_methods =
proc_mutex_proc_pthread_create,
proc_mutex_proc_pthread_acquire,
proc_mutex_proc_pthread_tryacquire,
+ proc_mutex_proc_pthread_timedacquire,
proc_mutex_proc_pthread_release,
proc_mutex_proc_pthread_cleanup,
proc_mutex_no_child_init,
@@ -652,6 +767,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;
@@ -692,6 +814,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_fcntl_timedacquire,
proc_mutex_fcntl_release,
proc_mutex_fcntl_cleanup,
proc_mutex_no_child_init,
@@ -783,6 +906,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;
@@ -847,6 +977,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_flock_timedacquire,
proc_mutex_flock_release,
proc_mutex_flock_cleanup,
proc_mutex_flock_child_init,
@@ -920,6 +1051,21 @@ static apr_status_t proc_mutex_choose_method(apr_proc_mutex_t *new_mutex, apr_lo
return APR_ENOTIMPL;
#endif
break;
+ case APR_LOCK_DEFAULT_TIMED:
+#if APR_HAS_PROC_PTHREAD_SERIALIZE \
+ && defined(HAVE_PTHREAD_MUTEX_ROBUST) \
+ && defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK)
+ new_mutex->inter_meth = &mutex_proc_pthread_methods;
+#elif APR_HAS_SYSVSEM_SERIALIZE \
+ && defined(HAVE_SEMTIMEDOP)
+ new_mutex->inter_meth = &mutex_sysv_methods;
+#elif APR_HAS_POSIXSEM_SERIALIZE \
+ && defined(HAVE_SEM_TIMEDWAIT)
+ new_mutex->inter_meth = &mutex_posixsem_methods;
+#else
+ return APR_ENOTIMPL;
+#endif
+ break;
default:
return APR_ENOTIMPL;
}
@@ -991,6 +1137,13 @@ APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex)
return mutex->meth->tryacquire(mutex);
}
+APR_DECLARE(apr_status_t) apr_proc_mutex_timedlock(apr_proc_mutex_t *mutex,
+ apr_time_t timeout,
+ int absolute)
+{
+ return mutex->meth->timedacquire(mutex, timeout, absolute);
+}
+
APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex)
{
return mutex->meth->release(mutex);
diff --git a/locks/unix/thread_cond.c b/locks/unix/thread_cond.c
index db7dd4f0d..3c8e3170a 100644
--- a/locks/unix/thread_cond.c
+++ b/locks/unix/thread_cond.c
@@ -79,21 +79,31 @@ APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond,
apr_interval_time_t timeout)
{
apr_status_t rv;
- apr_time_t then;
- struct timespec abstime;
+ if (timeout < 0) {
+ rv = pthread_cond_wait(&cond->cond, &mutex->mutex);
+#ifdef HAVE_ZOS_PTHREADS
+ if (rv) {
+ rv = errno;
+ }
+#endif
+ }
+ else {
+ apr_time_t then;
+ struct timespec abstime;
- then = apr_time_now() + timeout;
- abstime.tv_sec = apr_time_sec(then);
- abstime.tv_nsec = apr_time_usec(then) * 1000; /* nanoseconds */
+ then = apr_time_now() + timeout;
+ abstime.tv_sec = apr_time_sec(then);
+ abstime.tv_nsec = apr_time_usec(then) * 1000; /* nanoseconds */
- rv = pthread_cond_timedwait(&cond->cond, &mutex->mutex, &abstime);
+ rv = pthread_cond_timedwait(&cond->cond, &mutex->mutex, &abstime);
#ifdef HAVE_ZOS_PTHREADS
- if (rv) {
- rv = errno;
- }
+ if (rv) {
+ rv = errno;
+ }
#endif
- if (ETIMEDOUT == rv) {
- return APR_TIMEUP;
+ if (ETIMEDOUT == rv) {
+ return APR_TIMEUP;
+ }
}
return rv;
}
diff --git a/locks/unix/thread_mutex.c b/locks/unix/thread_mutex.c
index 73fd1e146..fe515b2e6 100644
--- a/locks/unix/thread_mutex.c
+++ b/locks/unix/thread_mutex.c
@@ -77,6 +77,19 @@ 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);
@@ -89,13 +102,45 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex)
{
apr_status_t rv;
+ 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++;
+ rv = apr_thread_cond_wait(mutex->cond, mutex);
+ 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
+ }
+
+ return rv;
+ }
+
rv = pthread_mutex_lock(&mutex->mutex);
#ifdef HAVE_ZOS_PTHREADS
if (rv) {
rv = errno;
}
#endif
-
+
return rv;
}
@@ -103,6 +148,36 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex)
{
apr_status_t rv;
+ 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) {
+ rv = APR_EBUSY;
+ }
+ else {
+ mutex->locked = 1;
+ }
+
+ rv2 = pthread_mutex_unlock(&mutex->mutex);
+ if (rv2) {
+#ifdef HAVE_ZOS_PTHREADS
+ rv = errno;
+#else
+ rv = rv2;
+#endif
+ }
+
+ return rv;
+ }
+
rv = pthread_mutex_trylock(&mutex->mutex);
if (rv) {
#ifdef HAVE_ZOS_PTHREADS
@@ -114,10 +189,130 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex)
return APR_SUCCESS;
}
+APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex,
+ apr_time_t timeout,
+ int absolute)
+{
+ apr_status_t rv = APR_ENOTIMPL;
+
+#ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK
+ if (timeout < 0) {
+ rv = pthread_mutex_lock(&mutex->mutex);
+ if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
+ 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_mutex_timedlock(&mutex->mutex, &abstime);
+ if (rv) {
+#ifdef HAVE_ZOS_PTHREADS
+ rv = errno;
+#endif
+ if (rv == ETIMEDOUT) {
+ rv = APR_TIMEUP;
+ }
+ }
+ }
+
+#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;
+}
+
APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex)
{
apr_status_t status;
+ if (mutex->cond) {
+ apr_status_t stat2;
+
+ status = pthread_mutex_lock(&mutex->mutex);
+ if (status) {
+#ifdef HAVE_ZOS_PTHREADS
+ status = errno;
+#endif
+ return status;
+ }
+
+ if (!mutex->locked) {
+ status = APR_EINVAL;
+ }
+ else if (mutex->num_waiters) {
+ status = apr_thread_cond_signal(mutex->cond);
+ }
+ else {
+ mutex->locked = 0;
+ status = APR_SUCCESS;
+ }
+
+ stat2 = pthread_mutex_unlock(&mutex->mutex);
+ if (stat2) {
+#ifdef HAVE_ZOS_PTHREADS
+ status = errno;
+#else
+ status = stat2;
+#endif
+ }
+
+ return status;
+ }
+
status = pthread_mutex_unlock(&mutex->mutex);
#ifdef HAVE_ZOS_PTHREADS
if (status) {
@@ -130,7 +325,17 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex)
APR_DECLARE(apr_status_t) apr_thread_mutex_destroy(apr_thread_mutex_t *mutex)
{
- return apr_pool_cleanup_run(mutex->pool, mutex, thread_mutex_cleanup);
+ apr_status_t rv, rv2 = APR_SUCCESS;
+
+ if (mutex->cond) {
+ rv2 = apr_thread_cond_destroy(mutex->cond);
+ }
+ rv = apr_pool_cleanup_run(mutex->pool, mutex, thread_mutex_cleanup);
+ if (rv == APR_SUCCESS) {
+ rv = rv2;
+ }
+
+ return rv;
}
APR_POOL_IMPLEMENT_ACCESSOR(thread_mutex)
diff --git a/locks/win32/proc_mutex.c b/locks/win32/proc_mutex.c
index 38366f185..5ec9b2648 100644
--- a/locks/win32/proc_mutex.c
+++ b/locks/win32/proc_mutex.c
@@ -160,6 +160,37 @@ APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex)
return apr_get_os_error();
}
+APR_DECLARE(apr_status_t) apr_proc_mutex_timedlock(apr_proc_mutex_t *mutex,
+ apr_time_t timeout,
+ int absolute)
+{
+ DWORD rv;
+
+ if (timeout < 0) {
+ rv = WaitForSingleObject(mutex->handle, INFINITE);
+ }
+ else {
+ if (absolute) {
+ apr_time_t now = apr_time_now();
+ if (timeout > now) {
+ timeout -= now;
+ }
+ else {
+ timeout = 0;
+ }
+ }
+ rv = WaitForSingleObject(mutex->handle, apr_time_as_msec(timeout));
+ if (rv == WAIT_TIMEOUT) {
+ return APR_TIMEUP;
+ }
+ }
+
+ if (rv == WAIT_OBJECT_0 || rv == WAIT_ABANDONED) {
+ return APR_SUCCESS;
+ }
+ return apr_get_os_error();
+}
+
APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex)
{
if (ReleaseMutex(mutex->handle) == 0) {
diff --git a/locks/win32/thread_cond.c b/locks/win32/thread_cond.c
index 60286e542..b2ac1c8ff 100644
--- a/locks/win32/thread_cond.c
+++ b/locks/win32/thread_cond.c
@@ -61,9 +61,9 @@ APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond)
return apr_pool_cleanup_run(cond->pool, cond, thread_cond_cleanup);
}
-static APR_INLINE apr_status_t _thread_cond_timedwait(apr_thread_cond_t *cond,
- apr_thread_mutex_t *mutex,
- DWORD timeout_ms )
+static APR_INLINE apr_status_t thread_cond_timedwait(apr_thread_cond_t *cond,
+ apr_thread_mutex_t *mutex,
+ DWORD timeout_ms )
{
DWORD res;
apr_status_t rv;
@@ -115,16 +115,15 @@ static APR_INLINE apr_status_t _thread_cond_timedwait(apr_thread_cond_t *cond,
APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond,
apr_thread_mutex_t *mutex)
{
- return _thread_cond_timedwait(cond, mutex, INFINITE);
+ return thread_cond_timedwait(cond, mutex, INFINITE);
}
APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond,
apr_thread_mutex_t *mutex,
apr_interval_time_t timeout)
{
- DWORD timeout_ms = (DWORD) apr_time_as_msec(timeout);
-
- return _thread_cond_timedwait(cond, mutex, timeout_ms);
+ DWORD timeout_ms = (timeout >= 0) ? apr_time_as_msec(timeout) : INFINITE;
+ return thread_cond_timedwait(cond, mutex, timeout_ms);
}
APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond)
diff --git a/locks/win32/thread_mutex.c b/locks/win32/thread_mutex.c
index 9b10d7278..cd0ccf5ba 100644
--- a/locks/win32/thread_mutex.c
+++ b/locks/win32/thread_mutex.c
@@ -54,6 +54,10 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex,
(*mutex)->type = thread_mutex_unnested_event;
(*mutex)->handle = CreateEvent(NULL, FALSE, TRUE, NULL);
}
+ else if (flags & APR_THREAD_MUTEX_TIMED) {
+ (*mutex)->type = thread_mutex_nested_mutex;
+ (*mutex)->handle = CreateMutex(NULL, FALSE, NULL);
+ }
else {
#if APR_HAS_UNICODE_FS
/* Critical Sections are terrific, performance-wise, on NT.
@@ -63,6 +67,7 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex,
IF_WIN_OS_IS_UNICODE {
InitializeCriticalSection(&(*mutex)->section);
(*mutex)->type = thread_mutex_critical_section;
+ (*mutex)->handle = NULL;
}
#endif
#if APR_HAS_ANSI_FS
@@ -86,9 +91,9 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex)
}
else {
DWORD rv = WaitForSingleObject(mutex->handle, INFINITE);
- if ((rv != WAIT_OBJECT_0) && (rv != WAIT_ABANDONED)) {
+ if ((rv != WAIT_OBJECT_0) && (rv != WAIT_ABANDONED)) {
return (rv == WAIT_TIMEOUT) ? APR_EBUSY : apr_get_os_error();
- }
+ }
}
return APR_SUCCESS;
}
@@ -102,13 +107,44 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex)
}
else {
DWORD rv = WaitForSingleObject(mutex->handle, 0);
- if ((rv != WAIT_OBJECT_0) && (rv != WAIT_ABANDONED)) {
+ if ((rv != WAIT_OBJECT_0) && (rv != WAIT_ABANDONED)) {
return (rv == WAIT_TIMEOUT) ? APR_EBUSY : apr_get_os_error();
- }
+ }
}
return APR_SUCCESS;
}
+APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex,
+ apr_time_t timeout,
+ int absolute)
+{
+ if (mutex->type != thread_mutex_critical_section) {
+ DWORD rv, timeout_ms;
+ if (timeout < 0) {
+ timeout_ms = INFINITE;
+ }
+ else {
+ if (absolute) {
+ apr_time_t now = apr_time_now();
+ if (timeout > now) {
+ timeout -= now;
+ }
+ else {
+ timeout = 0;
+ }
+ }
+ timeout_ms = apr_time_as_msec(timeout);
+ }
+ rv = WaitForSingleObject(mutex->handle, timeout_ms);
+ if ((rv != WAIT_OBJECT_0) && (rv != WAIT_ABANDONED)) {
+ return (rv == WAIT_TIMEOUT) ? APR_TIMEUP : apr_get_os_error();
+ }
+ return APR_SUCCESS;
+ }
+
+ return APR_ENOTIMPL;
+}
+
APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex)
{
if (mutex->type == thread_mutex_critical_section) {