2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "SDL_config.h"
24 #include "SDL_thread.h"
25 #include "SDL_timer.h"
30 #include <sys/types.h>
35 #include "SDL_error.h"
36 #include "SDL_thread.h"
39 struct SDL_semaphore {
43 /* Not defined by many operating systems, use configure to detect */
45 #if !defined(HAVE_SEMUN)
54 static struct sembuf op_trywait[2] = {
55 { 0, -1, (IPC_NOWAIT|SEM_UNDO) } /* Decrement semaphore, no block */
57 static struct sembuf op_wait[2] = {
58 { 0, -1, SEM_UNDO } /* Decrement semaphore */
60 static struct sembuf op_post[1] = {
61 { 0, 1, (IPC_NOWAIT|SEM_UNDO) } /* Increment semaphore */
64 /* Create a blockable semaphore */
65 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
67 extern int _creating_thread_lock; /* SDL_threads.c */
71 sem = (SDL_sem *)SDL_malloc(sizeof(*sem));
76 sem->id = semget(IPC_PRIVATE, 1, (0600|IPC_CREAT));
78 SDL_SetError("Couldn't create semaphore");
82 init.val = initial_value; /* Initialize semaphore */
83 semctl(sem->id, 0, SETVAL, init);
87 void SDL_DestroySemaphore(SDL_sem *sem)
91 semctl(sem->id, 0, IPC_RMID);
95 semctl(sem->id, 0, IPC_RMID, dummy);
101 int SDL_SemTryWait(SDL_sem *sem)
106 SDL_SetError("Passed a NULL semaphore");
112 if ( semop(sem->id, op_trywait, 1) < 0 ) {
113 if ( errno == EINTR ) {
116 retval = SDL_MUTEX_TIMEDOUT;
121 int SDL_SemWait(SDL_sem *sem)
126 SDL_SetError("Passed a NULL semaphore");
132 if ( semop(sem->id, op_wait, 1) < 0 ) {
133 if ( errno == EINTR ) {
136 SDL_SetError("Semaphore operation error");
142 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
147 SDL_SetError("Passed a NULL semaphore");
151 /* Try the easy cases first */
152 if ( timeout == 0 ) {
153 return SDL_SemTryWait(sem);
155 if ( timeout == SDL_MUTEX_MAXWAIT ) {
156 return SDL_SemWait(sem);
159 /* Ack! We have to busy wait... */
160 timeout += SDL_GetTicks();
162 retval = SDL_SemTryWait(sem);
167 } while ( SDL_GetTicks() < timeout );
172 Uint32 SDL_SemValue(SDL_sem *sem)
181 semval = semctl(sem->id, 0, GETVAL);
186 semval = semctl(sem->id, 0, GETVAL, arg);
190 if ( errno == EINTR ) {
194 value = (Uint32)semval;
200 int SDL_SemPost(SDL_sem *sem)
205 SDL_SetError("Passed a NULL semaphore");
211 if ( semop(sem->id, op_post, 1) < 0 ) {
212 if ( errno == EINTR ) {
215 SDL_SetError("Semaphore operation error");