summaryrefslogtreecommitdiffstats
path: root/src/darwin/sem_darwin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/darwin/sem_darwin.c')
-rw-r--r--src/darwin/sem_darwin.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/darwin/sem_darwin.c b/src/darwin/sem_darwin.c
new file mode 100644
index 0000000..0ace564
--- /dev/null
+++ b/src/darwin/sem_darwin.c
@@ -0,0 +1,68 @@
+// Copyright 2012-2022 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#include "zix/sem.h"
+
+#include "zix/status.h"
+
+#include <mach/mach.h>
+
+#include <stdint.h>
+#include <time.h>
+
+ZixStatus
+zix_sem_init(ZixSem* sem, unsigned val)
+{
+ return semaphore_create(
+ mach_task_self(), &sem->sem, SYNC_POLICY_FIFO, (int)val)
+ ? ZIX_STATUS_ERROR
+ : ZIX_STATUS_SUCCESS;
+}
+
+ZixStatus
+zix_sem_destroy(ZixSem* sem)
+{
+ return semaphore_destroy(mach_task_self(), sem->sem) ? ZIX_STATUS_ERROR
+ : ZIX_STATUS_SUCCESS;
+}
+
+ZixStatus
+zix_sem_post(ZixSem* sem)
+{
+ return semaphore_signal(sem->sem) ? ZIX_STATUS_ERROR : ZIX_STATUS_SUCCESS;
+}
+
+ZixStatus
+zix_sem_wait(ZixSem* sem)
+{
+ kern_return_t r = 0;
+ while ((r = semaphore_wait(sem->sem)) && r == KERN_ABORTED) {
+ // Interrupted, try again
+ }
+
+ return r ? ZIX_STATUS_ERROR : ZIX_STATUS_SUCCESS;
+}
+
+ZixStatus
+zix_sem_try_wait(ZixSem* sem)
+{
+ const mach_timespec_t zero = {0, 0};
+ const kern_return_t r = semaphore_timedwait(sem->sem, zero);
+
+ return (r == KERN_SUCCESS) ? ZIX_STATUS_SUCCESS
+ : (r == KERN_OPERATION_TIMED_OUT) ? ZIX_STATUS_UNAVAILABLE
+ : ZIX_STATUS_ERROR;
+}
+
+ZixStatus
+zix_sem_timed_wait(ZixSem* sem,
+ const uint32_t seconds,
+ const uint32_t nanoseconds)
+{
+ const mach_timespec_t interval = {seconds, (clock_res_t)nanoseconds};
+ const kern_return_t r = semaphore_timedwait(sem->sem, interval);
+
+ return (r == KERN_SUCCESS) ? ZIX_STATUS_SUCCESS
+ : (r == KERN_OPERATION_TIMED_OUT) ? ZIX_STATUS_TIMEOUT
+ : ZIX_STATUS_ERROR;
+}