summaryrefslogtreecommitdiff
path: root/locks/unix/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'locks/unix/misc.c')
-rw-r--r--locks/unix/misc.c74
1 files changed, 74 insertions, 0 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 */