darwin_semaphore.h raw
1 /*
2 * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
3 * Copyright (c) 1996 by Silicon Graphics. All rights reserved.
4 * Copyright (c) 1998 by Fergus Henderson. All rights reserved.
5 * Copyright (c) 2000-2009 by Hewlett-Packard Development Company.
6 * All rights reserved.
7 *
8 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
9 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
10 *
11 * Permission is hereby granted to use or copy this program
12 * for any purpose, provided the above notices are retained on all copies.
13 * Permission to modify the code and to distribute modified code is granted,
14 * provided the above notices are retained, and a notice that the code was
15 * modified is included with the above copyright notice.
16 */
17
18 #ifndef GC_DARWIN_SEMAPHORE_H
19 #define GC_DARWIN_SEMAPHORE_H
20
21 #include "gc_priv.h"
22
23 /*
24 * This is a very simple semaphore implementation based on `pthreads`.
25 * It is not async-signal safe. But this is not a problem because
26 * signals are not used to suspend threads on the target.
27 */
28
29 #if !defined(DARWIN) && !defined(GC_WIN32_THREADS) || !defined(GC_PTHREADS)
30 # error darwin_semaphore.h included for improper target
31 #endif
32
33 #include <errno.h>
34
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38
39 typedef struct {
40 pthread_mutex_t mutex;
41 pthread_cond_t cond;
42 int value;
43 } sem_t;
44
45 GC_INLINE int
46 sem_init(sem_t *sem, int pshared, int value)
47 {
48 int err;
49
50 if (UNLIKELY(pshared != 0)) {
51 errno = EPERM; /*< unsupported */
52 return -1;
53 }
54 sem->value = value;
55 err = pthread_mutex_init(&sem->mutex, NULL);
56 if (UNLIKELY(err != 0)) {
57 errno = err;
58 return -1;
59 }
60 err = pthread_cond_init(&sem->cond, NULL);
61 if (UNLIKELY(err != 0)) {
62 (void)pthread_mutex_destroy(&sem->mutex);
63 errno = err;
64 return -1;
65 }
66 return 0;
67 }
68
69 GC_INLINE int
70 sem_post(sem_t *sem)
71 {
72 int err = pthread_mutex_lock(&sem->mutex);
73
74 if (UNLIKELY(err != 0)) {
75 errno = err;
76 return -1;
77 }
78 sem->value++;
79 err = pthread_cond_signal(&sem->cond);
80 if (UNLIKELY(err != 0)) {
81 (void)pthread_mutex_unlock(&sem->mutex);
82 errno = err;
83 return -1;
84 }
85 err = pthread_mutex_unlock(&sem->mutex);
86 if (UNLIKELY(err != 0)) {
87 errno = err;
88 return -1;
89 }
90 return 0;
91 }
92
93 GC_INLINE int
94 sem_wait(sem_t *sem)
95 {
96 int err = pthread_mutex_lock(&sem->mutex);
97
98 if (UNLIKELY(err != 0)) {
99 errno = err;
100 return -1;
101 }
102 while (0 == sem->value) {
103 err = pthread_cond_wait(&sem->cond, &sem->mutex);
104 if (UNLIKELY(err != 0)) {
105 (void)pthread_mutex_unlock(&sem->mutex);
106 errno = err;
107 return -1;
108 }
109 }
110 sem->value--;
111 err = pthread_mutex_unlock(&sem->mutex);
112 if (UNLIKELY(err != 0)) {
113 errno = err;
114 return -1;
115 }
116 return 0;
117 }
118
119 GC_INLINE int
120 sem_destroy(sem_t *sem)
121 {
122 int err = pthread_cond_destroy(&sem->cond);
123
124 if (UNLIKELY(err != 0)) {
125 errno = err;
126 return -1;
127 }
128 err = pthread_mutex_destroy(&sem->mutex);
129 if (UNLIKELY(err != 0)) {
130 errno = err;
131 return -1;
132 }
133 return 0;
134 }
135
136 #ifdef __cplusplus
137 } /* extern "C" */
138 #endif
139
140 #endif
141