SDL-1.2.14
[sdl_omap.git] / src / thread / irix / SDL_syssem.c
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 Sam Lantinga
4
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.
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
13     Lesser General Public License for more details.
14
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
18
19     Sam Lantinga
20     slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 #include "SDL_thread.h"
25 #include "SDL_timer.h"
26
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <sys/types.h>
31 #include <sys/ipc.h>
32 #include <sys/sem.h>
33 #include <errno.h>
34
35 #include "SDL_error.h"
36 #include "SDL_thread.h"
37
38
39 struct SDL_semaphore {
40         int id;
41 };
42
43 /* Not defined by many operating systems, use configure to detect */
44 /*
45 #if !defined(HAVE_SEMUN)
46 union semun {
47         int val;
48         struct semid_ds *buf;
49         ushort *array;
50 };
51 #endif
52 */
53
54 static struct sembuf op_trywait[2] = {
55         { 0, -1, (IPC_NOWAIT|SEM_UNDO) } /* Decrement semaphore, no block */
56 };
57 static struct sembuf op_wait[2] = {
58         { 0, -1, SEM_UNDO }             /* Decrement semaphore */
59 };
60 static struct sembuf op_post[1] = {
61         { 0, 1, (IPC_NOWAIT|SEM_UNDO) } /* Increment semaphore */
62 };
63
64 /* Create a blockable semaphore */
65 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
66 {
67         extern int _creating_thread_lock;       /* SDL_threads.c */
68         SDL_sem *sem;
69         union semun init;
70
71         sem = (SDL_sem *)SDL_malloc(sizeof(*sem));
72         if ( sem == NULL ) {
73                 SDL_OutOfMemory();
74                 return(NULL);
75         }
76         sem->id = semget(IPC_PRIVATE, 1, (0600|IPC_CREAT));
77         if ( sem->id < 0 ) {
78                 SDL_SetError("Couldn't create semaphore");
79                 SDL_free(sem);
80                 return(NULL);
81         }
82         init.val = initial_value;       /* Initialize semaphore */
83         semctl(sem->id, 0, SETVAL, init);
84         return(sem);
85 }
86
87 void SDL_DestroySemaphore(SDL_sem *sem)
88 {
89         if ( sem ) {
90 #ifdef __IRIX__
91                 semctl(sem->id, 0, IPC_RMID);
92 #else
93                 union semun dummy;
94                 dummy.val = 0;
95                 semctl(sem->id, 0, IPC_RMID, dummy);
96 #endif
97                 SDL_free(sem);
98         }
99 }
100
101 int SDL_SemTryWait(SDL_sem *sem)
102 {
103         int retval;
104
105         if ( ! sem ) {
106                 SDL_SetError("Passed a NULL semaphore");
107                 return -1;
108         }
109
110         retval = 0;
111   tryagain:
112         if ( semop(sem->id, op_trywait, 1) < 0 ) {
113                 if ( errno == EINTR ) {
114                         goto tryagain;
115                 }
116                 retval = SDL_MUTEX_TIMEDOUT;
117         }
118         return retval;
119 }
120
121 int SDL_SemWait(SDL_sem *sem)
122 {
123         int retval;
124
125         if ( ! sem ) {
126                 SDL_SetError("Passed a NULL semaphore");
127                 return -1;
128         }
129
130         retval = 0;
131   tryagain:
132         if ( semop(sem->id, op_wait, 1) < 0 ) {
133                 if ( errno == EINTR ) {
134                         goto tryagain;
135                 }
136                 SDL_SetError("Semaphore operation error");
137                 retval = -1;
138         }
139         return retval;
140 }
141
142 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
143 {
144         int retval;
145
146         if ( ! sem ) {
147                 SDL_SetError("Passed a NULL semaphore");
148                 return -1;
149         }
150
151         /* Try the easy cases first */
152         if ( timeout == 0 ) {
153                 return SDL_SemTryWait(sem);
154         }
155         if ( timeout == SDL_MUTEX_MAXWAIT ) {
156                 return SDL_SemWait(sem);
157         }
158
159         /* Ack!  We have to busy wait... */
160         timeout += SDL_GetTicks();
161         do {
162                 retval = SDL_SemTryWait(sem);
163                 if ( retval == 0 ) {
164                         break;
165                 }
166                 SDL_Delay(1);
167         } while ( SDL_GetTicks() < timeout );
168
169         return retval;
170 }
171
172 Uint32 SDL_SemValue(SDL_sem *sem)
173 {
174         int semval;
175         Uint32 value;
176         
177         value = 0;
178         if ( sem ) {
179           tryagain:
180 #ifdef __IRIX__
181                 semval = semctl(sem->id, 0, GETVAL);
182 #else
183                 {
184                 union semun arg;
185                 arg.val = 0;
186                 semval = semctl(sem->id, 0, GETVAL, arg);
187                 }
188 #endif
189                 if ( semval < 0 ) {
190                         if ( errno == EINTR ) {
191                                 goto tryagain;
192                         }
193                 } else {
194                         value = (Uint32)semval;
195                 }
196         }
197         return value;
198 }
199
200 int SDL_SemPost(SDL_sem *sem)
201 {
202         int retval;
203
204         if ( ! sem ) {
205                 SDL_SetError("Passed a NULL semaphore");
206                 return -1;
207         }
208
209         retval = 0;
210   tryagain:
211         if ( semop(sem->id, op_post, 1) < 0 ) {
212                 if ( errno == EINTR ) {
213                         goto tryagain;
214                 }
215                 SDL_SetError("Semaphore operation error");
216                 retval = -1;
217         }
218         return retval;
219 }