You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by yl...@apache.org on 2016/03/05 02:40:59 UTC

svn commit: r1733684 - in /apr/apr/branches/1.6.x: ./ include/ include/arch/netware/ include/arch/os2/ include/arch/unix/ locks/beos/ locks/netware/ locks/os2/ locks/unix/ locks/win32/ test/

Author: ylavic
Date: Sat Mar  5 01:40:58 2016
New Revision: 1733684

URL: http://svn.apache.org/viewvc?rev=1733684&view=rev
Log:
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

Modified:
    apr/apr/branches/1.6.x/   (props changed)
    apr/apr/branches/1.6.x/configure.in
    apr/apr/branches/1.6.x/include/apr_global_mutex.h
    apr/apr/branches/1.6.x/include/apr_proc_mutex.h
    apr/apr/branches/1.6.x/include/apr_thread_mutex.h
    apr/apr/branches/1.6.x/include/apr_time.h
    apr/apr/branches/1.6.x/include/arch/netware/apr_arch_thread_mutex.h
    apr/apr/branches/1.6.x/include/arch/os2/apr_arch_thread_cond.h
    apr/apr/branches/1.6.x/include/arch/unix/apr_arch_proc_mutex.h
    apr/apr/branches/1.6.x/include/arch/unix/apr_arch_thread_mutex.h
    apr/apr/branches/1.6.x/locks/beos/proc_mutex.c
    apr/apr/branches/1.6.x/locks/beos/thread_cond.c
    apr/apr/branches/1.6.x/locks/beos/thread_mutex.c
    apr/apr/branches/1.6.x/locks/netware/proc_mutex.c
    apr/apr/branches/1.6.x/locks/netware/thread_cond.c
    apr/apr/branches/1.6.x/locks/netware/thread_mutex.c
    apr/apr/branches/1.6.x/locks/os2/proc_mutex.c
    apr/apr/branches/1.6.x/locks/os2/thread_cond.c
    apr/apr/branches/1.6.x/locks/os2/thread_mutex.c
    apr/apr/branches/1.6.x/locks/unix/global_mutex.c
    apr/apr/branches/1.6.x/locks/unix/proc_mutex.c
    apr/apr/branches/1.6.x/locks/unix/thread_cond.c
    apr/apr/branches/1.6.x/locks/unix/thread_mutex.c
    apr/apr/branches/1.6.x/locks/win32/proc_mutex.c
    apr/apr/branches/1.6.x/locks/win32/thread_cond.c
    apr/apr/branches/1.6.x/locks/win32/thread_mutex.c
    apr/apr/branches/1.6.x/test/testglobalmutex.c
    apr/apr/branches/1.6.x/test/testlock.c
    apr/apr/branches/1.6.x/test/testlockperf.c
    apr/apr/branches/1.6.x/test/testmutexscope.c
    apr/apr/branches/1.6.x/test/testprocmutex.c

Propchange: apr/apr/branches/1.6.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sat Mar  5 01:40:58 2016
@@ -1,4 +1,4 @@
 /apr/apr/branches/1.4.x:1003369,1101301
-/apr/apr/trunk:733052,739635,741862,741866-741867,741869,741871,745763-745764,746310,747990,748080,748361,748371,748565,748888,748902,748988,749810,760443,767895,775683,782838,783398,783958,784633,784773,788588,789050,793192-793193,794118,794485,795267,799497,800627,809745,809854,810472,811455,813063,821306,829490,831641,832904,835607,888669,892028,892159,892435,892909,896382,896653,908427,910419,910597,917819,917837-917838,925965,929796,931973,951771,960665,960671,979891,983618,989450,990435,1003338,1044440,1044447,1055657,1072165,1078845,1081462,1081495,1083038,1083242,1084662,1086695,1088023,1089031,1089129,1089438,1099348,1103310,1183683,1183685-1183686,1183688,1183693,1183698,1213382,1235047,1236970,1237078,1237507,1240472,1340286,1340288,1340470,1341193,1341196,1343233,1343243,1367050,1368819,1370494,1372018,1372022,1372093,1372849,1376957,1384764,1389077,1400200,1402868,1405985,1406690,1420106,1420109,1425356,1428809,1438940,1438957-1438959,1442903,1449568,1456418,1459994,146
 0179-1460180,1460241,1460399,1460405,1462738,1462813,1470186,1470348,1475509,1478905,1480067,1481262,1481265,1484271,1487796,1489517,1496407,1502804,1510354,1516261,1523384,1523479,1523484,1523505,1523521,1523604,1523613,1523615,1523844-1523845,1523853,1524014,1524031,1528797,1528809,1529488,1529495,1529515,1529521,1529668,1530786,1530800,1530988,1531554,1531768,1531884,1532022,1533104,1533111,1533979,1535027,1535157,1536744,1538171,1539374,1539389,1539455,1539603,1541054,1541061,1541486,1541655,1541666,1541744,1542601,1542779,1543033,1543056,1548575,1550907,1551650,1551659,1558905,1559382,1559873,1559975,1561040,1561260,1561265,1561321,1561347,1561356,1561361,1561394,1561555,1571894,1575509,1578420,1587045,1587063,1587543,1587545,1588878,1588937,1593611,1593614-1593615,1593680,1594684,1594708,1595549,1597797,1597803,1604590,1604596,1604598,1605104,1610854,1611023,1611107,1611110,1611117,1611120,1611125,1611184,1611193,1611466,1611515,1611517,1625173,1626564,1634615,1642159,1648830,
 1664406,1664447,1664451,1664471,1664769-1664770,1664775,1664904,1664911,1664958,1666341,1666411,1666458,1666611,1667420-1667421,1667423,1667914-1667916,1671329,1671356,1671389,1671513-1671514,1671957,1672354,1672366,1672495,1672575,1675644,1675656,1675668,1676013,1685929,1696140,1696767,1722547,1722557,1726928,1727020,1727160,1727175,1727199,1728957,1733451,1733594
+/apr/apr/trunk:733052,739635,741862,741866-741867,741869,741871,745763-745764,746310,747990,748080,748361,748371,748565,748888,748902,748988,749810,760443,767895,775683,782838,783398,783958,784633,784773,788588,789050,793192-793193,794118,794485,795267,799497,800627,809745,809854,810472,811455,813063,821306,829490,831641,832904,835607,888669,892028,892159,892435,892909,896382,896653,908427,910419,910597,917819,917837-917838,925965,929796,930508,931973,951771,960665,960671,979891,983618,989450,990435,1003338,1044440,1044447,1055657,1072165,1078845,1081462,1081495,1083038,1083242,1084662,1086695,1088023,1089031,1089129,1089438,1099348,1103310,1183683,1183685-1183686,1183688,1183693,1183698,1213382,1235047,1236970,1237078,1237507,1240472,1340286,1340288,1340470,1341193,1341196,1343233,1343243,1367050,1368819,1370494,1372018,1372022,1372093,1372849,1376957,1384764,1389077,1400200,1402868,1405985,1406690,1420106,1420109,1425356,1428809,1438940,1438957-1438959,1442903,1449568,1456418,1459
 994,1460179-1460180,1460241,1460399,1460405,1462738,1462813,1470186,1470348,1475509,1478905,1480067,1481262,1481265,1484271,1487796,1489517,1496407,1502804,1510354,1516261,1523384,1523479,1523484,1523505,1523521,1523604,1523613,1523615,1523844-1523845,1523853,1524014,1524031,1528797,1528809,1529488,1529495,1529515,1529521,1529668,1530786,1530800,1530988,1531554,1531768,1531884,1532022,1533104,1533111,1533979,1535027,1535157,1536744,1538171,1539374,1539389,1539455,1539603,1541054,1541061,1541486,1541655,1541666,1541744,1542601,1542779,1543033,1543056,1548575,1550907,1551650,1551659,1558905,1559382,1559873,1559975,1561040,1561260,1561265,1561321,1561347,1561356,1561361,1561394,1561555,1571894,1575509,1578420,1587045,1587063,1587543,1587545,1588878,1588937,1593611,1593614-1593615,1593680,1594684,1594708,1595549,1597797,1597803,1604590,1604596,1604598,1605104,1610854,1611023,1611107,1611110,1611117,1611120,1611125,1611184,1611193,1611466,1611515,1611517,1625173,1626564,1634615,1642159,1
 648830,1664406,1664447,1664451,1664471,1664769-1664770,1664775,1664904,1664911,1664958,1666341,1666411,1666458,1666611,1667420-1667421,1667423,1667900-1667901,1667903,1667914-1667916,1667962,1669077,1671292,1671329,1671356,1671389,1671513-1671514,1671957,1672354,1672366,1672495,1672575,1675644,1675656,1675668,1676013,1685929,1696140,1696767,1722547,1722557,1726928,1727020,1727160,1727175,1727199,1728957,1732582,1733451,1733594
 /apr/apr/trunk/test/testnames.c:1460405
 /httpd/httpd/trunk:1604590

Modified: apr/apr/branches/1.6.x/configure.in
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/configure.in?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/configure.in (original)
+++ apr/apr/branches/1.6.x/configure.in Sat Mar  5 01:40:58 2016
@@ -2166,10 +2166,17 @@ AC_SUBST(struct_rlimit)
 dnl ----------------------------- Checking for Locking Characteristics 
 echo "${nl}Checking for Locking..."
 
-AC_CHECK_FUNCS(semget semctl flock)
-AC_CHECK_HEADERS(semaphore.h OS.h)
+AC_CHECK_FUNCS(semget semctl semop semtimedop flock)
+APR_IFALLYES(func:semtimedop, have_semtimedop="1", have_semtimedop="0")
+
+AC_CHECK_HEADERS(semaphore.h)
 AC_SEARCH_LIBS(sem_open, rt)
-AC_CHECK_FUNCS(sem_close sem_unlink sem_post sem_wait create_sem)
+AC_CHECK_FUNCS(sem_close sem_unlink sem_post sem_wait sem_timedwait)
+APR_IFALLYES(func:sem_timedwait, have_sem_timedwait="1", have_sem_timedwait="0")
+
+AC_CHECK_HEADERS(OS.h)
+AC_CHECK_FUNCS(create_sem acquire_sem acquire_sem_etc)
+APR_IFALLYES(header:OS.h func:acquire_sem_etc, have_acquire_sem_etc="1", have_acquire_sem_etc="0")
 
 # Some systems return ENOSYS from sem_open.
 AC_CACHE_CHECK(for working sem_open,ac_cv_func_sem_open,[
@@ -2228,7 +2235,10 @@ APR_CHECK_DEFINE_FILES(POLLIN, poll.h sy
 
 if test "$threads" = "1"; then
     APR_CHECK_DEFINE(PTHREAD_PROCESS_SHARED, pthread.h)
-    AC_CHECK_FUNCS(pthread_mutexattr_setpshared)
+    AC_CHECK_FUNCS(pthread_mutex_timedlock pthread_mutexattr_setpshared)
+    APR_IFALLYES(header:pthread.h func:pthread_mutex_timedlock,
+                 have_pthread_mutex_timedlock="1", have_pthread_mutex_timedlock="0")
+    AC_SUBST(have_pthread_mutex_timedlock)
     # Some systems have setpshared and define PROCESS_SHARED, but don't 
     # really support PROCESS_SHARED locks.  So, we must validate that we 
     # can go through the steps without receiving some sort of system error.
@@ -2266,8 +2276,8 @@ fi
 APR_IFALLYES(header:semaphore.h func:sem_open func:sem_close dnl
              func:sem_unlink func:sem_post func:sem_wait,
              hasposixser="1", hasposixser="0")
-APR_IFALLYES(func:semget func:semctl define:SEM_UNDO, hassysvser="1", 
-             hassysvser="0")
+APR_IFALLYES(func:semget func:semctl func:semop define:SEM_UNDO,
+             hassysvser="1", hassysvser="0")
 APR_IFALLYES(func:flock define:LOCK_EX, hasflockser="1", hasflockser="0")
 APR_IFALLYES(header:fcntl.h define:F_SETLK, hasfcntlser="1", hasfcntlser="0")
 # note: the current APR use of shared mutex requires /dev/zero
@@ -2292,9 +2302,9 @@ APR_IFALLYES(func:flock define:LOCK_EX,
             APR_DECIDE(USE_FLOCK_SERIALIZE, [4.2BSD-style flock()]))
 APR_IFALLYES(header:fcntl.h define:F_SETLK,
             APR_DECIDE(USE_FCNTL_SERIALIZE, [SVR4-style fcntl()]))
-APR_IFALLYES(func:semget func:semctl define:SEM_UNDO,
+APR_IFALLYES(func:semget func:semctl func:semop define:SEM_UNDO,
             APR_DECIDE(USE_SYSVSEM_SERIALIZE, [SysV IPC semget()]))
-APR_IFALLYES(header:OS.h func:create_sem, 
+APR_IFALLYES(header:OS.h func:create_sem func:acquire_sem func:acquire_sem_etc, 
             APR_DECIDE(USE_BEOSSEM, [BeOS Semaphores])) 
 if test "x$apr_lock_method" != "x"; then
     APR_DECISION_FORCE($apr_lock_method)

Modified: apr/apr/branches/1.6.x/include/apr_global_mutex.h
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/include/apr_global_mutex.h?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/include/apr_global_mutex.h (original)
+++ apr/apr/branches/1.6.x/include/apr_global_mutex.h Sat Mar  5 01:40:58 2016
@@ -29,6 +29,7 @@
 #if APR_PROC_MUTEX_IS_GLOBAL
 #include "apr_proc_mutex.h"
 #endif
+#include "apr_time.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -66,6 +67,7 @@ typedef struct apr_global_mutex_t apr_gl
  *            APR_LOCK_POSIXSEM
  *            APR_LOCK_PROC_PTHREAD
  *            APR_LOCK_DEFAULT     pick the default mechanism for the platform
+ *            APR_LOCK_DEFAULT_TIMED pick the default timed mechanism
  * </PRE>
  * @param pool the pool from which to allocate the mutex.
  * @warning Check APR_HAS_foo_SERIALIZE defines to see if the platform supports
@@ -109,6 +111,17 @@ APR_DECLARE(apr_status_t) apr_global_mut
 APR_DECLARE(apr_status_t) apr_global_mutex_trylock(apr_global_mutex_t *mutex);
 
 /**
+ * Attempt to acquire the lock for the given mutex until timeout expires.
+ * If the acquisition time outs, the call returns with APR_TIMEUP.
+ * @param mutex the mutex on which to attempt the lock acquiring.
+ * @param timeout the absolute time or relative timeout (microseconds)
+ * @param absolute whether the timeout given is absolute (!0) or relative (0)
+ */
+APR_DECLARE(apr_status_t) apr_global_mutex_timedlock(apr_global_mutex_t *mutex,
+                                                     apr_time_t timeout,
+                                                     int absolute);
+
+/**
  * Release the lock for the given mutex.
  * @param mutex the mutex from which to release the lock.
  */

Modified: apr/apr/branches/1.6.x/include/apr_proc_mutex.h
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/include/apr_proc_mutex.h?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/include/apr_proc_mutex.h (original)
+++ apr/apr/branches/1.6.x/include/apr_proc_mutex.h Sat Mar  5 01:40:58 2016
@@ -26,6 +26,7 @@
 #include "apr_pools.h"
 #include "apr_errno.h"
 #include "apr_perms_set.h"
+#include "apr_time.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -48,7 +49,8 @@ typedef enum {
     APR_LOCK_SYSVSEM,       /**< System V Semaphores */
     APR_LOCK_PROC_PTHREAD,  /**< POSIX pthread process-based locking */
     APR_LOCK_POSIXSEM,      /**< POSIX semaphore process-based locking */
-    APR_LOCK_DEFAULT        /**< Use the default process lock */
+    APR_LOCK_DEFAULT,       /**< Use the default process lock */
+    APR_LOCK_DEFAULT_TIMED  /**< Use the default process timed lock */
 } apr_lockmech_e;
 
 /** Opaque structure representing a process mutex. */
@@ -114,6 +116,17 @@ APR_DECLARE(apr_status_t) apr_proc_mutex
 APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex);
 
 /**
+ * Attempt to acquire the lock for the given mutex until timeout expires.
+ * If the acquisition time outs, the call returns with APR_TIMEUP.
+ * @param mutex the mutex on which to attempt the lock acquiring.
+ * @param timeout the absolute time or relative timeout (microseconds)
+ * @param absolute whether the timeout given is absolute (!0) or relative (0)
+ */
+APR_DECLARE(apr_status_t) apr_proc_mutex_timedlock(apr_proc_mutex_t *mutex,
+                                                   apr_time_t timeout,
+                                                   int absolute);
+
+/**
  * Release the lock for the given mutex.
  * @param mutex the mutex from which to release the lock.
  */

Modified: apr/apr/branches/1.6.x/include/apr_thread_mutex.h
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/include/apr_thread_mutex.h?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/include/apr_thread_mutex.h (original)
+++ apr/apr/branches/1.6.x/include/apr_thread_mutex.h Sat Mar  5 01:40:58 2016
@@ -43,9 +43,11 @@ typedef struct apr_thread_mutex_t apr_th
 #define APR_THREAD_MUTEX_DEFAULT  0x0   /**< platform-optimal lock behavior */
 #define APR_THREAD_MUTEX_NESTED   0x1   /**< enable nested (recursive) locks */
 #define APR_THREAD_MUTEX_UNNESTED 0x2   /**< disable nested locks */
+#define APR_THREAD_MUTEX_TIMED    0x4   /**< enable timed locks */
 
 /* Delayed the include to avoid a circular reference */
 #include "apr_pools.h"
+#include "apr_time.h"
 
 /**
  * Create and initialize a mutex that can be used to synchronize threads.
@@ -82,6 +84,17 @@ APR_DECLARE(apr_status_t) apr_thread_mut
 APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex);
 
 /**
+ * Attempt to acquire the lock for the given mutex until timeout expires.
+ * If the acquisition time outs, the call returns with APR_TIMEUP.
+ * @param mutex the mutex on which to attempt the lock acquiring.
+ * @param timeout the absolute time or relative timeout (microseconds)
+ * @param absolute whether the timeout given is absolute (!0) or relative (0)
+ */
+APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex,
+                                                     apr_time_t timeout,
+                                                     int absolute);
+
+/**
  * Release the lock for the given mutex.
  * @param mutex the mutex from which to release the lock.
  */

Modified: apr/apr/branches/1.6.x/include/apr_time.h
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/include/apr_time.h?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/include/apr_time.h (original)
+++ apr/apr/branches/1.6.x/include/apr_time.h Sat Mar  5 01:40:58 2016
@@ -23,7 +23,6 @@
  */
 
 #include "apr.h"
-#include "apr_pools.h"
 #include "apr_errno.h"
 
 #ifdef __cplusplus
@@ -120,6 +119,9 @@ struct apr_time_exp_t {
     apr_int32_t tm_gmtoff;
 };
 
+/* Delayed the include to avoid a circular reference */
+#include "apr_pools.h"
+
 /**
  * Convert an ansi time_t to an apr_time_t
  * @param result the resulting apr_time_t

Modified: apr/apr/branches/1.6.x/include/arch/netware/apr_arch_thread_mutex.h
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/include/arch/netware/apr_arch_thread_mutex.h?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/include/arch/netware/apr_arch_thread_mutex.h (original)
+++ apr/apr/branches/1.6.x/include/arch/netware/apr_arch_thread_mutex.h Sat Mar  5 01:40:58 2016
@@ -18,11 +18,14 @@
 #define THREAD_MUTEX_H
 
 #include "apr_thread_mutex.h"
+#include "apr_thread_cond.h"
 #include <nks/synch.h>
 
 struct apr_thread_mutex_t {
     apr_pool_t *pool;
     NXMutex_t *mutex;
+    apr_thread_cond_t *cond;
+    int locked, num_waiters;
 };
 
 #endif  /* THREAD_MUTEX_H */

Modified: apr/apr/branches/1.6.x/include/arch/os2/apr_arch_thread_cond.h
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/include/arch/os2/apr_arch_thread_cond.h?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/include/arch/os2/apr_arch_thread_cond.h (original)
+++ apr/apr/branches/1.6.x/include/arch/os2/apr_arch_thread_cond.h Sat Mar  5 01:40:58 2016
@@ -22,6 +22,11 @@
 
 struct apr_thread_cond_t {
     apr_pool_t *pool;
+    HEV semaphore;
+    HMTX mutex;
+    unsigned long num_waiting;
+    unsigned long num_wake;
+    unsigned long generation;
 };
 
 #endif  /* THREAD_COND_H */

Modified: apr/apr/branches/1.6.x/include/arch/unix/apr_arch_proc_mutex.h
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/include/arch/unix/apr_arch_proc_mutex.h?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/include/arch/unix/apr_arch_proc_mutex.h (original)
+++ apr/apr/branches/1.6.x/include/arch/unix/apr_arch_proc_mutex.h Sat Mar  5 01:40:58 2016
@@ -26,6 +26,7 @@
 #include "apr_portable.h"
 #include "apr_file_io.h"
 #include "apr_arch_file_io.h"
+#include "apr_time.h"
 
 /* System headers required by Locks library */
 #if APR_HAVE_SYS_TYPES_H
@@ -72,6 +73,7 @@ struct apr_proc_mutex_unix_lock_methods_
     apr_status_t (*create)(apr_proc_mutex_t *, const char *);
     apr_status_t (*acquire)(apr_proc_mutex_t *);
     apr_status_t (*tryacquire)(apr_proc_mutex_t *);
+    apr_status_t (*timedacquire)(apr_proc_mutex_t *, apr_time_t, int);
     apr_status_t (*release)(apr_proc_mutex_t *);
     apr_status_t (*cleanup)(void *);
     apr_status_t (*child_init)(apr_proc_mutex_t **, apr_pool_t *, const char *);

Modified: apr/apr/branches/1.6.x/include/arch/unix/apr_arch_thread_mutex.h
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/include/arch/unix/apr_arch_thread_mutex.h?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/include/arch/unix/apr_arch_thread_mutex.h (original)
+++ apr/apr/branches/1.6.x/include/arch/unix/apr_arch_thread_mutex.h Sat Mar  5 01:40:58 2016
@@ -21,6 +21,7 @@
 #include "apr_private.h"
 #include "apr_general.h"
 #include "apr_thread_mutex.h"
+#include "apr_thread_cond.h"
 #include "apr_portable.h"
 #include "apr_atomic.h"
 
@@ -32,6 +33,8 @@
 struct apr_thread_mutex_t {
     apr_pool_t *pool;
     pthread_mutex_t mutex;
+    apr_thread_cond_t *cond;
+    int locked, num_waiters;
 };
 #endif
 

Modified: apr/apr/branches/1.6.x/locks/beos/proc_mutex.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/beos/proc_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/locks/beos/proc_mutex.c (original)
+++ apr/apr/branches/1.6.x/locks/beos/proc_mutex.c Sat Mar  5 01:40:58 2016
@@ -27,13 +27,13 @@ static apr_status_t _proc_mutex_cleanup(
     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
     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
 {
     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;

Modified: apr/apr/branches/1.6.x/locks/beos/thread_cond.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/beos/thread_cond.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/locks/beos/thread_cond.c (original)
+++ apr/apr/branches/1.6.x/locks/beos/thread_cond.c Sat Mar  5 01:40:58 2016
@@ -81,7 +81,7 @@ APR_DECLARE(apr_status_t) apr_thread_con
 
 
 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);

Modified: apr/apr/branches/1.6.x/locks/beos/thread_mutex.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/beos/thread_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/locks/beos/thread_mutex.c (original)
+++ apr/apr/branches/1.6.x/locks/beos/thread_mutex.c Sat Mar  5 01:40:58 2016
@@ -27,13 +27,13 @@ static apr_status_t _thread_mutex_cleanu
     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_mut
         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_mut
 
 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_mut
             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;

Modified: apr/apr/branches/1.6.x/locks/netware/proc_mutex.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/netware/proc_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/locks/netware/proc_mutex.c (original)
+++ apr/apr/branches/1.6.x/locks/netware/proc_mutex.c Sat Mar  5 01:40:58 2016
@@ -26,15 +26,24 @@ APR_DECLARE(apr_status_t) apr_proc_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
     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)

Modified: apr/apr/branches/1.6.x/locks/netware/thread_cond.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/netware/thread_cond.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/locks/netware/thread_cond.c (original)
+++ apr/apr/branches/1.6.x/locks/netware/thread_cond.c Sat Mar  5 01:40:58 2016
@@ -66,10 +66,21 @@ APR_DECLARE(apr_status_t) apr_thread_con
 
 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;
 }

Modified: apr/apr/branches/1.6.x/locks/netware/thread_mutex.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/netware/thread_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/locks/netware/thread_mutex.c (original)
+++ apr/apr/branches/1.6.x/locks/netware/thread_mutex.c Sat Mar  5 01:40:58 2016
@@ -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_mut
         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_mut
     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_mut
 
 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;
 }

Modified: apr/apr/branches/1.6.x/locks/os2/proc_mutex.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/os2/proc_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/locks/os2/proc_mutex.c (original)
+++ apr/apr/branches/1.6.x/locks/os2/proc_mutex.c Sat Mar  5 01:40:58 2016
@@ -80,7 +80,7 @@ APR_DECLARE(apr_status_t) apr_proc_mutex
     ULONG rc;
     char *semname;
 
-    if (mech != APR_LOCK_DEFAULT) {
+    if (mech != APR_LOCK_DEFAULT && mech != APR_LOCK_DEFAULT_TIMED) {
         return APR_ENOTIMPL;
     }
 
@@ -148,6 +148,42 @@ APR_DECLARE(apr_status_t) apr_proc_mutex
 
     if (rc == 0) {
         mutex->owner = CurrentTid;
+        mutex->lock_count++;
+    }
+
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+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++;
     }
 

Modified: apr/apr/branches/1.6.x/locks/os2/thread_cond.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/os2/thread_cond.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/locks/os2/thread_cond.c (original)
+++ apr/apr/branches/1.6.x/locks/os2/thread_cond.c Sat Mar  5 01:40:58 2016
@@ -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)

Modified: apr/apr/branches/1.6.x/locks/os2/thread_mutex.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/os2/thread_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/locks/os2/thread_mutex.c (original)
+++ apr/apr/branches/1.6.x/locks/os2/thread_mutex.c Sat Mar  5 01:40:58 2016
@@ -71,6 +71,36 @@ APR_DECLARE(apr_status_t) apr_thread_mut
 
 
 
+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);

Modified: apr/apr/branches/1.6.x/locks/unix/global_mutex.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/unix/global_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/locks/unix/global_mutex.c (original)
+++ apr/apr/branches/1.6.x/locks/unix/global_mutex.c Sat Mar  5 01:40:58 2016
@@ -141,6 +141,40 @@ APR_DECLARE(apr_status_t) apr_global_mut
     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;

Modified: apr/apr/branches/1.6.x/locks/unix/proc_mutex.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/unix/proc_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/locks/unix/proc_mutex.c (original)
+++ apr/apr/branches/1.6.x/locks/unix/proc_mutex.c Sat Mar  5 01:40:58 2016
@@ -184,6 +184,41 @@ static apr_status_t proc_mutex_posix_try
     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_me
     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_trya
     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_me
     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_pthr
 #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_me
     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_try
     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_me
     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_try
     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_me
     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_me
         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
     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);

Modified: apr/apr/branches/1.6.x/locks/unix/thread_cond.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/unix/thread_cond.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/locks/unix/thread_cond.c (original)
+++ apr/apr/branches/1.6.x/locks/unix/thread_cond.c Sat Mar  5 01:40:58 2016
@@ -79,21 +79,31 @@ APR_DECLARE(apr_status_t) apr_thread_con
                                                     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;
 }

Modified: apr/apr/branches/1.6.x/locks/unix/thread_mutex.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/unix/thread_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/locks/unix/thread_mutex.c (original)
+++ apr/apr/branches/1.6.x/locks/unix/thread_mutex.c Sat Mar  5 01:40:58 2016
@@ -77,6 +77,19 @@ APR_DECLARE(apr_status_t) apr_thread_mut
         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_mut
 {
     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_mut
 {
     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_mut
     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_mut
 
 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)

Modified: apr/apr/branches/1.6.x/locks/win32/proc_mutex.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/win32/proc_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/locks/win32/proc_mutex.c (original)
+++ apr/apr/branches/1.6.x/locks/win32/proc_mutex.c Sat Mar  5 01:40:58 2016
@@ -160,6 +160,37 @@ APR_DECLARE(apr_status_t) apr_proc_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) {

Modified: apr/apr/branches/1.6.x/locks/win32/thread_cond.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/win32/thread_cond.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/locks/win32/thread_cond.c (original)
+++ apr/apr/branches/1.6.x/locks/win32/thread_cond.c Sat Mar  5 01:40:58 2016
@@ -61,9 +61,9 @@ APR_DECLARE(apr_status_t) apr_thread_con
     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_c
 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)

Modified: apr/apr/branches/1.6.x/locks/win32/thread_mutex.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/win32/thread_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/locks/win32/thread_mutex.c (original)
+++ apr/apr/branches/1.6.x/locks/win32/thread_mutex.c Sat Mar  5 01:40:58 2016
@@ -54,6 +54,10 @@ APR_DECLARE(apr_status_t) apr_thread_mut
         (*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_mut
         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_mut
     }
     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_mut
     }
     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) {

Modified: apr/apr/branches/1.6.x/test/testglobalmutex.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/test/testglobalmutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/test/testglobalmutex.c (original)
+++ apr/apr/branches/1.6.x/test/testglobalmutex.c Sat Mar  5 01:40:58 2016
@@ -68,6 +68,7 @@ static const char *mutexname(apr_lockmec
     case APR_LOCK_PROC_PTHREAD: return "proc_pthread";
     case APR_LOCK_POSIXSEM: return "posixsem";
     case APR_LOCK_DEFAULT: return "default";
+    case APR_LOCK_DEFAULT_TIMED: return "default_timed";
     default: return "unknown";
     }
 }
@@ -129,6 +130,8 @@ abts_suite *testglobalmutex(abts_suite *
     mech = APR_LOCK_FLOCK;
     abts_run_test(suite, test_exclusive, &mech);
 #endif
+    mech = APR_LOCK_DEFAULT_TIMED;
+    abts_run_test(suite, test_exclusive, &mech);
 
     return suite;
 }

Modified: apr/apr/branches/1.6.x/test/testlock.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/test/testlock.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/test/testlock.c (original)
+++ apr/apr/branches/1.6.x/test/testlock.c Sat Mar  5 01:40:58 2016
@@ -90,7 +90,12 @@ static void *APR_THREAD_FUNC thread_mute
     
     while (1)
     {
-        apr_thread_mutex_lock(thread_mutex);
+        if (data) {
+            apr_thread_mutex_timedlock(thread_mutex, *(apr_time_t *)data, 0);
+        }
+        else {
+            apr_thread_mutex_lock(thread_mutex);
+        }
         if (i == MAX_ITER)
             exitLoop = 0;
         else 
@@ -178,6 +183,38 @@ static void test_thread_mutex(abts_case
     ABTS_INT_EQUAL(tc, MAX_ITER, x);
 }
 
+static void test_thread_timedmutex(abts_case *tc, void *data)
+{
+    apr_thread_t *t1, *t2, *t3, *t4;
+    apr_status_t s1, s2, s3, s4;
+    apr_time_t timeout;
+
+    s1 = apr_thread_mutex_create(&thread_mutex, APR_THREAD_MUTEX_TIMED, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
+    ABTS_PTR_NOTNULL(tc, thread_mutex);
+
+    i = 0;
+    x = 0;
+
+    timeout = apr_time_from_sec(5);
+
+    s1 = apr_thread_create(&t1, NULL, thread_mutex_function, &timeout, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
+    s2 = apr_thread_create(&t2, NULL, thread_mutex_function, &timeout, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
+    s3 = apr_thread_create(&t3, NULL, thread_mutex_function, &timeout, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
+    s4 = apr_thread_create(&t4, NULL, thread_mutex_function, &timeout, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
+
+    apr_thread_join(&s1, t1);
+    apr_thread_join(&s2, t2);
+    apr_thread_join(&s3, t3);
+    apr_thread_join(&s4, t4);
+
+    ABTS_INT_EQUAL(tc, MAX_ITER, x);
+}
+
 static void test_thread_rwlock(abts_case *tc, void *data)
 {
     apr_thread_t *t1, *t2, *t3, *t4;
@@ -305,6 +342,38 @@ static void test_timeoutcond(abts_case *
                        apr_thread_cond_destroy(timeout_cond));
 }
 
+static void test_timeoutmutex(abts_case *tc, void *data)
+{
+    apr_status_t s;
+    apr_time_t begin, end;
+    apr_time_t timeout;
+    int i;
+
+    s = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_TIMED, p);
+    ABTS_INT_EQUAL(tc, APR_SUCCESS, s);
+    ABTS_PTR_NOTNULL(tc, timeout_mutex);
+
+    timeout = apr_time_from_sec(5);
+
+    ABTS_INT_EQUAL(tc, 0, apr_thread_mutex_lock(timeout_mutex));
+    for (i = 0; i < MAX_RETRY; i++) {
+        begin = apr_time_now();
+        s = apr_thread_mutex_timedlock(timeout_mutex, timeout, 0);
+        end = apr_time_now();
+
+        if (s != APR_SUCCESS && !APR_STATUS_IS_TIMEUP(s)) {
+            continue;
+        }
+        ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(s));
+        ABTS_ASSERT(tc, "Timer returned too late", end - begin - timeout < 100000);
+        break;
+    }
+    ABTS_ASSERT(tc, "Too many retries", i < MAX_RETRY);
+    ABTS_INT_EQUAL(tc, 0, apr_thread_mutex_unlock(timeout_mutex));
+    APR_ASSERT_SUCCESS(tc, "Unable to destroy the mutex",
+                       apr_thread_mutex_destroy(timeout_mutex));
+}
+
 #endif /* !APR_HAS_THREADS */
 
 #if !APR_HAS_THREADS
@@ -323,9 +392,11 @@ abts_suite *testlock(abts_suite *suite)
     abts_run_test(suite, threads_not_impl, NULL);
 #else
     abts_run_test(suite, test_thread_mutex, NULL);
+    abts_run_test(suite, test_thread_timedmutex, NULL);
     abts_run_test(suite, test_thread_rwlock, NULL);
     abts_run_test(suite, test_cond, NULL);
     abts_run_test(suite, test_timeoutcond, NULL);
+    abts_run_test(suite, test_timeoutmutex, NULL);
 #endif
 
     return suite;

Modified: apr/apr/branches/1.6.x/test/testlockperf.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/test/testlockperf.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/test/testlockperf.c (original)
+++ apr/apr/branches/1.6.x/test/testlockperf.c Sat Mar  5 01:40:58 2016
@@ -60,7 +60,12 @@ void * APR_THREAD_FUNC thread_mutex_func
     int i;
 
     for (i = 0; i < max_counter; i++) {
-        apr_thread_mutex_lock(thread_lock);
+        if (data) {
+            apr_thread_mutex_timedlock(thread_lock, *(apr_time_t *)data, 0);
+        }
+        else {
+            apr_thread_mutex_lock(thread_lock);
+        }
         mutex_counter++;
         apr_thread_mutex_unlock(thread_lock);
     }
@@ -175,6 +180,57 @@ int test_thread_mutex_nested(int num_thr
     return APR_SUCCESS;
 }
 
+static int test_thread_mutex_timed(int num_threads)
+{
+    apr_thread_t *t[MAX_THREADS];
+    apr_status_t s[MAX_THREADS];
+    apr_time_t time_start, time_stop;
+    apr_time_t timeout;
+    int i;
+
+    mutex_counter = 0;
+
+    timeout = apr_time_from_sec(5);
+
+    printf("apr_thread_mutex_t Tests\n");
+    printf("%-60s", "    Initializing the apr_thread_mutex_t (TIMED)");
+    s[0] = apr_thread_mutex_create(&thread_lock, APR_THREAD_MUTEX_TIMED, pool);
+    if (s[0] != APR_SUCCESS) {
+        printf("Failed!\n");
+        return s[0];
+    }
+    printf("OK\n");
+
+    apr_thread_mutex_lock(thread_lock);
+    /* set_concurrency(4)? -aaron */
+    printf("    Starting %d threads    ", num_threads); 
+    for (i = 0; i < num_threads; ++i) {
+        s[i] = apr_thread_create(&t[i], NULL, thread_mutex_func, &timeout, pool);
+        if (s[i] != APR_SUCCESS) {
+            printf("Failed!\n");
+            return s[i];
+        }
+    }
+    printf("OK\n");
+
+    time_start = apr_time_now();
+    apr_thread_mutex_unlock(thread_lock);
+
+    /* printf("%-60s", "    Waiting for threads to exit"); */
+    for (i = 0; i < num_threads; ++i) {
+        apr_thread_join(&s[i], t[i]);
+    }
+    /* printf("OK\n"); */
+
+    time_stop = apr_time_now();
+    printf("microseconds: %" APR_INT64_T_FMT " usec\n",
+           (time_stop - time_start));
+    if (mutex_counter != max_counter * num_threads)
+        printf("error: counter = %ld\n", mutex_counter);
+
+    return APR_SUCCESS;
+}
+
 int test_thread_rwlock(int num_threads)
 {
     apr_thread_t *t[MAX_THREADS];
@@ -273,6 +329,12 @@ int main(int argc, const char * const *a
             exit(-4);
         }
 
+        if ((rv = test_thread_mutex_timed(i)) != APR_SUCCESS) {
+            fprintf(stderr,"thread_mutex (TIMED) test failed : [%d] %s\n",
+                    rv, apr_strerror(rv, (char*)errmsg, 200));
+            exit(-5);
+        }
+
         if ((rv = test_thread_rwlock(i)) != APR_SUCCESS) {
             fprintf(stderr,"thread_rwlock test failed : [%d] %s\n",
                     rv, apr_strerror(rv, (char*)errmsg, 200));

Modified: apr/apr/branches/1.6.x/test/testmutexscope.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/test/testmutexscope.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/test/testmutexscope.c (original)
+++ apr/apr/branches/1.6.x/test/testmutexscope.c Sat Mar  5 01:40:58 2016
@@ -43,20 +43,22 @@ static apr_pool_t *p;
 static volatile int counter;
 typedef enum {TEST_GLOBAL, TEST_PROC} test_mode_e;
 
-static void lock_init(apr_lockmech_e mech, test_mode_e test_mode)
+static int lock_init(apr_lockmech_e mech, test_mode_e test_mode)
 {
+    apr_status_t rv;
     if (test_mode == TEST_PROC) {
-        assert(apr_proc_mutex_create(&proc_mutex,
-                                     NULL,
-                                     mech,
-                                     p) == APR_SUCCESS);
+        rv = apr_proc_mutex_create(&proc_mutex,
+                                           NULL,
+                                           mech,
+                                           p);
     }
     else {
-        assert(apr_global_mutex_create(&global_mutex,
-                                       NULL,
-                                       mech,
-                                       p) == APR_SUCCESS);
+        rv = apr_global_mutex_create(&global_mutex,
+                                     NULL,
+                                     mech,
+                                     p);
     }
+    return rv;
 }
 
 static void lock_destroy(test_mode_e test_mode)
@@ -120,7 +122,17 @@ static void test_mech_mode(apr_lockmech_
   assert(apr_thread_mutex_create(&thread_mutex, 0, p) == APR_SUCCESS);
   assert(apr_thread_mutex_lock(thread_mutex) == APR_SUCCESS);
   
-  lock_init(mech, test_mode);
+  rv = lock_init(mech, test_mode);
+  if (rv != APR_SUCCESS) {
+      char errmsg[256];
+      printf("%s mutexes with mechanism `%s': %s\n",
+             test_mode == TEST_GLOBAL ? "Global" : "Proc", mech_name,
+             apr_strerror(rv, errmsg, sizeof errmsg));
+      if (rv != APR_ENOTIMPL || mech == APR_LOCK_DEFAULT) {
+          exit(1);
+      }
+      return;
+  }
 
   counter = 0;
 
@@ -142,7 +154,7 @@ static void test_mech_mode(apr_lockmech_
   apr_sleep(apr_time_from_sec(5));
 
   if (test_mode == TEST_PROC) {
-      printf("  Mutex mechanism `%s' is %sglobal in scope on this platform.\n",
+      printf("  mutex mechanism `%s' is %sglobal in scope on this platform.\n",
              mech_name, counter == 1 ? "" : "not ");
   }
   else {
@@ -155,7 +167,7 @@ static void test_mech_mode(apr_lockmech_
           exit(1);
       }
       else {
-          printf("  no problems encountered...\n");
+          printf("  no problem encountered...\n");
       }
   }
   
@@ -205,6 +217,7 @@ int main(void)
 #if APR_HAS_PROC_PTHREAD_SERIALIZE
         ,{APR_LOCK_PROC_PTHREAD, "proc_pthread"}
 #endif
+        ,{APR_LOCK_DEFAULT_TIMED, "default_timed"}
     };
     int i;
         

Modified: apr/apr/branches/1.6.x/test/testprocmutex.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/test/testprocmutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
==============================================================================
--- apr/apr/branches/1.6.x/test/testprocmutex.c (original)
+++ apr/apr/branches/1.6.x/test/testprocmutex.c Sat Mar  5 01:40:58 2016
@@ -35,6 +35,11 @@
 static apr_proc_mutex_t *proc_lock;
 static volatile int *x;
 
+typedef struct lockmech {
+    apr_lockmech_e num;
+    const char *name;
+} lockmech_t;
+
 /* a slower more racy way to implement (*x)++ */
 static int increment(int n)
 {
@@ -68,7 +73,7 @@ static void make_child(abts_case *tc, in
             exit(1);
 
         do {
-            if (trylock) {
+            if (trylock > 0) {
                 int wait_usec = 0;
 
                 while ((rv = apr_proc_mutex_trylock(proc_lock))) {
@@ -79,6 +84,16 @@ static void make_child(abts_case *tc, in
                     apr_sleep(1);
                 }
             }
+            else if (trylock < 0) {
+                int wait_usec = 0;
+
+                while ((rv = apr_proc_mutex_timedlock(proc_lock, 1, 0))) {
+                    if (!APR_STATUS_IS_TIMEUP(rv))
+                        exit(1);
+                    if (++wait_usec >= MAX_WAIT_USEC)
+                        exit(1);
+                }
+            }
             else {
                 if (apr_proc_mutex_lock(proc_lock))
                     exit(1);
@@ -108,16 +123,21 @@ static void await_child(abts_case *tc, a
 }
 
 static void test_exclusive(abts_case *tc, const char *lockname, 
-                           apr_lockmech_e mech)
+                           lockmech_t *mech)
 {
     apr_proc_t *child[CHILDREN];
     apr_status_t rv;
     int n;
  
-    rv = apr_proc_mutex_create(&proc_lock, lockname, mech, p);
+    rv = apr_proc_mutex_create(&proc_lock, lockname, mech->num, p);
     APR_ASSERT_SUCCESS(tc, "create the mutex", rv);
-    if (rv != APR_SUCCESS)
+    if (rv != APR_SUCCESS) {
+        fprintf(stderr, "%s not implemented, ", mech->name);
+        ABTS_ASSERT(tc, "Default timed not implemented",
+                    mech->num != APR_LOCK_DEFAULT &&
+                    mech->num != APR_LOCK_DEFAULT_TIMED);
         return;
+    }
  
     for (n = 0; n < CHILDREN; n++)
         make_child(tc, 0, &child[n], p);
@@ -129,24 +149,52 @@ static void test_exclusive(abts_case *tc
 
     rv = apr_proc_mutex_trylock(proc_lock);
     if (rv == APR_ENOTIMPL) {
-        ABTS_NOT_IMPL(tc, "apr_proc_mutex_trylock not implemented");
-        return;
+        fprintf(stderr, "%s_trylock() not implemented, ", mech->name);
+        ABTS_ASSERT(tc, "Default timed trylock not implemented",
+                    mech->num != APR_LOCK_DEFAULT &&
+                    mech->num != APR_LOCK_DEFAULT_TIMED);
     }
-    APR_ASSERT_SUCCESS(tc, "check for trylock", rv);
+    else {
+        APR_ASSERT_SUCCESS(tc, "check for trylock", rv);
 
-    rv = apr_proc_mutex_unlock(proc_lock);
-    APR_ASSERT_SUCCESS(tc, "unlock after trylock check", rv);
+        rv = apr_proc_mutex_unlock(proc_lock);
+        APR_ASSERT_SUCCESS(tc, "unlock after trylock check", rv);
 
-    *x = 0;
+        *x = 0;
 
-    for (n = 0; n < CHILDREN; n++)
-        make_child(tc, 1, &child[n], p);
+        for (n = 0; n < CHILDREN; n++)
+            make_child(tc, 1, &child[n], p);
+
+        for (n = 0; n < CHILDREN; n++)
+            await_child(tc, child[n]);
+        
+        ABTS_ASSERT(tc, "Locks don't appear to work with trylock",
+                    *x == MAX_COUNTER);
+    }
 
-    for (n = 0; n < CHILDREN; n++)
-        await_child(tc, child[n]);
-    
-    ABTS_ASSERT(tc, "Locks don't appear to work with trylock",
-                *x == MAX_COUNTER);
+    rv = apr_proc_mutex_timedlock(proc_lock, 1, 0);
+    if (rv == APR_ENOTIMPL) {
+        fprintf(stderr, "%s_timedlock() not implemented, ", mech->name);
+        ABTS_ASSERT(tc, "Default timed timedlock not implemented",
+                    mech->num != APR_LOCK_DEFAULT_TIMED);
+    }
+    else {
+        APR_ASSERT_SUCCESS(tc, "check for timedlock", rv);
+
+        rv = apr_proc_mutex_unlock(proc_lock);
+        APR_ASSERT_SUCCESS(tc, "unlock after timedlock check", rv);
+
+        *x = 0;
+
+        for (n = 0; n < CHILDREN; n++)
+            make_child(tc, -1, &child[n], p);
+
+        for (n = 0; n < CHILDREN; n++)
+            await_child(tc, child[n]);
+        
+        ABTS_ASSERT(tc, "Locks don't appear to work with timedlock",
+                    *x == MAX_COUNTER);
+    }
 }
 #endif
 
@@ -156,7 +204,6 @@ static void proc_mutex(abts_case *tc, vo
     apr_status_t rv;
     const char *shmname = "tpm.shm";
     apr_shm_t *shm;
-    apr_lockmech_e *mech = data;
 
     /* Use anonymous shm if available. */
     rv = apr_shm_create(&shm, sizeof(int), NULL, p);
@@ -170,7 +217,7 @@ static void proc_mutex(abts_case *tc, vo
         return;
 
     x = apr_shm_baseaddr_get(shm);
-    test_exclusive(tc, NULL, *mech);
+    test_exclusive(tc, NULL, data);
     rv = apr_shm_destroy(shm);
     APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv);
 #else
@@ -181,30 +228,30 @@ static void proc_mutex(abts_case *tc, vo
 
 abts_suite *testprocmutex(abts_suite *suite)
 {
-    apr_lockmech_e mech = APR_LOCK_DEFAULT;
-
-    suite = ADD_SUITE(suite)
-    abts_run_test(suite, proc_mutex, &mech);
-#if APR_HAS_POSIXSEM_SERIALIZE
-    mech = APR_LOCK_POSIXSEM;
-    abts_run_test(suite, proc_mutex, &mech);
+    lockmech_t lockmechs[] = {
+        {APR_LOCK_DEFAULT, "default"}
+#if APR_HAS_FLOCK_SERIALIZE
+        ,{APR_LOCK_FLOCK, "flock"}
 #endif
 #if APR_HAS_SYSVSEM_SERIALIZE
-    mech = APR_LOCK_SYSVSEM;
-    abts_run_test(suite, proc_mutex, &mech);
+        ,{APR_LOCK_SYSVSEM, "sysvsem"}
 #endif
-#if APR_HAS_PROC_PTHREAD_SERIALIZE
-    mech = APR_LOCK_PROC_PTHREAD;
-    abts_run_test(suite, proc_mutex, &mech);
+#if APR_HAS_POSIXSEM_SERIALIZE
+        ,{APR_LOCK_POSIXSEM, "posix"}
 #endif
 #if APR_HAS_FCNTL_SERIALIZE
-    mech = APR_LOCK_FCNTL;
-    abts_run_test(suite, proc_mutex, &mech);
+        ,{APR_LOCK_FCNTL, "fcntl"}
 #endif
-#if APR_HAS_FLOCK_SERIALIZE
-    mech = APR_LOCK_FLOCK;
-    abts_run_test(suite, proc_mutex, &mech);
+#if APR_HAS_PROC_PTHREAD_SERIALIZE
+        ,{APR_LOCK_PROC_PTHREAD, "proc_pthread"}
 #endif
+        ,{APR_LOCK_DEFAULT_TIMED, "default_timed"}
+    };
+    int i;
 
+    suite = ADD_SUITE(suite)
+    for (i = 0; i < sizeof(lockmechs) / sizeof(lockmechs[0]); i++) {
+        abts_run_test(suite, proc_mutex, &lockmechs[i]);
+    }
     return suite;
 }




Re: svn commit: r1733684 - in /apr/apr/branches/1.6.x: ./ include/ include/arch/netware/ include/arch/os2/ include/arch/unix/ locks/beos/ locks/netware/ locks/os2/ locks/unix/ locks/win32/ test/

Posted by Rainer Jung <ra...@kippdata.de>.
Hi Yann,

Am 19.12.2016 um 01:55 schrieb Yann Ylavic:
> On Sat, Dec 17, 2016 at 6:48 PM, Rainer Jung <ra...@kippdata.de> wrote:
>> This commit introduced a new dependency on pthread_mutex_timedlock. Although
>> its presence is detected by configure and locks/unix/thread_mutex.c checks
>> HAVE_PTHREAD_MUTEX_TIMEDLOCK and provides an alternative implementation if
>> it is not defined, file locks/unix/proc_mutex.c uses pthread_mutex_timedlock
>> unconditionally.
>
> Thanks Rainer for noticing, hopefully fixed in r1774973.

looks good from visually checking.

> I wonder if we could fall back to using pthread_cond_timewait() like
> we do for thread_mutex, but that'd require
> pthread_condattr_setpshared() to be available on the system.
> Is it the case at least on this older Solaris?

Yes, Solaris 8 has it, get and set. They are in the man pages, in 
pthread.h and I find symbols in libpthread.so.

The full pthread function list taken from the Solaris 8 man page:

pthread_atfork()
pthread_attr_destroy()
pthread_attr_getdetachstate()
pthread_attr_getguardsize()
pthread_attr_getinheritsched()
pthread_attr_getschedparam()
pthread_attr_getschedpolicy()
pthread_attr_getscope()
pthread_attr_getstackaddr()
pthread_attr_getstacksize()
pthread_attr_init()
pthread_attr_setdetachstate()
pthread_attr_setguardsize()
pthread_attr_setinheritsched()
pthread_attr_setschedparam()
pthread_attr_setschedpolicy()
pthread_attr_setscope()
pthread_attr_setstackaddr()
pthread_attr_setstacksize()
pthread_cancel()
pthread_cleanup_pop()
pthread_cleanup_push()
pthread_cond_broadcast()
pthread_cond_destroy()
pthread_cond_init()
pthread_cond_signal()
pthread_cond_timedwait()
pthread_cond_wait()
pthread_condattr_destroy()
pthread_condattr_getpshared()
pthread_condattr_init()
pthread_condattr_setpshared()
pthread_create()
pthread_detach()
pthread_equal()
pthread_exit()
pthread_getconcurrency()
pthread_getschedparam()
pthread_getspecific()
pthread_join()
pthread_key_create()
pthread_key_delete()
pthread_kill()
pthread_mutex_destroy()
pthread_mutex_getprioceiling()
pthread_mutex_init()
pthread_mutex_lock()
pthread_mutex_setprioceiling()
pthread_mutex_trylock()
pthread_mutex_unlock()
pthread_mutexattr_destroy()
pthread_mutexattr_getprioceiling()
pthread_mutexattr_getprotocol()
pthread_mutexattr_getpshared()
pthread_mutexattr_gettype()
pthread_mutexattr_init()
pthread_mutexattr_setprioceiling()
pthread_mutexattr_setprotocol()
pthread_mutexattr_setpshared()
pthread_mutexattr_settype()
pthread_once()
pthread_rwlock_destroy()
pthread_rwlock_init()
pthread_rwlock_rdlock()
pthread_rwlock_tryrdlock()
pthread_rwlock_trywrlock()
pthread_rwlock_unlock()
pthread_rwlock_wrlock()
pthread_rwlockattr_destroy()
pthread_rwlockattr_getpshared()
pthread_rwlockattr_init()
pthread_rwlockattr_setpshared()
pthread_self()
pthread_setcancelstate()
pthread_setcanceltype()
pthread_setconcurrency()
pthread_setschedparam()
pthread_setspecific()
pthread_sigmask()
pthread_testcancel()

> It's possibly not worth it too, thoughts?

I can't judge, I haven't really looked into what the code is doing and 
how useful it would be. Just noticed the compile problem and hte 
inconsistency between the thread and proc cases. Sorry.

Regards,

Rainer

Re: svn commit: r1733684 - in /apr/apr/branches/1.6.x: ./ include/ include/arch/netware/ include/arch/os2/ include/arch/unix/ locks/beos/ locks/netware/ locks/os2/ locks/unix/ locks/win32/ test/

Posted by Yann Ylavic <yl...@gmail.com>.
On Sat, Dec 17, 2016 at 6:48 PM, Rainer Jung <ra...@kippdata.de> wrote:
> This commit introduced a new dependency on pthread_mutex_timedlock. Although
> its presence is detected by configure and locks/unix/thread_mutex.c checks
> HAVE_PTHREAD_MUTEX_TIMEDLOCK and provides an alternative implementation if
> it is not defined, file locks/unix/proc_mutex.c uses pthread_mutex_timedlock
> unconditionally.

Thanks Rainer for noticing, hopefully fixed in r1774973.

I wonder if we could fall back to using pthread_cond_timewait() like
we do for thread_mutex, but that'd require
pthread_condattr_setpshared() to be available on the system.
Is it the case at least on this older Solaris?
It's possibly not worth it too, thoughts?

Regards,
Yann.

Re: svn commit: r1733684 - in /apr/apr/branches/1.6.x: ./ include/ include/arch/netware/ include/arch/os2/ include/arch/unix/ locks/beos/ locks/netware/ locks/os2/ locks/unix/ locks/win32/ test/

Posted by Rainer Jung <ra...@kippdata.de>.
This commit introduced a new dependency on pthread_mutex_timedlock. 
Although its presence is detected by configure and 
locks/unix/thread_mutex.c checks HAVE_PTHREAD_MUTEX_TIMEDLOCK and 
provides an alternative implementation if it is not defined, file 
locks/unix/proc_mutex.c uses pthread_mutex_timedlock unconditionally.

One platform that doesn't have it is ancient Solaris 8.

I don't really care whether we require it for APR 1.6 or not, but 
providing an alternative in thread_mutex.c but not in proc_mutex.c seems 
inconsistent.

Sorry for the late feedback, but I just noticed this during testing the 
httpd 2.4.25 release candidate with heads of 1.5.x and 1.6.x.

Regards,

Rainer

Am 05.03.2016 um 02:40 schrieb ylavic@apache.org:
> Author: ylavic
> Date: Sat Mar  5 01:40:58 2016
> New Revision: 1733684
>
> URL: http://svn.apache.org/viewvc?rev=1733684&view=rev
> Log:
> 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
>
> Modified:
>     apr/apr/branches/1.6.x/   (props changed)
>     apr/apr/branches/1.6.x/configure.in
>     apr/apr/branches/1.6.x/include/apr_global_mutex.h
>     apr/apr/branches/1.6.x/include/apr_proc_mutex.h
>     apr/apr/branches/1.6.x/include/apr_thread_mutex.h
>     apr/apr/branches/1.6.x/include/apr_time.h
>     apr/apr/branches/1.6.x/include/arch/netware/apr_arch_thread_mutex.h
>     apr/apr/branches/1.6.x/include/arch/os2/apr_arch_thread_cond.h
>     apr/apr/branches/1.6.x/include/arch/unix/apr_arch_proc_mutex.h
>     apr/apr/branches/1.6.x/include/arch/unix/apr_arch_thread_mutex.h
>     apr/apr/branches/1.6.x/locks/beos/proc_mutex.c
>     apr/apr/branches/1.6.x/locks/beos/thread_cond.c
>     apr/apr/branches/1.6.x/locks/beos/thread_mutex.c
>     apr/apr/branches/1.6.x/locks/netware/proc_mutex.c
>     apr/apr/branches/1.6.x/locks/netware/thread_cond.c
>     apr/apr/branches/1.6.x/locks/netware/thread_mutex.c
>     apr/apr/branches/1.6.x/locks/os2/proc_mutex.c
>     apr/apr/branches/1.6.x/locks/os2/thread_cond.c
>     apr/apr/branches/1.6.x/locks/os2/thread_mutex.c
>     apr/apr/branches/1.6.x/locks/unix/global_mutex.c
>     apr/apr/branches/1.6.x/locks/unix/proc_mutex.c
>     apr/apr/branches/1.6.x/locks/unix/thread_cond.c
>     apr/apr/branches/1.6.x/locks/unix/thread_mutex.c
>     apr/apr/branches/1.6.x/locks/win32/proc_mutex.c
>     apr/apr/branches/1.6.x/locks/win32/thread_cond.c
>     apr/apr/branches/1.6.x/locks/win32/thread_mutex.c
>     apr/apr/branches/1.6.x/test/testglobalmutex.c
>     apr/apr/branches/1.6.x/test/testlock.c
>     apr/apr/branches/1.6.x/test/testlockperf.c
>     apr/apr/branches/1.6.x/test/testmutexscope.c
>     apr/apr/branches/1.6.x/test/testprocmutex.c
>
> Propchange: apr/apr/branches/1.6.x/
> ------------------------------------------------------------------------------
> --- svn:mergeinfo (original)
> +++ svn:mergeinfo Sat Mar  5 01:40:58 2016
> @@ -1,4 +1,4 @@
>  /apr/apr/branches/1.4.x:1003369,1101301
> -/apr/apr/trunk:733052,739635,741862,741866-741867,741869,741871,745763-745764,746310,747990,748080,748361,748371,748565,748888,748902,748988,749810,760443,767895,775683,782838,783398,783958,784633,784773,788588,789050,793192-793193,794118,794485,795267,799497,800627,809745,809854,810472,811455,813063,821306,829490,831641,832904,835607,888669,892028,892159,892435,892909,896382,896653,908427,910419,910597,917819,917837-917838,925965,929796,931973,951771,960665,960671,979891,983618,989450,990435,1003338,1044440,1044447,1055657,1072165,1078845,1081462,1081495,1083038,1083242,1084662,1086695,1088023,1089031,1089129,1089438,1099348,1103310,1183683,1183685-1183686,1183688,1183693,1183698,1213382,1235047,1236970,1237078,1237507,1240472,1340286,1340288,1340470,1341193,1341196,1343233,1343243,1367050,1368819,1370494,1372018,1372022,1372093,1372849,1376957,1384764,1389077,1400200,1402868,1405985,1406690,1420106,1420109,1425356,1428809,1438940,1438957-1438959,1442903,1449568,1456418,1459994,146
>  0179-1460180,1460241,1460399,1460405,1462738,1462813,1470186,1470348,1475509,1478905,1480067,1481262,1481265,1484271,1487796,1489517,1496407,1502804,1510354,1516261,1523384,1523479,1523484,1523505,1523521,1523604,1523613,1523615,1523844-1523845,1523853,1524014,1524031,1528797,1528809,1529488,1529495,1529515,1529521,1529668,1530786,1530800,1530988,1531554,1531768,1531884,1532022,1533104,1533111,1533979,1535027,1535157,1536744,1538171,1539374,1539389,1539455,1539603,1541054,1541061,1541486,1541655,1541666,1541744,1542601,1542779,1543033,1543056,1548575,1550907,1551650,1551659,1558905,1559382,1559873,1559975,1561040,1561260,1561265,1561321,1561347,1561356,1561361,1561394,1561555,1571894,1575509,1578420,1587045,1587063,1587543,1587545,1588878,1588937,1593611,1593614-1593615,1593680,1594684,1594708,1595549,1597797,1597803,1604590,1604596,1604598,1605104,1610854,1611023,1611107,1611110,1611117,1611120,1611125,1611184,1611193,1611466,1611515,1611517,1625173,1626564,1634615,1642159,1648830,
>  1664406,1664447,1664451,1664471,1664769-1664770,1664775,1664904,1664911,1664958,1666341,1666411,1666458,1666611,1667420-1667421,1667423,1667914-1667916,1671329,1671356,1671389,1671513-1671514,1671957,1672354,1672366,1672495,1672575,1675644,1675656,1675668,1676013,1685929,1696140,1696767,1722547,1722557,1726928,1727020,1727160,1727175,1727199,1728957,1733451,1733594
> +/apr/apr/trunk:733052,739635,741862,741866-741867,741869,741871,745763-745764,746310,747990,748080,748361,748371,748565,748888,748902,748988,749810,760443,767895,775683,782838,783398,783958,784633,784773,788588,789050,793192-793193,794118,794485,795267,799497,800627,809745,809854,810472,811455,813063,821306,829490,831641,832904,835607,888669,892028,892159,892435,892909,896382,896653,908427,910419,910597,917819,917837-917838,925965,929796,930508,931973,951771,960665,960671,979891,983618,989450,990435,1003338,1044440,1044447,1055657,1072165,1078845,1081462,1081495,1083038,1083242,1084662,1086695,1088023,1089031,1089129,1089438,1099348,1103310,1183683,1183685-1183686,1183688,1183693,1183698,1213382,1235047,1236970,1237078,1237507,1240472,1340286,1340288,1340470,1341193,1341196,1343233,1343243,1367050,1368819,1370494,1372018,1372022,1372093,1372849,1376957,1384764,1389077,1400200,1402868,1405985,1406690,1420106,1420109,1425356,1428809,1438940,1438957-1438959,1442903,1449568,1456418,1459
>  994,1460179-1460180,1460241,1460399,1460405,1462738,1462813,1470186,1470348,1475509,1478905,1480067,1481262,1481265,1484271,1487796,1489517,1496407,1502804,1510354,1516261,1523384,1523479,1523484,1523505,1523521,1523604,1523613,1523615,1523844-1523845,1523853,1524014,1524031,1528797,1528809,1529488,1529495,1529515,1529521,1529668,1530786,1530800,1530988,1531554,1531768,1531884,1532022,1533104,1533111,1533979,1535027,1535157,1536744,1538171,1539374,1539389,1539455,1539603,1541054,1541061,1541486,1541655,1541666,1541744,1542601,1542779,1543033,1543056,1548575,1550907,1551650,1551659,1558905,1559382,1559873,1559975,1561040,1561260,1561265,1561321,1561347,1561356,1561361,1561394,1561555,1571894,1575509,1578420,1587045,1587063,1587543,1587545,1588878,1588937,1593611,1593614-1593615,1593680,1594684,1594708,1595549,1597797,1597803,1604590,1604596,1604598,1605104,1610854,1611023,1611107,1611110,1611117,1611120,1611125,1611184,1611193,1611466,1611515,1611517,1625173,1626564,1634615,1642159,1
>  648830,1664406,1664447,1664451,1664471,1664769-1664770,1664775,1664904,1664911,1664958,1666341,1666411,1666458,1666611,1667420-1667421,1667423,1667900-1667901,1667903,1667914-1667916,1667962,1669077,1671292,1671329,1671356,1671389,1671513-1671514,1671957,1672354,1672366,1672495,1672575,1675644,1675656,1675668,1676013,1685929,1696140,1696767,1722547,1722557,1726928,1727020,1727160,1727175,1727199,1728957,1732582,1733451,1733594
>  /apr/apr/trunk/test/testnames.c:1460405
>  /httpd/httpd/trunk:1604590
>
> Modified: apr/apr/branches/1.6.x/configure.in
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/configure.in?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/configure.in (original)
> +++ apr/apr/branches/1.6.x/configure.in Sat Mar  5 01:40:58 2016
> @@ -2166,10 +2166,17 @@ AC_SUBST(struct_rlimit)
>  dnl ----------------------------- Checking for Locking Characteristics
>  echo "${nl}Checking for Locking..."
>
> -AC_CHECK_FUNCS(semget semctl flock)
> -AC_CHECK_HEADERS(semaphore.h OS.h)
> +AC_CHECK_FUNCS(semget semctl semop semtimedop flock)
> +APR_IFALLYES(func:semtimedop, have_semtimedop="1", have_semtimedop="0")
> +
> +AC_CHECK_HEADERS(semaphore.h)
>  AC_SEARCH_LIBS(sem_open, rt)
> -AC_CHECK_FUNCS(sem_close sem_unlink sem_post sem_wait create_sem)
> +AC_CHECK_FUNCS(sem_close sem_unlink sem_post sem_wait sem_timedwait)
> +APR_IFALLYES(func:sem_timedwait, have_sem_timedwait="1", have_sem_timedwait="0")
> +
> +AC_CHECK_HEADERS(OS.h)
> +AC_CHECK_FUNCS(create_sem acquire_sem acquire_sem_etc)
> +APR_IFALLYES(header:OS.h func:acquire_sem_etc, have_acquire_sem_etc="1", have_acquire_sem_etc="0")
>
>  # Some systems return ENOSYS from sem_open.
>  AC_CACHE_CHECK(for working sem_open,ac_cv_func_sem_open,[
> @@ -2228,7 +2235,10 @@ APR_CHECK_DEFINE_FILES(POLLIN, poll.h sy
>
>  if test "$threads" = "1"; then
>      APR_CHECK_DEFINE(PTHREAD_PROCESS_SHARED, pthread.h)
> -    AC_CHECK_FUNCS(pthread_mutexattr_setpshared)
> +    AC_CHECK_FUNCS(pthread_mutex_timedlock pthread_mutexattr_setpshared)
> +    APR_IFALLYES(header:pthread.h func:pthread_mutex_timedlock,
> +                 have_pthread_mutex_timedlock="1", have_pthread_mutex_timedlock="0")
> +    AC_SUBST(have_pthread_mutex_timedlock)
>      # Some systems have setpshared and define PROCESS_SHARED, but don't
>      # really support PROCESS_SHARED locks.  So, we must validate that we
>      # can go through the steps without receiving some sort of system error.
> @@ -2266,8 +2276,8 @@ fi
>  APR_IFALLYES(header:semaphore.h func:sem_open func:sem_close dnl
>               func:sem_unlink func:sem_post func:sem_wait,
>               hasposixser="1", hasposixser="0")
> -APR_IFALLYES(func:semget func:semctl define:SEM_UNDO, hassysvser="1",
> -             hassysvser="0")
> +APR_IFALLYES(func:semget func:semctl func:semop define:SEM_UNDO,
> +             hassysvser="1", hassysvser="0")
>  APR_IFALLYES(func:flock define:LOCK_EX, hasflockser="1", hasflockser="0")
>  APR_IFALLYES(header:fcntl.h define:F_SETLK, hasfcntlser="1", hasfcntlser="0")
>  # note: the current APR use of shared mutex requires /dev/zero
> @@ -2292,9 +2302,9 @@ APR_IFALLYES(func:flock define:LOCK_EX,
>              APR_DECIDE(USE_FLOCK_SERIALIZE, [4.2BSD-style flock()]))
>  APR_IFALLYES(header:fcntl.h define:F_SETLK,
>              APR_DECIDE(USE_FCNTL_SERIALIZE, [SVR4-style fcntl()]))
> -APR_IFALLYES(func:semget func:semctl define:SEM_UNDO,
> +APR_IFALLYES(func:semget func:semctl func:semop define:SEM_UNDO,
>              APR_DECIDE(USE_SYSVSEM_SERIALIZE, [SysV IPC semget()]))
> -APR_IFALLYES(header:OS.h func:create_sem,
> +APR_IFALLYES(header:OS.h func:create_sem func:acquire_sem func:acquire_sem_etc,
>              APR_DECIDE(USE_BEOSSEM, [BeOS Semaphores]))
>  if test "x$apr_lock_method" != "x"; then
>      APR_DECISION_FORCE($apr_lock_method)
>
> Modified: apr/apr/branches/1.6.x/include/apr_global_mutex.h
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/include/apr_global_mutex.h?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/include/apr_global_mutex.h (original)
> +++ apr/apr/branches/1.6.x/include/apr_global_mutex.h Sat Mar  5 01:40:58 2016
> @@ -29,6 +29,7 @@
>  #if APR_PROC_MUTEX_IS_GLOBAL
>  #include "apr_proc_mutex.h"
>  #endif
> +#include "apr_time.h"
>
>  #ifdef __cplusplus
>  extern "C" {
> @@ -66,6 +67,7 @@ typedef struct apr_global_mutex_t apr_gl
>   *            APR_LOCK_POSIXSEM
>   *            APR_LOCK_PROC_PTHREAD
>   *            APR_LOCK_DEFAULT     pick the default mechanism for the platform
> + *            APR_LOCK_DEFAULT_TIMED pick the default timed mechanism
>   * </PRE>
>   * @param pool the pool from which to allocate the mutex.
>   * @warning Check APR_HAS_foo_SERIALIZE defines to see if the platform supports
> @@ -109,6 +111,17 @@ APR_DECLARE(apr_status_t) apr_global_mut
>  APR_DECLARE(apr_status_t) apr_global_mutex_trylock(apr_global_mutex_t *mutex);
>
>  /**
> + * Attempt to acquire the lock for the given mutex until timeout expires.
> + * If the acquisition time outs, the call returns with APR_TIMEUP.
> + * @param mutex the mutex on which to attempt the lock acquiring.
> + * @param timeout the absolute time or relative timeout (microseconds)
> + * @param absolute whether the timeout given is absolute (!0) or relative (0)
> + */
> +APR_DECLARE(apr_status_t) apr_global_mutex_timedlock(apr_global_mutex_t *mutex,
> +                                                     apr_time_t timeout,
> +                                                     int absolute);
> +
> +/**
>   * Release the lock for the given mutex.
>   * @param mutex the mutex from which to release the lock.
>   */
>
> Modified: apr/apr/branches/1.6.x/include/apr_proc_mutex.h
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/include/apr_proc_mutex.h?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/include/apr_proc_mutex.h (original)
> +++ apr/apr/branches/1.6.x/include/apr_proc_mutex.h Sat Mar  5 01:40:58 2016
> @@ -26,6 +26,7 @@
>  #include "apr_pools.h"
>  #include "apr_errno.h"
>  #include "apr_perms_set.h"
> +#include "apr_time.h"
>
>  #ifdef __cplusplus
>  extern "C" {
> @@ -48,7 +49,8 @@ typedef enum {
>      APR_LOCK_SYSVSEM,       /**< System V Semaphores */
>      APR_LOCK_PROC_PTHREAD,  /**< POSIX pthread process-based locking */
>      APR_LOCK_POSIXSEM,      /**< POSIX semaphore process-based locking */
> -    APR_LOCK_DEFAULT        /**< Use the default process lock */
> +    APR_LOCK_DEFAULT,       /**< Use the default process lock */
> +    APR_LOCK_DEFAULT_TIMED  /**< Use the default process timed lock */
>  } apr_lockmech_e;
>
>  /** Opaque structure representing a process mutex. */
> @@ -114,6 +116,17 @@ APR_DECLARE(apr_status_t) apr_proc_mutex
>  APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex);
>
>  /**
> + * Attempt to acquire the lock for the given mutex until timeout expires.
> + * If the acquisition time outs, the call returns with APR_TIMEUP.
> + * @param mutex the mutex on which to attempt the lock acquiring.
> + * @param timeout the absolute time or relative timeout (microseconds)
> + * @param absolute whether the timeout given is absolute (!0) or relative (0)
> + */
> +APR_DECLARE(apr_status_t) apr_proc_mutex_timedlock(apr_proc_mutex_t *mutex,
> +                                                   apr_time_t timeout,
> +                                                   int absolute);
> +
> +/**
>   * Release the lock for the given mutex.
>   * @param mutex the mutex from which to release the lock.
>   */
>
> Modified: apr/apr/branches/1.6.x/include/apr_thread_mutex.h
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/include/apr_thread_mutex.h?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/include/apr_thread_mutex.h (original)
> +++ apr/apr/branches/1.6.x/include/apr_thread_mutex.h Sat Mar  5 01:40:58 2016
> @@ -43,9 +43,11 @@ typedef struct apr_thread_mutex_t apr_th
>  #define APR_THREAD_MUTEX_DEFAULT  0x0   /**< platform-optimal lock behavior */
>  #define APR_THREAD_MUTEX_NESTED   0x1   /**< enable nested (recursive) locks */
>  #define APR_THREAD_MUTEX_UNNESTED 0x2   /**< disable nested locks */
> +#define APR_THREAD_MUTEX_TIMED    0x4   /**< enable timed locks */
>
>  /* Delayed the include to avoid a circular reference */
>  #include "apr_pools.h"
> +#include "apr_time.h"
>
>  /**
>   * Create and initialize a mutex that can be used to synchronize threads.
> @@ -82,6 +84,17 @@ APR_DECLARE(apr_status_t) apr_thread_mut
>  APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex);
>
>  /**
> + * Attempt to acquire the lock for the given mutex until timeout expires.
> + * If the acquisition time outs, the call returns with APR_TIMEUP.
> + * @param mutex the mutex on which to attempt the lock acquiring.
> + * @param timeout the absolute time or relative timeout (microseconds)
> + * @param absolute whether the timeout given is absolute (!0) or relative (0)
> + */
> +APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex,
> +                                                     apr_time_t timeout,
> +                                                     int absolute);
> +
> +/**
>   * Release the lock for the given mutex.
>   * @param mutex the mutex from which to release the lock.
>   */
>
> Modified: apr/apr/branches/1.6.x/include/apr_time.h
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/include/apr_time.h?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/include/apr_time.h (original)
> +++ apr/apr/branches/1.6.x/include/apr_time.h Sat Mar  5 01:40:58 2016
> @@ -23,7 +23,6 @@
>   */
>
>  #include "apr.h"
> -#include "apr_pools.h"
>  #include "apr_errno.h"
>
>  #ifdef __cplusplus
> @@ -120,6 +119,9 @@ struct apr_time_exp_t {
>      apr_int32_t tm_gmtoff;
>  };
>
> +/* Delayed the include to avoid a circular reference */
> +#include "apr_pools.h"
> +
>  /**
>   * Convert an ansi time_t to an apr_time_t
>   * @param result the resulting apr_time_t
>
> Modified: apr/apr/branches/1.6.x/include/arch/netware/apr_arch_thread_mutex.h
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/include/arch/netware/apr_arch_thread_mutex.h?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/include/arch/netware/apr_arch_thread_mutex.h (original)
> +++ apr/apr/branches/1.6.x/include/arch/netware/apr_arch_thread_mutex.h Sat Mar  5 01:40:58 2016
> @@ -18,11 +18,14 @@
>  #define THREAD_MUTEX_H
>
>  #include "apr_thread_mutex.h"
> +#include "apr_thread_cond.h"
>  #include <nks/synch.h>
>
>  struct apr_thread_mutex_t {
>      apr_pool_t *pool;
>      NXMutex_t *mutex;
> +    apr_thread_cond_t *cond;
> +    int locked, num_waiters;
>  };
>
>  #endif  /* THREAD_MUTEX_H */
>
> Modified: apr/apr/branches/1.6.x/include/arch/os2/apr_arch_thread_cond.h
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/include/arch/os2/apr_arch_thread_cond.h?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/include/arch/os2/apr_arch_thread_cond.h (original)
> +++ apr/apr/branches/1.6.x/include/arch/os2/apr_arch_thread_cond.h Sat Mar  5 01:40:58 2016
> @@ -22,6 +22,11 @@
>
>  struct apr_thread_cond_t {
>      apr_pool_t *pool;
> +    HEV semaphore;
> +    HMTX mutex;
> +    unsigned long num_waiting;
> +    unsigned long num_wake;
> +    unsigned long generation;
>  };
>
>  #endif  /* THREAD_COND_H */
>
> Modified: apr/apr/branches/1.6.x/include/arch/unix/apr_arch_proc_mutex.h
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/include/arch/unix/apr_arch_proc_mutex.h?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/include/arch/unix/apr_arch_proc_mutex.h (original)
> +++ apr/apr/branches/1.6.x/include/arch/unix/apr_arch_proc_mutex.h Sat Mar  5 01:40:58 2016
> @@ -26,6 +26,7 @@
>  #include "apr_portable.h"
>  #include "apr_file_io.h"
>  #include "apr_arch_file_io.h"
> +#include "apr_time.h"
>
>  /* System headers required by Locks library */
>  #if APR_HAVE_SYS_TYPES_H
> @@ -72,6 +73,7 @@ struct apr_proc_mutex_unix_lock_methods_
>      apr_status_t (*create)(apr_proc_mutex_t *, const char *);
>      apr_status_t (*acquire)(apr_proc_mutex_t *);
>      apr_status_t (*tryacquire)(apr_proc_mutex_t *);
> +    apr_status_t (*timedacquire)(apr_proc_mutex_t *, apr_time_t, int);
>      apr_status_t (*release)(apr_proc_mutex_t *);
>      apr_status_t (*cleanup)(void *);
>      apr_status_t (*child_init)(apr_proc_mutex_t **, apr_pool_t *, const char *);
>
> Modified: apr/apr/branches/1.6.x/include/arch/unix/apr_arch_thread_mutex.h
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/include/arch/unix/apr_arch_thread_mutex.h?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/include/arch/unix/apr_arch_thread_mutex.h (original)
> +++ apr/apr/branches/1.6.x/include/arch/unix/apr_arch_thread_mutex.h Sat Mar  5 01:40:58 2016
> @@ -21,6 +21,7 @@
>  #include "apr_private.h"
>  #include "apr_general.h"
>  #include "apr_thread_mutex.h"
> +#include "apr_thread_cond.h"
>  #include "apr_portable.h"
>  #include "apr_atomic.h"
>
> @@ -32,6 +33,8 @@
>  struct apr_thread_mutex_t {
>      apr_pool_t *pool;
>      pthread_mutex_t mutex;
> +    apr_thread_cond_t *cond;
> +    int locked, num_waiters;
>  };
>  #endif
>
>
> Modified: apr/apr/branches/1.6.x/locks/beos/proc_mutex.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/beos/proc_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/locks/beos/proc_mutex.c (original)
> +++ apr/apr/branches/1.6.x/locks/beos/proc_mutex.c Sat Mar  5 01:40:58 2016
> @@ -27,13 +27,13 @@ static apr_status_t _proc_mutex_cleanup(
>      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
>      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
>  {
>      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;
>
> Modified: apr/apr/branches/1.6.x/locks/beos/thread_cond.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/beos/thread_cond.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/locks/beos/thread_cond.c (original)
> +++ apr/apr/branches/1.6.x/locks/beos/thread_cond.c Sat Mar  5 01:40:58 2016
> @@ -81,7 +81,7 @@ APR_DECLARE(apr_status_t) apr_thread_con
>
>
>  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);
>
> Modified: apr/apr/branches/1.6.x/locks/beos/thread_mutex.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/beos/thread_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/locks/beos/thread_mutex.c (original)
> +++ apr/apr/branches/1.6.x/locks/beos/thread_mutex.c Sat Mar  5 01:40:58 2016
> @@ -27,13 +27,13 @@ static apr_status_t _thread_mutex_cleanu
>      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_mut
>          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_mut
>
>  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_mut
>              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;
>
> Modified: apr/apr/branches/1.6.x/locks/netware/proc_mutex.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/netware/proc_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/locks/netware/proc_mutex.c (original)
> +++ apr/apr/branches/1.6.x/locks/netware/proc_mutex.c Sat Mar  5 01:40:58 2016
> @@ -26,15 +26,24 @@ APR_DECLARE(apr_status_t) apr_proc_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
>      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)
>
> Modified: apr/apr/branches/1.6.x/locks/netware/thread_cond.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/netware/thread_cond.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/locks/netware/thread_cond.c (original)
> +++ apr/apr/branches/1.6.x/locks/netware/thread_cond.c Sat Mar  5 01:40:58 2016
> @@ -66,10 +66,21 @@ APR_DECLARE(apr_status_t) apr_thread_con
>
>  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;
>  }
>
> Modified: apr/apr/branches/1.6.x/locks/netware/thread_mutex.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/netware/thread_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/locks/netware/thread_mutex.c (original)
> +++ apr/apr/branches/1.6.x/locks/netware/thread_mutex.c Sat Mar  5 01:40:58 2016
> @@ -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_mut
>          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_mut
>      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_mut
>
>  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;
>  }
>
> Modified: apr/apr/branches/1.6.x/locks/os2/proc_mutex.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/os2/proc_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/locks/os2/proc_mutex.c (original)
> +++ apr/apr/branches/1.6.x/locks/os2/proc_mutex.c Sat Mar  5 01:40:58 2016
> @@ -80,7 +80,7 @@ APR_DECLARE(apr_status_t) apr_proc_mutex
>      ULONG rc;
>      char *semname;
>
> -    if (mech != APR_LOCK_DEFAULT) {
> +    if (mech != APR_LOCK_DEFAULT && mech != APR_LOCK_DEFAULT_TIMED) {
>          return APR_ENOTIMPL;
>      }
>
> @@ -148,6 +148,42 @@ APR_DECLARE(apr_status_t) apr_proc_mutex
>
>      if (rc == 0) {
>          mutex->owner = CurrentTid;
> +        mutex->lock_count++;
> +    }
> +
> +    return APR_FROM_OS_ERROR(rc);
> +}
> +
> +
> +
> +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++;
>      }
>
>
> Modified: apr/apr/branches/1.6.x/locks/os2/thread_cond.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/os2/thread_cond.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/locks/os2/thread_cond.c (original)
> +++ apr/apr/branches/1.6.x/locks/os2/thread_cond.c Sat Mar  5 01:40:58 2016
> @@ -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)
>
> Modified: apr/apr/branches/1.6.x/locks/os2/thread_mutex.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/os2/thread_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/locks/os2/thread_mutex.c (original)
> +++ apr/apr/branches/1.6.x/locks/os2/thread_mutex.c Sat Mar  5 01:40:58 2016
> @@ -71,6 +71,36 @@ APR_DECLARE(apr_status_t) apr_thread_mut
>
>
>
> +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);
>
> Modified: apr/apr/branches/1.6.x/locks/unix/global_mutex.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/unix/global_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/locks/unix/global_mutex.c (original)
> +++ apr/apr/branches/1.6.x/locks/unix/global_mutex.c Sat Mar  5 01:40:58 2016
> @@ -141,6 +141,40 @@ APR_DECLARE(apr_status_t) apr_global_mut
>      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;
>
> Modified: apr/apr/branches/1.6.x/locks/unix/proc_mutex.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/unix/proc_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/locks/unix/proc_mutex.c (original)
> +++ apr/apr/branches/1.6.x/locks/unix/proc_mutex.c Sat Mar  5 01:40:58 2016
> @@ -184,6 +184,41 @@ static apr_status_t proc_mutex_posix_try
>      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_me
>      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_trya
>      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_me
>      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_pthr
>  #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_me
>      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_try
>      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_me
>      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_try
>      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_me
>      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_me
>          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
>      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);
>
> Modified: apr/apr/branches/1.6.x/locks/unix/thread_cond.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/unix/thread_cond.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/locks/unix/thread_cond.c (original)
> +++ apr/apr/branches/1.6.x/locks/unix/thread_cond.c Sat Mar  5 01:40:58 2016
> @@ -79,21 +79,31 @@ APR_DECLARE(apr_status_t) apr_thread_con
>                                                      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;
>  }
>
> Modified: apr/apr/branches/1.6.x/locks/unix/thread_mutex.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/unix/thread_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/locks/unix/thread_mutex.c (original)
> +++ apr/apr/branches/1.6.x/locks/unix/thread_mutex.c Sat Mar  5 01:40:58 2016
> @@ -77,6 +77,19 @@ APR_DECLARE(apr_status_t) apr_thread_mut
>          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_mut
>  {
>      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_mut
>  {
>      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_mut
>      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_mut
>
>  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)
>
> Modified: apr/apr/branches/1.6.x/locks/win32/proc_mutex.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/win32/proc_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/locks/win32/proc_mutex.c (original)
> +++ apr/apr/branches/1.6.x/locks/win32/proc_mutex.c Sat Mar  5 01:40:58 2016
> @@ -160,6 +160,37 @@ APR_DECLARE(apr_status_t) apr_proc_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) {
>
> Modified: apr/apr/branches/1.6.x/locks/win32/thread_cond.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/win32/thread_cond.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/locks/win32/thread_cond.c (original)
> +++ apr/apr/branches/1.6.x/locks/win32/thread_cond.c Sat Mar  5 01:40:58 2016
> @@ -61,9 +61,9 @@ APR_DECLARE(apr_status_t) apr_thread_con
>      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_c
>  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)
>
> Modified: apr/apr/branches/1.6.x/locks/win32/thread_mutex.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/locks/win32/thread_mutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/locks/win32/thread_mutex.c (original)
> +++ apr/apr/branches/1.6.x/locks/win32/thread_mutex.c Sat Mar  5 01:40:58 2016
> @@ -54,6 +54,10 @@ APR_DECLARE(apr_status_t) apr_thread_mut
>          (*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_mut
>          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_mut
>      }
>      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_mut
>      }
>      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) {
>
> Modified: apr/apr/branches/1.6.x/test/testglobalmutex.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/test/testglobalmutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/test/testglobalmutex.c (original)
> +++ apr/apr/branches/1.6.x/test/testglobalmutex.c Sat Mar  5 01:40:58 2016
> @@ -68,6 +68,7 @@ static const char *mutexname(apr_lockmec
>      case APR_LOCK_PROC_PTHREAD: return "proc_pthread";
>      case APR_LOCK_POSIXSEM: return "posixsem";
>      case APR_LOCK_DEFAULT: return "default";
> +    case APR_LOCK_DEFAULT_TIMED: return "default_timed";
>      default: return "unknown";
>      }
>  }
> @@ -129,6 +130,8 @@ abts_suite *testglobalmutex(abts_suite *
>      mech = APR_LOCK_FLOCK;
>      abts_run_test(suite, test_exclusive, &mech);
>  #endif
> +    mech = APR_LOCK_DEFAULT_TIMED;
> +    abts_run_test(suite, test_exclusive, &mech);
>
>      return suite;
>  }
>
> Modified: apr/apr/branches/1.6.x/test/testlock.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/test/testlock.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/test/testlock.c (original)
> +++ apr/apr/branches/1.6.x/test/testlock.c Sat Mar  5 01:40:58 2016
> @@ -90,7 +90,12 @@ static void *APR_THREAD_FUNC thread_mute
>
>      while (1)
>      {
> -        apr_thread_mutex_lock(thread_mutex);
> +        if (data) {
> +            apr_thread_mutex_timedlock(thread_mutex, *(apr_time_t *)data, 0);
> +        }
> +        else {
> +            apr_thread_mutex_lock(thread_mutex);
> +        }
>          if (i == MAX_ITER)
>              exitLoop = 0;
>          else
> @@ -178,6 +183,38 @@ static void test_thread_mutex(abts_case
>      ABTS_INT_EQUAL(tc, MAX_ITER, x);
>  }
>
> +static void test_thread_timedmutex(abts_case *tc, void *data)
> +{
> +    apr_thread_t *t1, *t2, *t3, *t4;
> +    apr_status_t s1, s2, s3, s4;
> +    apr_time_t timeout;
> +
> +    s1 = apr_thread_mutex_create(&thread_mutex, APR_THREAD_MUTEX_TIMED, p);
> +    ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
> +    ABTS_PTR_NOTNULL(tc, thread_mutex);
> +
> +    i = 0;
> +    x = 0;
> +
> +    timeout = apr_time_from_sec(5);
> +
> +    s1 = apr_thread_create(&t1, NULL, thread_mutex_function, &timeout, p);
> +    ABTS_INT_EQUAL(tc, APR_SUCCESS, s1);
> +    s2 = apr_thread_create(&t2, NULL, thread_mutex_function, &timeout, p);
> +    ABTS_INT_EQUAL(tc, APR_SUCCESS, s2);
> +    s3 = apr_thread_create(&t3, NULL, thread_mutex_function, &timeout, p);
> +    ABTS_INT_EQUAL(tc, APR_SUCCESS, s3);
> +    s4 = apr_thread_create(&t4, NULL, thread_mutex_function, &timeout, p);
> +    ABTS_INT_EQUAL(tc, APR_SUCCESS, s4);
> +
> +    apr_thread_join(&s1, t1);
> +    apr_thread_join(&s2, t2);
> +    apr_thread_join(&s3, t3);
> +    apr_thread_join(&s4, t4);
> +
> +    ABTS_INT_EQUAL(tc, MAX_ITER, x);
> +}
> +
>  static void test_thread_rwlock(abts_case *tc, void *data)
>  {
>      apr_thread_t *t1, *t2, *t3, *t4;
> @@ -305,6 +342,38 @@ static void test_timeoutcond(abts_case *
>                         apr_thread_cond_destroy(timeout_cond));
>  }
>
> +static void test_timeoutmutex(abts_case *tc, void *data)
> +{
> +    apr_status_t s;
> +    apr_time_t begin, end;
> +    apr_time_t timeout;
> +    int i;
> +
> +    s = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_TIMED, p);
> +    ABTS_INT_EQUAL(tc, APR_SUCCESS, s);
> +    ABTS_PTR_NOTNULL(tc, timeout_mutex);
> +
> +    timeout = apr_time_from_sec(5);
> +
> +    ABTS_INT_EQUAL(tc, 0, apr_thread_mutex_lock(timeout_mutex));
> +    for (i = 0; i < MAX_RETRY; i++) {
> +        begin = apr_time_now();
> +        s = apr_thread_mutex_timedlock(timeout_mutex, timeout, 0);
> +        end = apr_time_now();
> +
> +        if (s != APR_SUCCESS && !APR_STATUS_IS_TIMEUP(s)) {
> +            continue;
> +        }
> +        ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(s));
> +        ABTS_ASSERT(tc, "Timer returned too late", end - begin - timeout < 100000);
> +        break;
> +    }
> +    ABTS_ASSERT(tc, "Too many retries", i < MAX_RETRY);
> +    ABTS_INT_EQUAL(tc, 0, apr_thread_mutex_unlock(timeout_mutex));
> +    APR_ASSERT_SUCCESS(tc, "Unable to destroy the mutex",
> +                       apr_thread_mutex_destroy(timeout_mutex));
> +}
> +
>  #endif /* !APR_HAS_THREADS */
>
>  #if !APR_HAS_THREADS
> @@ -323,9 +392,11 @@ abts_suite *testlock(abts_suite *suite)
>      abts_run_test(suite, threads_not_impl, NULL);
>  #else
>      abts_run_test(suite, test_thread_mutex, NULL);
> +    abts_run_test(suite, test_thread_timedmutex, NULL);
>      abts_run_test(suite, test_thread_rwlock, NULL);
>      abts_run_test(suite, test_cond, NULL);
>      abts_run_test(suite, test_timeoutcond, NULL);
> +    abts_run_test(suite, test_timeoutmutex, NULL);
>  #endif
>
>      return suite;
>
> Modified: apr/apr/branches/1.6.x/test/testlockperf.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/test/testlockperf.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/test/testlockperf.c (original)
> +++ apr/apr/branches/1.6.x/test/testlockperf.c Sat Mar  5 01:40:58 2016
> @@ -60,7 +60,12 @@ void * APR_THREAD_FUNC thread_mutex_func
>      int i;
>
>      for (i = 0; i < max_counter; i++) {
> -        apr_thread_mutex_lock(thread_lock);
> +        if (data) {
> +            apr_thread_mutex_timedlock(thread_lock, *(apr_time_t *)data, 0);
> +        }
> +        else {
> +            apr_thread_mutex_lock(thread_lock);
> +        }
>          mutex_counter++;
>          apr_thread_mutex_unlock(thread_lock);
>      }
> @@ -175,6 +180,57 @@ int test_thread_mutex_nested(int num_thr
>      return APR_SUCCESS;
>  }
>
> +static int test_thread_mutex_timed(int num_threads)
> +{
> +    apr_thread_t *t[MAX_THREADS];
> +    apr_status_t s[MAX_THREADS];
> +    apr_time_t time_start, time_stop;
> +    apr_time_t timeout;
> +    int i;
> +
> +    mutex_counter = 0;
> +
> +    timeout = apr_time_from_sec(5);
> +
> +    printf("apr_thread_mutex_t Tests\n");
> +    printf("%-60s", "    Initializing the apr_thread_mutex_t (TIMED)");
> +    s[0] = apr_thread_mutex_create(&thread_lock, APR_THREAD_MUTEX_TIMED, pool);
> +    if (s[0] != APR_SUCCESS) {
> +        printf("Failed!\n");
> +        return s[0];
> +    }
> +    printf("OK\n");
> +
> +    apr_thread_mutex_lock(thread_lock);
> +    /* set_concurrency(4)? -aaron */
> +    printf("    Starting %d threads    ", num_threads);
> +    for (i = 0; i < num_threads; ++i) {
> +        s[i] = apr_thread_create(&t[i], NULL, thread_mutex_func, &timeout, pool);
> +        if (s[i] != APR_SUCCESS) {
> +            printf("Failed!\n");
> +            return s[i];
> +        }
> +    }
> +    printf("OK\n");
> +
> +    time_start = apr_time_now();
> +    apr_thread_mutex_unlock(thread_lock);
> +
> +    /* printf("%-60s", "    Waiting for threads to exit"); */
> +    for (i = 0; i < num_threads; ++i) {
> +        apr_thread_join(&s[i], t[i]);
> +    }
> +    /* printf("OK\n"); */
> +
> +    time_stop = apr_time_now();
> +    printf("microseconds: %" APR_INT64_T_FMT " usec\n",
> +           (time_stop - time_start));
> +    if (mutex_counter != max_counter * num_threads)
> +        printf("error: counter = %ld\n", mutex_counter);
> +
> +    return APR_SUCCESS;
> +}
> +
>  int test_thread_rwlock(int num_threads)
>  {
>      apr_thread_t *t[MAX_THREADS];
> @@ -273,6 +329,12 @@ int main(int argc, const char * const *a
>              exit(-4);
>          }
>
> +        if ((rv = test_thread_mutex_timed(i)) != APR_SUCCESS) {
> +            fprintf(stderr,"thread_mutex (TIMED) test failed : [%d] %s\n",
> +                    rv, apr_strerror(rv, (char*)errmsg, 200));
> +            exit(-5);
> +        }
> +
>          if ((rv = test_thread_rwlock(i)) != APR_SUCCESS) {
>              fprintf(stderr,"thread_rwlock test failed : [%d] %s\n",
>                      rv, apr_strerror(rv, (char*)errmsg, 200));
>
> Modified: apr/apr/branches/1.6.x/test/testmutexscope.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/test/testmutexscope.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/test/testmutexscope.c (original)
> +++ apr/apr/branches/1.6.x/test/testmutexscope.c Sat Mar  5 01:40:58 2016
> @@ -43,20 +43,22 @@ static apr_pool_t *p;
>  static volatile int counter;
>  typedef enum {TEST_GLOBAL, TEST_PROC} test_mode_e;
>
> -static void lock_init(apr_lockmech_e mech, test_mode_e test_mode)
> +static int lock_init(apr_lockmech_e mech, test_mode_e test_mode)
>  {
> +    apr_status_t rv;
>      if (test_mode == TEST_PROC) {
> -        assert(apr_proc_mutex_create(&proc_mutex,
> -                                     NULL,
> -                                     mech,
> -                                     p) == APR_SUCCESS);
> +        rv = apr_proc_mutex_create(&proc_mutex,
> +                                           NULL,
> +                                           mech,
> +                                           p);
>      }
>      else {
> -        assert(apr_global_mutex_create(&global_mutex,
> -                                       NULL,
> -                                       mech,
> -                                       p) == APR_SUCCESS);
> +        rv = apr_global_mutex_create(&global_mutex,
> +                                     NULL,
> +                                     mech,
> +                                     p);
>      }
> +    return rv;
>  }
>
>  static void lock_destroy(test_mode_e test_mode)
> @@ -120,7 +122,17 @@ static void test_mech_mode(apr_lockmech_
>    assert(apr_thread_mutex_create(&thread_mutex, 0, p) == APR_SUCCESS);
>    assert(apr_thread_mutex_lock(thread_mutex) == APR_SUCCESS);
>
> -  lock_init(mech, test_mode);
> +  rv = lock_init(mech, test_mode);
> +  if (rv != APR_SUCCESS) {
> +      char errmsg[256];
> +      printf("%s mutexes with mechanism `%s': %s\n",
> +             test_mode == TEST_GLOBAL ? "Global" : "Proc", mech_name,
> +             apr_strerror(rv, errmsg, sizeof errmsg));
> +      if (rv != APR_ENOTIMPL || mech == APR_LOCK_DEFAULT) {
> +          exit(1);
> +      }
> +      return;
> +  }
>
>    counter = 0;
>
> @@ -142,7 +154,7 @@ static void test_mech_mode(apr_lockmech_
>    apr_sleep(apr_time_from_sec(5));
>
>    if (test_mode == TEST_PROC) {
> -      printf("  Mutex mechanism `%s' is %sglobal in scope on this platform.\n",
> +      printf("  mutex mechanism `%s' is %sglobal in scope on this platform.\n",
>               mech_name, counter == 1 ? "" : "not ");
>    }
>    else {
> @@ -155,7 +167,7 @@ static void test_mech_mode(apr_lockmech_
>            exit(1);
>        }
>        else {
> -          printf("  no problems encountered...\n");
> +          printf("  no problem encountered...\n");
>        }
>    }
>
> @@ -205,6 +217,7 @@ int main(void)
>  #if APR_HAS_PROC_PTHREAD_SERIALIZE
>          ,{APR_LOCK_PROC_PTHREAD, "proc_pthread"}
>  #endif
> +        ,{APR_LOCK_DEFAULT_TIMED, "default_timed"}
>      };
>      int i;
>
>
> Modified: apr/apr/branches/1.6.x/test/testprocmutex.c
> URL: http://svn.apache.org/viewvc/apr/apr/branches/1.6.x/test/testprocmutex.c?rev=1733684&r1=1733683&r2=1733684&view=diff
> ==============================================================================
> --- apr/apr/branches/1.6.x/test/testprocmutex.c (original)
> +++ apr/apr/branches/1.6.x/test/testprocmutex.c Sat Mar  5 01:40:58 2016
> @@ -35,6 +35,11 @@
>  static apr_proc_mutex_t *proc_lock;
>  static volatile int *x;
>
> +typedef struct lockmech {
> +    apr_lockmech_e num;
> +    const char *name;
> +} lockmech_t;
> +
>  /* a slower more racy way to implement (*x)++ */
>  static int increment(int n)
>  {
> @@ -68,7 +73,7 @@ static void make_child(abts_case *tc, in
>              exit(1);
>
>          do {
> -            if (trylock) {
> +            if (trylock > 0) {
>                  int wait_usec = 0;
>
>                  while ((rv = apr_proc_mutex_trylock(proc_lock))) {
> @@ -79,6 +84,16 @@ static void make_child(abts_case *tc, in
>                      apr_sleep(1);
>                  }
>              }
> +            else if (trylock < 0) {
> +                int wait_usec = 0;
> +
> +                while ((rv = apr_proc_mutex_timedlock(proc_lock, 1, 0))) {
> +                    if (!APR_STATUS_IS_TIMEUP(rv))
> +                        exit(1);
> +                    if (++wait_usec >= MAX_WAIT_USEC)
> +                        exit(1);
> +                }
> +            }
>              else {
>                  if (apr_proc_mutex_lock(proc_lock))
>                      exit(1);
> @@ -108,16 +123,21 @@ static void await_child(abts_case *tc, a
>  }
>
>  static void test_exclusive(abts_case *tc, const char *lockname,
> -                           apr_lockmech_e mech)
> +                           lockmech_t *mech)
>  {
>      apr_proc_t *child[CHILDREN];
>      apr_status_t rv;
>      int n;
>
> -    rv = apr_proc_mutex_create(&proc_lock, lockname, mech, p);
> +    rv = apr_proc_mutex_create(&proc_lock, lockname, mech->num, p);
>      APR_ASSERT_SUCCESS(tc, "create the mutex", rv);
> -    if (rv != APR_SUCCESS)
> +    if (rv != APR_SUCCESS) {
> +        fprintf(stderr, "%s not implemented, ", mech->name);
> +        ABTS_ASSERT(tc, "Default timed not implemented",
> +                    mech->num != APR_LOCK_DEFAULT &&
> +                    mech->num != APR_LOCK_DEFAULT_TIMED);
>          return;
> +    }
>
>      for (n = 0; n < CHILDREN; n++)
>          make_child(tc, 0, &child[n], p);
> @@ -129,24 +149,52 @@ static void test_exclusive(abts_case *tc
>
>      rv = apr_proc_mutex_trylock(proc_lock);
>      if (rv == APR_ENOTIMPL) {
> -        ABTS_NOT_IMPL(tc, "apr_proc_mutex_trylock not implemented");
> -        return;
> +        fprintf(stderr, "%s_trylock() not implemented, ", mech->name);
> +        ABTS_ASSERT(tc, "Default timed trylock not implemented",
> +                    mech->num != APR_LOCK_DEFAULT &&
> +                    mech->num != APR_LOCK_DEFAULT_TIMED);
>      }
> -    APR_ASSERT_SUCCESS(tc, "check for trylock", rv);
> +    else {
> +        APR_ASSERT_SUCCESS(tc, "check for trylock", rv);
>
> -    rv = apr_proc_mutex_unlock(proc_lock);
> -    APR_ASSERT_SUCCESS(tc, "unlock after trylock check", rv);
> +        rv = apr_proc_mutex_unlock(proc_lock);
> +        APR_ASSERT_SUCCESS(tc, "unlock after trylock check", rv);
>
> -    *x = 0;
> +        *x = 0;
>
> -    for (n = 0; n < CHILDREN; n++)
> -        make_child(tc, 1, &child[n], p);
> +        for (n = 0; n < CHILDREN; n++)
> +            make_child(tc, 1, &child[n], p);
> +
> +        for (n = 0; n < CHILDREN; n++)
> +            await_child(tc, child[n]);
> +
> +        ABTS_ASSERT(tc, "Locks don't appear to work with trylock",
> +                    *x == MAX_COUNTER);
> +    }
>
> -    for (n = 0; n < CHILDREN; n++)
> -        await_child(tc, child[n]);
> -
> -    ABTS_ASSERT(tc, "Locks don't appear to work with trylock",
> -                *x == MAX_COUNTER);
> +    rv = apr_proc_mutex_timedlock(proc_lock, 1, 0);
> +    if (rv == APR_ENOTIMPL) {
> +        fprintf(stderr, "%s_timedlock() not implemented, ", mech->name);
> +        ABTS_ASSERT(tc, "Default timed timedlock not implemented",
> +                    mech->num != APR_LOCK_DEFAULT_TIMED);
> +    }
> +    else {
> +        APR_ASSERT_SUCCESS(tc, "check for timedlock", rv);
> +
> +        rv = apr_proc_mutex_unlock(proc_lock);
> +        APR_ASSERT_SUCCESS(tc, "unlock after timedlock check", rv);
> +
> +        *x = 0;
> +
> +        for (n = 0; n < CHILDREN; n++)
> +            make_child(tc, -1, &child[n], p);
> +
> +        for (n = 0; n < CHILDREN; n++)
> +            await_child(tc, child[n]);
> +
> +        ABTS_ASSERT(tc, "Locks don't appear to work with timedlock",
> +                    *x == MAX_COUNTER);
> +    }
>  }
>  #endif
>
> @@ -156,7 +204,6 @@ static void proc_mutex(abts_case *tc, vo
>      apr_status_t rv;
>      const char *shmname = "tpm.shm";
>      apr_shm_t *shm;
> -    apr_lockmech_e *mech = data;
>
>      /* Use anonymous shm if available. */
>      rv = apr_shm_create(&shm, sizeof(int), NULL, p);
> @@ -170,7 +217,7 @@ static void proc_mutex(abts_case *tc, vo
>          return;
>
>      x = apr_shm_baseaddr_get(shm);
> -    test_exclusive(tc, NULL, *mech);
> +    test_exclusive(tc, NULL, data);
>      rv = apr_shm_destroy(shm);
>      APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv);
>  #else
> @@ -181,30 +228,30 @@ static void proc_mutex(abts_case *tc, vo
>
>  abts_suite *testprocmutex(abts_suite *suite)
>  {
> -    apr_lockmech_e mech = APR_LOCK_DEFAULT;
> -
> -    suite = ADD_SUITE(suite)
> -    abts_run_test(suite, proc_mutex, &mech);
> -#if APR_HAS_POSIXSEM_SERIALIZE
> -    mech = APR_LOCK_POSIXSEM;
> -    abts_run_test(suite, proc_mutex, &mech);
> +    lockmech_t lockmechs[] = {
> +        {APR_LOCK_DEFAULT, "default"}
> +#if APR_HAS_FLOCK_SERIALIZE
> +        ,{APR_LOCK_FLOCK, "flock"}
>  #endif
>  #if APR_HAS_SYSVSEM_SERIALIZE
> -    mech = APR_LOCK_SYSVSEM;
> -    abts_run_test(suite, proc_mutex, &mech);
> +        ,{APR_LOCK_SYSVSEM, "sysvsem"}
>  #endif
> -#if APR_HAS_PROC_PTHREAD_SERIALIZE
> -    mech = APR_LOCK_PROC_PTHREAD;
> -    abts_run_test(suite, proc_mutex, &mech);
> +#if APR_HAS_POSIXSEM_SERIALIZE
> +        ,{APR_LOCK_POSIXSEM, "posix"}
>  #endif
>  #if APR_HAS_FCNTL_SERIALIZE
> -    mech = APR_LOCK_FCNTL;
> -    abts_run_test(suite, proc_mutex, &mech);
> +        ,{APR_LOCK_FCNTL, "fcntl"}
>  #endif
> -#if APR_HAS_FLOCK_SERIALIZE
> -    mech = APR_LOCK_FLOCK;
> -    abts_run_test(suite, proc_mutex, &mech);
> +#if APR_HAS_PROC_PTHREAD_SERIALIZE
> +        ,{APR_LOCK_PROC_PTHREAD, "proc_pthread"}
>  #endif
> +        ,{APR_LOCK_DEFAULT_TIMED, "default_timed"}
> +    };
> +    int i;
>
> +    suite = ADD_SUITE(suite)
> +    for (i = 0; i < sizeof(lockmechs) / sizeof(lockmechs[0]); i++) {
> +        abts_run_test(suite, proc_mutex, &lockmechs[i]);
> +    }
>      return suite;
>  }