diff options
author | Yann Ylavic <ylavic@apache.org> | 2015-03-19 23:38:38 +0000 |
---|---|---|
committer | Yann Ylavic <ylavic@apache.org> | 2015-03-19 23:38:38 +0000 |
commit | 90c4770899c4c45288e1cd1cb0277324a7d3bdbf (patch) | |
tree | db6a0ab5bc8d6b81c56cd429c0b9bda4383c15ec /test/testprocmutex.c | |
parent | c94867c4cd3211541e22b5a293ee96398c886e9c (diff) | |
download | apr-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.c | 119 |
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; } |