Mercurial > sdl-ios-xcode
annotate src/thread/linux/SDL_syssem.c @ 1345:7f32b9bede06
Fixes for Visual C++ 6.0
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Tue, 07 Feb 2006 18:36:54 +0000 |
parents | 604d73db6802 |
children | c71e05b4dc2e |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1300
diff
changeset
|
3 Copyright (C) 1997-2006 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1300
diff
changeset
|
6 modify it under the terms of the GNU Lesser General Public |
0 | 7 License as published by the Free Software Foundation; either |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1300
diff
changeset
|
8 version 2.1 of the License, or (at your option) any later version. |
0 | 9 |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1300
diff
changeset
|
13 Lesser General Public License for more details. |
0 | 14 |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1300
diff
changeset
|
15 You should have received a copy of the GNU Lesser General Public |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1300
diff
changeset
|
16 License along with this library; if not, write to the Free Software |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1300
diff
changeset
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 18 |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
94
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
1338
604d73db6802
Removed uses of stdlib.h and string.h
Sam Lantinga <slouken@libsdl.org>
parents:
1336
diff
changeset
|
23 #include "SDL_stdlib.h" |
0 | 24 #include "SDL_error.h" |
25 #include "SDL_thread.h" | |
26 #include "SDL_timer.h" | |
27 | |
28 #ifdef linux | |
29 /* Look to see if glibc is available, and if so, what version */ | |
30 #include <features.h> | |
31 | |
32 #if (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0) | |
33 #warning Working around a bug in glibc 2.0 pthreads | |
34 #undef SDL_USE_PTHREADS | |
35 /* The bug is actually a problem where threads are suspended, but don't | |
36 wake up when the thread manager sends them a signal. This is a problem | |
37 with thread creation too, but it happens less often. :-/ | |
38 We avoid this by using System V IPC for semaphores. | |
39 */ | |
40 #endif /* glibc 2.0 */ | |
41 #endif /* linux */ | |
42 | |
43 #ifdef SDL_USE_PTHREADS | |
44 | |
45 #ifdef SDL_NO_PTHREAD_SEMAPHORES | |
94
ae6e6b73333f
Cleaned up the OpenBSD port, thanks to Peter Valchev
Sam Lantinga <slouken@lokigames.com>
parents:
18
diff
changeset
|
46 #include "generic/SDL_syssem.c" |
0 | 47 #else |
48 | |
18
d9e3595b63d5
Added pthread.h - necessary on some configurations
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
49 #include <pthread.h> |
0 | 50 #include <semaphore.h> |
51 | |
52 /* Wrapper around POSIX 1003.1b semaphores */ | |
53 | |
54 #ifdef MACOSX | |
55 #define USE_NAMED_SEMAPHORES | |
56 #endif /* MACOSX */ | |
57 | |
58 struct SDL_semaphore { | |
59 sem_t *sem; | |
60 #ifndef USE_NAMED_SEMAPHORES | |
61 sem_t sem_data; | |
62 #endif | |
63 }; | |
64 | |
65 /* Create a semaphore, initialized with value */ | |
66 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) | |
67 { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
68 SDL_sem *sem = (SDL_sem *) SDL_malloc(sizeof(SDL_sem)); |
0 | 69 if ( sem ) { |
70 #ifdef USE_NAMED_SEMAPHORES | |
71 static int semnum = 0; | |
72 char name[32]; | |
73 | |
1338
604d73db6802
Removed uses of stdlib.h and string.h
Sam Lantinga <slouken@libsdl.org>
parents:
1336
diff
changeset
|
74 SDL_snprintf(name, SDL_arraysize(name), "/SDL_sem-%d-%4.4d", getpid(), semnum++); |
0 | 75 sem->sem = sem_open(name, O_CREAT, 0600, initial_value); |
76 if ( sem->sem == (sem_t *)SEM_FAILED ) { | |
77 SDL_SetError("sem_open(%s) failed", name); | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
78 SDL_free(sem); |
0 | 79 sem = NULL; |
80 } else { | |
81 sem_unlink(name); | |
82 } | |
83 #else | |
84 if ( sem_init(&sem->sem_data, 0, initial_value) < 0 ) { | |
85 SDL_SetError("sem_init() failed"); | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
86 SDL_free(sem); |
0 | 87 sem = NULL; |
88 } else { | |
89 sem->sem = &sem->sem_data; | |
90 } | |
91 #endif /* USE_NAMED_SEMAPHORES */ | |
92 } else { | |
93 SDL_OutOfMemory(); | |
94 } | |
95 return sem; | |
96 } | |
97 | |
98 void SDL_DestroySemaphore(SDL_sem *sem) | |
99 { | |
100 if ( sem ) { | |
101 #ifdef USE_NAMED_SEMAPHORES | |
102 sem_close(sem->sem); | |
103 #else | |
104 sem_destroy(sem->sem); | |
105 #endif | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
106 SDL_free(sem); |
0 | 107 } |
108 } | |
109 | |
110 int SDL_SemTryWait(SDL_sem *sem) | |
111 { | |
112 int retval; | |
113 | |
114 if ( ! sem ) { | |
115 SDL_SetError("Passed a NULL semaphore"); | |
116 return -1; | |
117 } | |
118 retval = SDL_MUTEX_TIMEDOUT; | |
119 if ( sem_trywait(sem->sem) == 0 ) { | |
120 retval = 0; | |
121 } | |
122 return retval; | |
123 } | |
124 | |
125 int SDL_SemWait(SDL_sem *sem) | |
126 { | |
127 int retval; | |
128 | |
129 if ( ! sem ) { | |
130 SDL_SetError("Passed a NULL semaphore"); | |
131 return -1; | |
132 } | |
133 | |
134 retval = sem_wait(sem->sem); | |
135 if ( retval < 0 ) { | |
136 SDL_SetError("sem_wait() failed"); | |
137 } | |
138 return retval; | |
139 } | |
140 | |
141 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) | |
142 { | |
143 int retval; | |
144 | |
145 if ( ! sem ) { | |
146 SDL_SetError("Passed a NULL semaphore"); | |
147 return -1; | |
148 } | |
149 | |
150 /* Try the easy cases first */ | |
151 if ( timeout == 0 ) { | |
152 return SDL_SemTryWait(sem); | |
153 } | |
154 if ( timeout == SDL_MUTEX_MAXWAIT ) { | |
155 return SDL_SemWait(sem); | |
156 } | |
157 | |
158 /* Ack! We have to busy wait... */ | |
159 timeout += SDL_GetTicks(); | |
160 do { | |
161 retval = SDL_SemTryWait(sem); | |
162 if ( retval == 0 ) { | |
163 break; | |
164 } | |
165 SDL_Delay(1); | |
166 } while ( SDL_GetTicks() < timeout ); | |
167 | |
168 return retval; | |
169 } | |
170 | |
171 Uint32 SDL_SemValue(SDL_sem *sem) | |
172 { | |
173 int ret = 0; | |
174 if ( sem ) { | |
175 sem_getvalue(sem->sem, &ret); | |
176 if ( ret < 0 ) { | |
177 ret = 0; | |
178 } | |
179 } | |
180 return (Uint32)ret; | |
181 } | |
182 | |
183 int SDL_SemPost(SDL_sem *sem) | |
184 { | |
185 int retval; | |
186 | |
187 if ( ! sem ) { | |
188 SDL_SetError("Passed a NULL semaphore"); | |
189 return -1; | |
190 } | |
191 | |
192 retval = sem_post(sem->sem); | |
193 if ( retval < 0 ) { | |
194 SDL_SetError("sem_post() failed"); | |
195 } | |
196 return retval; | |
197 } | |
198 | |
199 #endif /* NO_PTHREAD_SEMAPHORES */ | |
200 | |
201 #else /* System V IPC implementation */ | |
202 | |
203 #include <stdio.h> | |
204 #include <stdlib.h> | |
205 #include <sys/types.h> | |
206 #include <sys/ipc.h> | |
207 #include <sys/sem.h> | |
208 #include <errno.h> | |
209 | |
210 #include "SDL_error.h" | |
211 #include "SDL_thread.h" | |
212 | |
213 | |
214 struct SDL_semaphore { | |
215 int id; | |
216 }; | |
217 | |
218 /* Not defined by many operating systems, use configure to detect */ | |
219 #if !defined(HAVE_SEMUN) | |
220 union semun { | |
221 int val; | |
222 struct semid_ds *buf; | |
223 ushort *array; | |
224 }; | |
225 #endif | |
226 | |
227 static struct sembuf op_trywait[2] = { | |
228 { 0, -1, (IPC_NOWAIT|SEM_UNDO) } /* Decrement semaphore, no block */ | |
229 }; | |
230 static struct sembuf op_wait[2] = { | |
231 { 0, -1, SEM_UNDO } /* Decrement semaphore */ | |
232 }; | |
233 static struct sembuf op_post[1] = { | |
234 { 0, 1, (IPC_NOWAIT|SEM_UNDO) } /* Increment semaphore */ | |
235 }; | |
236 | |
237 /* Create a blockable semaphore */ | |
238 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) | |
239 { | |
240 extern int _creating_thread_lock; /* SDL_threads.c */ | |
241 SDL_sem *sem; | |
242 union semun init; | |
243 key_t key; | |
244 | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
245 sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); |
0 | 246 if ( sem == NULL ) { |
247 SDL_OutOfMemory(); | |
248 return(NULL); | |
249 } | |
250 /* This flag is true if we are creating the thread manager sem, | |
251 which is never freed. This allows us to reuse the same sem. | |
252 */ | |
253 if ( _creating_thread_lock ) { | |
254 key = 'S'+'D'+'L'; | |
255 } else { | |
256 key = IPC_PRIVATE; | |
257 } | |
258 /* Keep trying to create sem while we don't own the requested key */ | |
259 do { | |
260 if ( key != IPC_PRIVATE ) { | |
261 ++key; | |
262 } | |
263 sem->id = semget(key, 1, (0600|IPC_CREAT)); | |
264 } while ((sem->id < 0) && (key != IPC_PRIVATE) && (errno == EACCES)); | |
265 | |
266 /* Report the error if we eventually failed */ | |
267 if ( sem->id < 0 ) { | |
268 SDL_SetError("Couldn't create semaphore"); | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
269 SDL_free(sem); |
0 | 270 return(NULL); |
271 } | |
272 init.val = initial_value; /* Initialize semaphore */ | |
273 semctl(sem->id, 0, SETVAL, init); | |
274 return(sem); | |
275 } | |
276 | |
277 void SDL_DestroySemaphore(SDL_sem *sem) | |
278 { | |
279 if ( sem ) { | |
280 #ifdef _SGI_SOURCE | |
281 semctl(sem->id, 0, IPC_RMID); | |
282 #else | |
283 union semun dummy; | |
284 dummy.val = 0; | |
285 semctl(sem->id, 0, IPC_RMID, dummy); | |
286 #endif | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
287 SDL_free(sem); |
0 | 288 } |
289 } | |
290 | |
291 int SDL_SemTryWait(SDL_sem *sem) | |
292 { | |
293 int retval; | |
294 | |
295 if ( ! sem ) { | |
296 SDL_SetError("Passed a NULL semaphore"); | |
297 return -1; | |
298 } | |
299 | |
300 retval = 0; | |
301 tryagain: | |
302 if ( semop(sem->id, op_trywait, 1) < 0 ) { | |
303 if ( errno == EINTR ) { | |
304 goto tryagain; | |
305 } | |
306 retval = SDL_MUTEX_TIMEDOUT; | |
307 } | |
308 return retval; | |
309 } | |
310 | |
311 int SDL_SemWait(SDL_sem *sem) | |
312 { | |
313 int retval; | |
314 | |
315 if ( ! sem ) { | |
316 SDL_SetError("Passed a NULL semaphore"); | |
317 return -1; | |
318 } | |
319 | |
320 retval = 0; | |
321 tryagain: | |
322 if ( semop(sem->id, op_wait, 1) < 0 ) { | |
323 if ( errno == EINTR ) { | |
324 goto tryagain; | |
325 } | |
326 SDL_SetError("Semaphore operation error"); | |
327 retval = -1; | |
328 } | |
329 return retval; | |
330 } | |
331 | |
332 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) | |
333 { | |
334 int retval; | |
335 | |
336 if ( ! sem ) { | |
337 SDL_SetError("Passed a NULL semaphore"); | |
338 return -1; | |
339 } | |
340 | |
341 /* Try the easy cases first */ | |
342 if ( timeout == 0 ) { | |
343 return SDL_SemTryWait(sem); | |
344 } | |
345 if ( timeout == SDL_MUTEX_MAXWAIT ) { | |
346 return SDL_SemWait(sem); | |
347 } | |
348 | |
349 /* Ack! We have to busy wait... */ | |
350 timeout += SDL_GetTicks(); | |
351 do { | |
352 retval = SDL_SemTryWait(sem); | |
353 if ( retval == 0 ) { | |
354 break; | |
355 } | |
356 SDL_Delay(1); | |
357 } while ( SDL_GetTicks() < timeout ); | |
358 | |
359 return retval; | |
360 } | |
361 | |
362 Uint32 SDL_SemValue(SDL_sem *sem) | |
363 { | |
364 int semval; | |
365 Uint32 value; | |
366 | |
367 value = 0; | |
368 if ( sem ) { | |
369 tryagain: | |
370 #ifdef _SGI_SOURCE | |
371 semval = semctl(sem->id, 0, GETVAL); | |
372 #else | |
373 { | |
374 union semun arg; | |
375 arg.val = 0; | |
376 semval = semctl(sem->id, 0, GETVAL, arg); | |
377 } | |
378 #endif | |
379 if ( semval < 0 ) { | |
380 if ( errno == EINTR ) { | |
381 goto tryagain; | |
382 } | |
383 } else { | |
384 value = (Uint32)semval; | |
385 } | |
386 } | |
387 return value; | |
388 } | |
389 | |
390 int SDL_SemPost(SDL_sem *sem) | |
391 { | |
392 int retval; | |
393 | |
394 if ( ! sem ) { | |
395 SDL_SetError("Passed a NULL semaphore"); | |
396 return -1; | |
397 } | |
398 | |
399 retval = 0; | |
400 tryagain: | |
401 if ( semop(sem->id, op_post, 1) < 0 ) { | |
402 if ( errno == EINTR ) { | |
403 goto tryagain; | |
404 } | |
405 SDL_SetError("Semaphore operation error"); | |
406 retval = -1; | |
407 } | |
408 return retval; | |
409 } | |
410 | |
411 #endif /* SDL_USE_PTHREADS */ |