diff options
author | Jim Jagielski <jim@apache.org> | 2017-04-04 19:08:39 +0000 |
---|---|---|
committer | Jim Jagielski <jim@apache.org> | 2017-04-04 19:08:39 +0000 |
commit | 684d6631b756d53a3d305296954203047c2754d5 (patch) | |
tree | d5eb1d42e256493b05bb414edbda4c394fbcc333 /locks | |
parent | 8e2fbbac09a3a387d97384f8db9866d6766b758f (diff) | |
download | apr-684d6631b756d53a3d305296954203047c2754d5.tar.gz |
the rest
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1790157 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'locks')
-rw-r--r-- | locks/unix/misc.c | 227 |
1 files changed, 180 insertions, 47 deletions
diff --git a/locks/unix/misc.c b/locks/unix/misc.c index 84a4a073a..b3bc21828 100644 --- a/locks/unix/misc.c +++ b/locks/unix/misc.c @@ -18,61 +18,194 @@ #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); +#if APR_HAS_THREADS +#if APR_HAS_SYSVSEM_SERIALIZE +#if !HAVE_SEMTIMEDOP +#include <sys/sem.h> +#endif +#endif #define SLEEP_TIME_NS 10000000 #define NANOSECS_PER_SEC 1000000000 +extern int errno; + +#ifndef HAVE_PTHREAD_MUTEX_TIMEDLOCK +extern int pthread_mutex_timedlock(pthread_mutex_t * mutex, + const struct timespec *abs_timeout); /* -* 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) + * 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; + 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 = *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)); - } - /* If we had a REALLY small timeout ;) */ - if (remaining.tv_sec < 0) { - return pthread_mutex_trylock(mutex); - } - 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; - } - } + 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)); + } + /* If we had a REALLY small timeout ;) */ + if (remaining.tv_sec < 0) { + return ETIMEDOUT; + } + 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; + return rv; } - #endif /* HAVE_PTHREAD_MUTEX_TIMEDLOCK */ + +#if APR_HAS_POSIXSEM_SERIALIZE +#if !HAVE_SEM_TIMEDWAIT +extern int sem_timedwait(sem_t * sem, const struct timespec *abs_timeout); +/* + * A sem_timedwait() impl for OSX/macOS, which lacks the + * real thing. + */ +int sem_timedwait(sem_t * sem, 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)); + } + /* If we had a REALLY small timeout ;) */ + if (remaining.tv_sec < 0) { + return ETIMEDOUT; + } + errno = 0; + while (((rv = sem_trywait(sem)) != 0) && (errno == EAGAIN)) { + 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_SEM_TIMEDWAIT */ +#endif /* APR_HAS_POSIXSEM_SERIALIZE */ + +#if APR_HAS_SYSVSEM_SERIALIZE +#if !HAVE_SEMTIMEDOP +extern int semtimedop(int semid, struct sembuf *sops, unsigned nsops, + const struct timespec *abs_timeout); +/* + * A semtimedop() impl for OSX/macOS, which lacks the + * real thing. + */ +int semtimedop(int semid, struct sembuf *sops, unsigned nsops, + const struct timespec *abs_timeout) +{ + int rv; + struct timespec remaining, ts, tod; + apr_time_t now; + struct sembuf proc_mutex_op_try; + + proc_mutex_op_try.sem_num = 0; + proc_mutex_op_try.sem_op = -1; + proc_mutex_op_try.sem_flg = SEM_UNDO | IPC_NOWAIT; + + 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)); + } + /* If we had a REALLY small timeout ;) */ + if (remaining.tv_sec < 0) { + return ETIMEDOUT; + } + errno = 0; + while (((rv = semop(semid, &proc_mutex_op_try, nsops)) != 0) + && (errno == EAGAIN)) { + 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_SEMTIMEDOP */ +#endif /* APR_HAS_SYSVSEM_SERIALIZE */ + + #endif /* APR_HAS_THREADS */ |