summaryrefslogtreecommitdiff
path: root/test/testprocmutex.c
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2015-03-19 23:38:38 +0000
committerYann Ylavic <ylavic@apache.org>2015-03-19 23:38:38 +0000
commit90c4770899c4c45288e1cd1cb0277324a7d3bdbf (patch)
treedb6a0ab5bc8d6b81c56cd429c0b9bda4383c15ec /test/testprocmutex.c
parentc94867c4cd3211541e22b5a293ee96398c886e9c (diff)
downloadapr-90c4770899c4c45288e1cd1cb0277324a7d3bdbf.tar.gz
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. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1667900 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'test/testprocmutex.c')
-rw-r--r--test/testprocmutex.c119
1 files changed, 83 insertions, 36 deletions
diff --git a/test/testprocmutex.c b/test/testprocmutex.c
index 78b2efc4c..f2992de9e 100644
--- a/test/testprocmutex.c
+++ b/test/testprocmutex.c
@@ -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, int trylock, apr_proc_t **proc, apr_pool_t
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, int trylock, apr_proc_t **proc, apr_pool_t
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, apr_proc_t *proc)
}
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, const char *lockname,
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, void *data)
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, void *data)
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, void *data)
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;
}