comparison src/thread/irix/SDL_syssem.c @ 1361:19418e4422cb

New configure-based build system. Still work in progress, but much improved
author Sam Lantinga <slouken@libsdl.org>
date Thu, 16 Feb 2006 10:11:48 +0000
parents
children d910939febfa
comparison
equal deleted inserted replaced
1360:70a9cfb4cf1b 1361:19418e4422cb
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2006 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
23 #include "SDL_thread.h"
24 #include "SDL_timer.h"
25
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <sys/types.h>
30 #include <sys/ipc.h>
31 #include <sys/sem.h>
32 #include <errno.h>
33
34 #include "SDL_error.h"
35 #include "SDL_thread.h"
36
37
38 struct SDL_semaphore {
39 int id;
40 };
41
42 /* Not defined by many operating systems, use configure to detect */
43 /*
44 #if !defined(HAVE_SEMUN)
45 union semun {
46 int val;
47 struct semid_ds *buf;
48 ushort *array;
49 };
50 #endif
51 */
52
53 static struct sembuf op_trywait[2] = {
54 { 0, -1, (IPC_NOWAIT|SEM_UNDO) } /* Decrement semaphore, no block */
55 };
56 static struct sembuf op_wait[2] = {
57 { 0, -1, SEM_UNDO } /* Decrement semaphore */
58 };
59 static struct sembuf op_post[1] = {
60 { 0, 1, (IPC_NOWAIT|SEM_UNDO) } /* Increment semaphore */
61 };
62
63 /* Create a blockable semaphore */
64 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
65 {
66 extern int _creating_thread_lock; /* SDL_threads.c */
67 SDL_sem *sem;
68 union semun init;
69 key_t key;
70
71 sem = (SDL_sem *)SDL_malloc(sizeof(*sem));
72 if ( sem == NULL ) {
73 SDL_OutOfMemory();
74 return(NULL);
75 }
76 /* This flag is true if we are creating the thread manager sem,
77 which is never freed. This allows us to reuse the same sem.
78 */
79 if ( _creating_thread_lock ) {
80 key = 'S'+'D'+'L';
81 } else {
82 key = IPC_PRIVATE;
83 }
84 /* Keep trying to create sem while we don't own the requested key */
85 do {
86 if ( key != IPC_PRIVATE ) {
87 ++key;
88 }
89 sem->id = semget(key, 1, (0600|IPC_CREAT));
90 } while ((sem->id < 0) && (key != IPC_PRIVATE) && (errno == EACCES));
91
92 /* Report the error if we eventually failed */
93 if ( sem->id < 0 ) {
94 SDL_SetError("Couldn't create semaphore");
95 SDL_free(sem);
96 return(NULL);
97 }
98 init.val = initial_value; /* Initialize semaphore */
99 semctl(sem->id, 0, SETVAL, init);
100 return(sem);
101 }
102
103 void SDL_DestroySemaphore(SDL_sem *sem)
104 {
105 if ( sem ) {
106 #ifdef _SGI_SOURCE
107 semctl(sem->id, 0, IPC_RMID);
108 #else
109 union semun dummy;
110 dummy.val = 0;
111 semctl(sem->id, 0, IPC_RMID, dummy);
112 #endif
113 SDL_free(sem);
114 }
115 }
116
117 int SDL_SemTryWait(SDL_sem *sem)
118 {
119 int retval;
120
121 if ( ! sem ) {
122 SDL_SetError("Passed a NULL semaphore");
123 return -1;
124 }
125
126 retval = 0;
127 tryagain:
128 if ( semop(sem->id, op_trywait, 1) < 0 ) {
129 if ( errno == EINTR ) {
130 goto tryagain;
131 }
132 retval = SDL_MUTEX_TIMEDOUT;
133 }
134 return retval;
135 }
136
137 int SDL_SemWait(SDL_sem *sem)
138 {
139 int retval;
140
141 if ( ! sem ) {
142 SDL_SetError("Passed a NULL semaphore");
143 return -1;
144 }
145
146 retval = 0;
147 tryagain:
148 if ( semop(sem->id, op_wait, 1) < 0 ) {
149 if ( errno == EINTR ) {
150 goto tryagain;
151 }
152 SDL_SetError("Semaphore operation error");
153 retval = -1;
154 }
155 return retval;
156 }
157
158 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
159 {
160 int retval;
161
162 if ( ! sem ) {
163 SDL_SetError("Passed a NULL semaphore");
164 return -1;
165 }
166
167 /* Try the easy cases first */
168 if ( timeout == 0 ) {
169 return SDL_SemTryWait(sem);
170 }
171 if ( timeout == SDL_MUTEX_MAXWAIT ) {
172 return SDL_SemWait(sem);
173 }
174
175 /* Ack! We have to busy wait... */
176 timeout += SDL_GetTicks();
177 do {
178 retval = SDL_SemTryWait(sem);
179 if ( retval == 0 ) {
180 break;
181 }
182 SDL_Delay(1);
183 } while ( SDL_GetTicks() < timeout );
184
185 return retval;
186 }
187
188 Uint32 SDL_SemValue(SDL_sem *sem)
189 {
190 int semval;
191 Uint32 value;
192
193 value = 0;
194 if ( sem ) {
195 tryagain:
196 #ifdef _SGI_SOURCE
197 semval = semctl(sem->id, 0, GETVAL);
198 #else
199 {
200 union semun arg;
201 arg.val = 0;
202 semval = semctl(sem->id, 0, GETVAL, arg);
203 }
204 #endif
205 if ( semval < 0 ) {
206 if ( errno == EINTR ) {
207 goto tryagain;
208 }
209 } else {
210 value = (Uint32)semval;
211 }
212 }
213 return value;
214 }
215
216 int SDL_SemPost(SDL_sem *sem)
217 {
218 int retval;
219
220 if ( ! sem ) {
221 SDL_SetError("Passed a NULL semaphore");
222 return -1;
223 }
224
225 retval = 0;
226 tryagain:
227 if ( semop(sem->id, op_post, 1) < 0 ) {
228 if ( errno == EINTR ) {
229 goto tryagain;
230 }
231 SDL_SetError("Semaphore operation error");
232 retval = -1;
233 }
234 return retval;
235 }