summaryrefslogtreecommitdiff
path: root/locks
diff options
context:
space:
mode:
authorJim Jagielski <jim@apache.org>2017-04-04 19:08:39 +0000
committerJim Jagielski <jim@apache.org>2017-04-04 19:08:39 +0000
commit684d6631b756d53a3d305296954203047c2754d5 (patch)
treed5eb1d42e256493b05bb414edbda4c394fbcc333 /locks
parent8e2fbbac09a3a387d97384f8db9866d6766b758f (diff)
downloadapr-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.c227
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 */