Ticket #61115: darwin_compat.c

File darwin_compat.c, 6.2 KB (added by ballapete (Peter "Pete" Dyballa), 4 years ago)

Darwin C compitability file for npth

Line 
1 /*
2  * Source: https://github.com/pktgen/sshfs/blob/master/compat/darwin_compat.c
3  * Copyright (c) 2006-2008 Amit Singh/Google Inc.
4  * Copyright (c) 2012 Anatol Pomozov
5  * Copyright (c) 2011-2013 Benjamin Fleischer
6  */
7
8 #include "darwin_compat.h"
9
10 #include <assert.h>
11 #include <errno.h>
12 #include <sys/types.h>
13
14 /*
15  * Semaphore implementation based on:
16  *
17  * Copyright (C) 2000,02 Free Software Foundation, Inc.
18  * This file is part of the GNU C Library.
19  * Written by Ga<EB>l Le Mignot <address@hidden>
20  *
21  * The GNU C Library is free software; you can redistribute it and/or
22  * modify it under the terms of the GNU Library General Public License as
23  * published by the Free Software Foundation; either version 2 of the
24  * License, or (at your option) any later version.
25  *
26  * The GNU C Library is distributed in the hope that it will be useful,
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
29  * Library General Public License for more details.
30  *
31  * You should have received a copy of the GNU Library General Public
32  * License along with the GNU C Library; see the file COPYING.LIB.  If not,
33  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
34  * Boston, MA 02111-1307, USA.
35  */
36
37 /* Semaphores */
38
39 #define __SEM_ID_NONE  ((int)0x0)
40 #define __SEM_ID_LOCAL ((int)0xcafef00d)
41
42 /* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_init.html */
43 int
44 darwin_sem_init(darwin_sem_t *sem, int pshared, unsigned int value)
45 {
46     if (pshared) {
47         errno = ENOSYS;
48         return -1;
49     }
50
51     sem->id = __SEM_ID_NONE;
52
53     if (pthread_cond_init(&sem->__data.local.count_cond, NULL)) {
54         goto cond_init_fail;
55     }
56
57     if (pthread_mutex_init(&sem->__data.local.count_lock, NULL)) {
58         goto mutex_init_fail;
59     }
60
61     sem->__data.local.count = value;
62     sem->id = __SEM_ID_LOCAL;
63
64     return 0;
65
66 mutex_init_fail:
67
68     pthread_cond_destroy(&sem->__data.local.count_cond);
69
70 cond_init_fail:
71
72     return -1;
73 }
74
75 /* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_destroy.html */
76 int
77 darwin_sem_destroy(darwin_sem_t *sem)
78 {
79     int res = 0;
80
81     pthread_mutex_lock(&sem->__data.local.count_lock);
82
83     sem->id = __SEM_ID_NONE;
84     pthread_cond_broadcast(&sem->__data.local.count_cond);
85
86     if (pthread_cond_destroy(&sem->__data.local.count_cond)) {
87         res = -1;
88     }
89
90     pthread_mutex_unlock(&sem->__data.local.count_lock);
91
92     if (pthread_mutex_destroy(&sem->__data.local.count_lock)) {
93         res = -1;
94     }
95
96     return res;
97 }
98
99 int
100 darwin_sem_getvalue(darwin_sem_t *sem, unsigned int *sval)
101 {
102     int res = 0;
103
104     pthread_mutex_lock(&sem->__data.local.count_lock);
105
106     if (sem->id != __SEM_ID_LOCAL) {
107         res = -1;
108         errno = EINVAL;
109     } else {
110         *sval = sem->__data.local.count;
111     }
112
113     pthread_mutex_unlock(&sem->__data.local.count_lock);
114
115     return res;
116 }
117
118 /* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_post.html */
119 int
120 darwin_sem_post(darwin_sem_t *sem)
121 {
122     int res = 0;
123
124     pthread_mutex_lock(&sem->__data.local.count_lock);
125
126     if (sem->id != __SEM_ID_LOCAL) {
127         res = -1;
128         errno = EINVAL;
129     } else if (sem->__data.local.count < DARWIN_SEM_VALUE_MAX) {
130         sem->__data.local.count++;
131         if (sem->__data.local.count == 1) {
132             pthread_cond_signal(&sem->__data.local.count_cond);
133         }
134     } else {
135         errno = ERANGE;
136         res = -1;
137     }
138
139     pthread_mutex_unlock(&sem->__data.local.count_lock);
140
141     return res;
142 }
143
144 /* http://www.opengroup.org/onlinepubs/009695399/functions/sem_timedwait.html */
145 int
146 darwin_sem_timedwait(darwin_sem_t *sem, const struct timespec *abs_timeout)
147 {
148     int res = 0;
149
150     if (abs_timeout &&
151         (abs_timeout->tv_nsec < 0 || abs_timeout->tv_nsec >= 1000000000)) {
152         errno = EINVAL;
153         return -1;
154     }
155
156     pthread_cleanup_push((void(*)(void*))&pthread_mutex_unlock,
157                  &sem->__data.local.count_lock);
158
159     pthread_mutex_lock(&sem->__data.local.count_lock);
160
161     if (sem->id != __SEM_ID_LOCAL) {
162         errno = EINVAL;
163         res = -1;
164     } else {
165         if (!sem->__data.local.count) {
166             res = pthread_cond_timedwait(&sem->__data.local.count_cond,
167                              &sem->__data.local.count_lock,
168                              abs_timeout);
169         }
170         if (res) {
171             assert(res == ETIMEDOUT);
172             res = -1;
173             errno = ETIMEDOUT;
174         } else if (sem->id != __SEM_ID_LOCAL) {
175             res = -1;
176             errno = EINVAL;
177         } else {
178             sem->__data.local.count--;
179         }
180     }
181
182     pthread_cleanup_pop(1);
183
184     return res;
185 }
186
187 /* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_trywait.html */
188 int
189 darwin_sem_trywait(darwin_sem_t *sem)
190 {
191     int res = 0;
192
193     pthread_mutex_lock(&sem->__data.local.count_lock);
194
195     if (sem->id != __SEM_ID_LOCAL) {
196         res = -1;
197         errno = EINVAL;
198     } else if (sem->__data.local.count) {
199         sem->__data.local.count--;
200     } else {
201         res = -1;
202         errno = EAGAIN;
203     }
204
205     pthread_mutex_unlock (&sem->__data.local.count_lock);
206
207     return res;
208 }
209
210 /* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_wait.html */
211 int
212 darwin_sem_wait(darwin_sem_t *sem)
213 {
214     int res = 0;
215
216     pthread_cleanup_push((void(*)(void*))&pthread_mutex_unlock,
217                  &sem->__data.local.count_lock);
218
219     pthread_mutex_lock(&sem->__data.local.count_lock);
220
221     if (sem->id != __SEM_ID_LOCAL) {
222         errno = EINVAL;
223         res = -1;
224     } else {
225         if (!sem->__data.local.count) {
226             pthread_cond_wait(&sem->__data.local.count_cond,
227                       &sem->__data.local.count_lock);
228             if (!sem->__data.local.count) {
229                 /* spurious wakeup, assume it is an interruption */
230                 res = -1;
231                 errno = EINTR;
232                 goto out;
233             }
234         }
235         if (sem->id != __SEM_ID_LOCAL) {
236             res = -1;
237             errno = EINVAL;
238         } else {
239             sem->__data.local.count--;
240         }
241     }
242
243 out:
244     pthread_cleanup_pop(1);
245
246     return res;
247 }