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 yla...@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;
 }

Reply via email to