diff options
-rw-r--r-- | locks/unix/misc.c | 74 | ||||
-rw-r--r-- | locks/unix/proc_mutex.c | 10 | ||||
-rw-r--r-- | locks/unix/thread_mutex.c | 67 | ||||
-rw-r--r-- | test/testlock.c | 2 |
4 files changed, 83 insertions, 70 deletions
diff --git a/locks/unix/misc.c b/locks/unix/misc.c new file mode 100644 index 000000000..3aacfe71d --- /dev/null +++ b/locks/unix/misc.c @@ -0,0 +1,74 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_private.h" +#include "apr_arch_thread_mutex.h" +#define APR_WANT_MEMFUNC +#include "apr_want.h" +#include <stdio.h> +#if APR_HAS_THREADS + +#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK +extern int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abs_timeout); +#define SLEEP_TIME_NS 10000000 +#define NANOSECS_PER_SEC 1000000000 +/* +* A pthread_mutex_timedlock() impl for OSX/macOS, which lacks the +* real thing. +* NOTE: Unlike the real McCoy, won't return EOWNERDEAD, EDEADLK +* or EOWNERDEAD +*/ +int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abs_timeout) +{ + int rv; + struct timespec remaining, ts, tod; + apr_time_t now; + + remaining = *abs_timeout; + now = apr_time_now(); + tod.tv_sec = apr_time_sec(now); + tod.tv_nsec = apr_time_usec(now) * 1000; /* nanoseconds */ + + remaining.tv_sec -= tod.tv_sec; + if (tod.tv_nsec <= remaining.tv_nsec) { + remaining.tv_nsec -= tod.tv_nsec; + } + else { + remaining.tv_sec--; + remaining.tv_nsec = (NANOSECS_PER_SEC - (tod.tv_nsec - remaining.tv_nsec)); + } + while ((rv = pthread_mutex_trylock(mutex)) == EBUSY) { + ts.tv_sec = 0; + ts.tv_nsec = (remaining.tv_sec > 0 ? SLEEP_TIME_NS : + (remaining.tv_nsec < SLEEP_TIME_NS ? remaining.tv_nsec : SLEEP_TIME_NS)); + nanosleep(&ts, &ts); + if (ts.tv_nsec <= remaining.tv_nsec) { + remaining.tv_nsec -= ts.tv_nsec; + } + else { + remaining.tv_sec--; + remaining.tv_nsec = (NANOSECS_PER_SEC - (ts.tv_nsec - remaining.tv_nsec)); + } + if (remaining.tv_sec < 0 || (!remaining.tv_sec && remaining.tv_nsec <= SLEEP_TIME_NS)) { + return ETIMEDOUT; + } + } + + return rv; +} + +#endif /* HAVE_PTHREAD_MUTEX_TIMEDLOCK */ +#endif /* APR_HAS_THREADS */ diff --git a/locks/unix/proc_mutex.c b/locks/unix/proc_mutex.c index e66f2674a..9ef996204 100644 --- a/locks/unix/proc_mutex.c +++ b/locks/unix/proc_mutex.c @@ -648,7 +648,9 @@ static apr_status_t proc_mutex_pthread_timedacquire(apr_proc_mutex_t *mutex, apr_time_t timeout, int absolute) { -#ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK +#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK +extern int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abs_timeout); +#endif if (timeout < 0) { return proc_mutex_pthread_acquire(mutex); } @@ -683,9 +685,6 @@ static apr_status_t proc_mutex_pthread_timedacquire(apr_proc_mutex_t *mutex, } mutex->curr_locked = 1; return APR_SUCCESS; -#else - return APR_ENOTIMPL; -#endif } static apr_status_t proc_mutex_pthread_release(apr_proc_mutex_t *mutex) @@ -1214,8 +1213,7 @@ static apr_status_t proc_mutex_choose_method(apr_proc_mutex_t *new_mutex, break; case APR_LOCK_DEFAULT_TIMED: #if APR_HAS_PROC_PTHREAD_SERIALIZE \ - && defined(HAVE_PTHREAD_MUTEX_ROBUST) \ - && defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK) + && defined(HAVE_PTHREAD_MUTEX_ROBUST) new_mutex->meth = &mutex_proc_pthread_methods; #elif APR_HAS_SYSVSEM_SERIALIZE \ && defined(HAVE_SEMTIMEDOP) diff --git a/locks/unix/thread_mutex.c b/locks/unix/thread_mutex.c index fe515b2e6..5c6716658 100644 --- a/locks/unix/thread_mutex.c +++ b/locks/unix/thread_mutex.c @@ -77,19 +77,6 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex, return rv; } -#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK - if (flags & APR_THREAD_MUTEX_TIMED) { - rv = apr_thread_cond_create(&new_mutex->cond, pool); - if (rv) { -#ifdef HAVE_ZOS_PTHREADS - rv = errno; -#endif - pthread_mutex_destroy(&new_mutex->mutex); - return rv; - } - } -#endif - apr_pool_cleanup_register(new_mutex->pool, new_mutex, thread_mutex_cleanup, apr_pool_cleanup_null); @@ -195,7 +182,10 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex, { apr_status_t rv = APR_ENOTIMPL; -#ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK +#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK +extern int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abs_timeout); +#endif + if (timeout < 0) { rv = pthread_mutex_lock(&mutex->mutex); if (rv) { @@ -223,55 +213,6 @@ APR_DECLARE(apr_status_t) apr_thread_mutex_timedlock(apr_thread_mutex_t *mutex, } } } - -#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; } diff --git a/test/testlock.c b/test/testlock.c index a36720b84..45eddb02e 100644 --- a/test/testlock.c +++ b/test/testlock.c @@ -365,7 +365,7 @@ static void test_timeoutmutex(abts_case *tc, void *data) continue; } ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(s)); - ABTS_ASSERT(tc, "Timer returned too late", end - begin - timeout < 100000); + ABTS_ASSERT(tc, "Timer returned too late", end - begin - timeout < 1000000); break; } ABTS_ASSERT(tc, "Too many retries", i < MAX_RETRY); |