From 288882b198de154e0fa38cec3704cae374ec41dc Mon Sep 17 00:00:00 2001 From: Jim Jagielski Date: Tue, 4 Apr 2017 13:14:15 +0000 Subject: Add in our own pthread_mutex_timedlock impl for those OSs, like osx/macos that don't have it. Be a bit more generous in the test git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1790107 13f79535-47bb-0310-9956-ffa450edef68 --- locks/unix/misc.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++ locks/unix/proc_mutex.c | 10 +++---- locks/unix/thread_mutex.c | 67 +++--------------------------------------- 3 files changed, 82 insertions(+), 69 deletions(-) create mode 100644 locks/unix/misc.c (limited to 'locks') 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 +#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; } -- cgit v1.2.1