Mercurial > sdl-ios-xcode
annotate src/thread/linux/SDL_syssem.c @ 641:df178851293b
Date: 28 Jun 2003 22:42:52 +0100
From: Alan Swanson
Subject: Re: [SDL] New XFree 4.3 Video Mode Patch
I have a wee amendment that moves the qsort in set_best_resolution
to only occur after failing to find an exact match only. This would
make absolutely sure we get a user set mode.
While I've never had any problems for my normal resolutions (1280x1024,
1024x768, 800x600 & 640,480) while closely examining the output from
qsort I've noticed it doesn't seem to sort the modes fully. These is
one definite wrong at 1152x768 and a few that just look wrong to me.
From a program (attached) I made to examine this more easily. X has
sorted its mode list using the same method as ours (plus frequency),
and our user modes get inserted without any other movement.
On the patch I've made I've also changed cmpmodes to sort on vertical
resolution and then horizontal. Ie vertical is now most significant
bit.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 28 Jun 2003 21:52:26 +0000 |
parents | f6ffac90895c |
children | b8d311d90021 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
297
f6ffac90895c
Updated copyright information for 2002
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 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 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
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 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 #include <stdlib.h> | |
29 #include "SDL_error.h" | |
30 #include "SDL_thread.h" | |
31 #include "SDL_timer.h" | |
32 | |
33 #ifdef linux | |
34 /* Look to see if glibc is available, and if so, what version */ | |
35 #include <features.h> | |
36 | |
37 #if (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0) | |
38 #warning Working around a bug in glibc 2.0 pthreads | |
39 #undef SDL_USE_PTHREADS | |
40 /* The bug is actually a problem where threads are suspended, but don't | |
41 wake up when the thread manager sends them a signal. This is a problem | |
42 with thread creation too, but it happens less often. :-/ | |
43 We avoid this by using System V IPC for semaphores. | |
44 */ | |
45 #endif /* glibc 2.0 */ | |
46 #endif /* linux */ | |
47 | |
48 #ifdef SDL_USE_PTHREADS | |
49 | |
50 #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
|
51 #include "generic/SDL_syssem.c" |
0 | 52 #else |
53 | |
54 #include <stdio.h> | |
55 #include <stdlib.h> | |
56 #include <unistd.h> /* For getpid() */ | |
18
d9e3595b63d5
Added pthread.h - necessary on some configurations
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
57 #include <pthread.h> |
0 | 58 #include <semaphore.h> |
59 | |
60 /* Wrapper around POSIX 1003.1b semaphores */ | |
61 | |
62 #ifdef MACOSX | |
63 #define USE_NAMED_SEMAPHORES | |
64 /* Broken sem_getvalue() in MacOS X Public Beta */ | |
65 #define BROKEN_SEMGETVALUE | |
66 #endif /* MACOSX */ | |
67 | |
68 struct SDL_semaphore { | |
69 sem_t *sem; | |
70 #ifndef USE_NAMED_SEMAPHORES | |
71 sem_t sem_data; | |
72 #endif | |
73 #ifdef BROKEN_SEMGETVALUE | |
74 /* This is a little hack for MacOS X - | |
75 It's not thread-safe, but it's better than nothing | |
76 */ | |
77 int sem_value; | |
78 #endif | |
79 }; | |
80 | |
81 /* Create a semaphore, initialized with value */ | |
82 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) | |
83 { | |
84 SDL_sem *sem = (SDL_sem *) malloc(sizeof(SDL_sem)); | |
85 if ( sem ) { | |
86 #ifdef USE_NAMED_SEMAPHORES | |
87 static int semnum = 0; | |
88 char name[32]; | |
89 | |
90 sprintf(name, "/SDL_sem-%d-%4.4d", getpid(), semnum++); | |
91 sem->sem = sem_open(name, O_CREAT, 0600, initial_value); | |
92 if ( sem->sem == (sem_t *)SEM_FAILED ) { | |
93 SDL_SetError("sem_open(%s) failed", name); | |
94 free(sem); | |
95 sem = NULL; | |
96 } else { | |
97 sem_unlink(name); | |
98 } | |
99 #else | |
100 if ( sem_init(&sem->sem_data, 0, initial_value) < 0 ) { | |
101 SDL_SetError("sem_init() failed"); | |
102 free(sem); | |
103 sem = NULL; | |
104 } else { | |
105 sem->sem = &sem->sem_data; | |
106 } | |
107 #endif /* USE_NAMED_SEMAPHORES */ | |
108 | |
109 #ifdef BROKEN_SEMGETVALUE | |
110 if ( sem ) { | |
111 sem->sem_value = initial_value; | |
112 } | |
113 #endif /* BROKEN_SEMGETVALUE */ | |
114 } else { | |
115 SDL_OutOfMemory(); | |
116 } | |
117 return sem; | |
118 } | |
119 | |
120 void SDL_DestroySemaphore(SDL_sem *sem) | |
121 { | |
122 if ( sem ) { | |
123 #ifdef USE_NAMED_SEMAPHORES | |
124 sem_close(sem->sem); | |
125 #else | |
126 sem_destroy(sem->sem); | |
127 #endif | |
128 free(sem); | |
129 } | |
130 } | |
131 | |
132 int SDL_SemTryWait(SDL_sem *sem) | |
133 { | |
134 int retval; | |
135 | |
136 if ( ! sem ) { | |
137 SDL_SetError("Passed a NULL semaphore"); | |
138 return -1; | |
139 } | |
140 retval = SDL_MUTEX_TIMEDOUT; | |
141 if ( sem_trywait(sem->sem) == 0 ) { | |
142 #ifdef BROKEN_SEMGETVALUE | |
143 --sem->sem_value; | |
144 #endif | |
145 retval = 0; | |
146 } | |
147 return retval; | |
148 } | |
149 | |
150 int SDL_SemWait(SDL_sem *sem) | |
151 { | |
152 int retval; | |
153 | |
154 if ( ! sem ) { | |
155 SDL_SetError("Passed a NULL semaphore"); | |
156 return -1; | |
157 } | |
158 | |
159 #ifdef BROKEN_SEMGETVALUE | |
160 --sem->sem_value; | |
161 #endif | |
162 retval = sem_wait(sem->sem); | |
163 if ( retval < 0 ) { | |
164 SDL_SetError("sem_wait() failed"); | |
165 } | |
166 return retval; | |
167 } | |
168 | |
169 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) | |
170 { | |
171 int retval; | |
172 | |
173 if ( ! sem ) { | |
174 SDL_SetError("Passed a NULL semaphore"); | |
175 return -1; | |
176 } | |
177 | |
178 /* Try the easy cases first */ | |
179 if ( timeout == 0 ) { | |
180 return SDL_SemTryWait(sem); | |
181 } | |
182 if ( timeout == SDL_MUTEX_MAXWAIT ) { | |
183 return SDL_SemWait(sem); | |
184 } | |
185 | |
186 /* Ack! We have to busy wait... */ | |
187 timeout += SDL_GetTicks(); | |
188 do { | |
189 retval = SDL_SemTryWait(sem); | |
190 if ( retval == 0 ) { | |
191 break; | |
192 } | |
193 SDL_Delay(1); | |
194 } while ( SDL_GetTicks() < timeout ); | |
195 | |
196 return retval; | |
197 } | |
198 | |
199 Uint32 SDL_SemValue(SDL_sem *sem) | |
200 { | |
201 int ret = 0; | |
202 if ( sem ) { | |
203 #ifdef BROKEN_SEMGETVALUE | |
204 ret = sem->sem_value; | |
205 #else | |
206 sem_getvalue(sem->sem, &ret); | |
207 #endif | |
208 if ( ret < 0 ) { | |
209 ret = 0; | |
210 } | |
211 } | |
212 return (Uint32)ret; | |
213 } | |
214 | |
215 int SDL_SemPost(SDL_sem *sem) | |
216 { | |
217 int retval; | |
218 | |
219 if ( ! sem ) { | |
220 SDL_SetError("Passed a NULL semaphore"); | |
221 return -1; | |
222 } | |
223 | |
224 #ifdef BROKEN_SEMGETVALUE | |
225 ++sem->sem_value; | |
226 #endif | |
227 retval = sem_post(sem->sem); | |
228 if ( retval < 0 ) { | |
229 SDL_SetError("sem_post() failed"); | |
230 } | |
231 return retval; | |
232 } | |
233 | |
234 #endif /* NO_PTHREAD_SEMAPHORES */ | |
235 | |
236 #else /* System V IPC implementation */ | |
237 | |
238 #include <stdio.h> | |
239 #include <stdlib.h> | |
240 #include <sys/types.h> | |
241 #include <sys/ipc.h> | |
242 #include <sys/sem.h> | |
243 #include <errno.h> | |
244 | |
245 #include "SDL_error.h" | |
246 #include "SDL_thread.h" | |
247 | |
248 | |
249 struct SDL_semaphore { | |
250 int id; | |
251 }; | |
252 | |
253 /* Not defined by many operating systems, use configure to detect */ | |
254 #if !defined(HAVE_SEMUN) | |
255 union semun { | |
256 int val; | |
257 struct semid_ds *buf; | |
258 ushort *array; | |
259 }; | |
260 #endif | |
261 | |
262 static struct sembuf op_trywait[2] = { | |
263 { 0, -1, (IPC_NOWAIT|SEM_UNDO) } /* Decrement semaphore, no block */ | |
264 }; | |
265 static struct sembuf op_wait[2] = { | |
266 { 0, -1, SEM_UNDO } /* Decrement semaphore */ | |
267 }; | |
268 static struct sembuf op_post[1] = { | |
269 { 0, 1, (IPC_NOWAIT|SEM_UNDO) } /* Increment semaphore */ | |
270 }; | |
271 | |
272 /* Create a blockable semaphore */ | |
273 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) | |
274 { | |
275 extern int _creating_thread_lock; /* SDL_threads.c */ | |
276 SDL_sem *sem; | |
277 union semun init; | |
278 key_t key; | |
279 | |
280 sem = (SDL_sem *)malloc(sizeof(*sem)); | |
281 if ( sem == NULL ) { | |
282 SDL_OutOfMemory(); | |
283 return(NULL); | |
284 } | |
285 /* This flag is true if we are creating the thread manager sem, | |
286 which is never freed. This allows us to reuse the same sem. | |
287 */ | |
288 if ( _creating_thread_lock ) { | |
289 key = 'S'+'D'+'L'; | |
290 } else { | |
291 key = IPC_PRIVATE; | |
292 } | |
293 /* Keep trying to create sem while we don't own the requested key */ | |
294 do { | |
295 if ( key != IPC_PRIVATE ) { | |
296 ++key; | |
297 } | |
298 sem->id = semget(key, 1, (0600|IPC_CREAT)); | |
299 } while ((sem->id < 0) && (key != IPC_PRIVATE) && (errno == EACCES)); | |
300 | |
301 /* Report the error if we eventually failed */ | |
302 if ( sem->id < 0 ) { | |
303 SDL_SetError("Couldn't create semaphore"); | |
304 free(sem); | |
305 return(NULL); | |
306 } | |
307 init.val = initial_value; /* Initialize semaphore */ | |
308 semctl(sem->id, 0, SETVAL, init); | |
309 return(sem); | |
310 } | |
311 | |
312 void SDL_DestroySemaphore(SDL_sem *sem) | |
313 { | |
314 if ( sem ) { | |
315 #ifdef _SGI_SOURCE | |
316 semctl(sem->id, 0, IPC_RMID); | |
317 #else | |
318 union semun dummy; | |
319 dummy.val = 0; | |
320 semctl(sem->id, 0, IPC_RMID, dummy); | |
321 #endif | |
322 free(sem); | |
323 } | |
324 } | |
325 | |
326 int SDL_SemTryWait(SDL_sem *sem) | |
327 { | |
328 int retval; | |
329 | |
330 if ( ! sem ) { | |
331 SDL_SetError("Passed a NULL semaphore"); | |
332 return -1; | |
333 } | |
334 | |
335 retval = 0; | |
336 tryagain: | |
337 if ( semop(sem->id, op_trywait, 1) < 0 ) { | |
338 if ( errno == EINTR ) { | |
339 goto tryagain; | |
340 } | |
341 retval = SDL_MUTEX_TIMEDOUT; | |
342 } | |
343 return retval; | |
344 } | |
345 | |
346 int SDL_SemWait(SDL_sem *sem) | |
347 { | |
348 int retval; | |
349 | |
350 if ( ! sem ) { | |
351 SDL_SetError("Passed a NULL semaphore"); | |
352 return -1; | |
353 } | |
354 | |
355 retval = 0; | |
356 tryagain: | |
357 if ( semop(sem->id, op_wait, 1) < 0 ) { | |
358 if ( errno == EINTR ) { | |
359 goto tryagain; | |
360 } | |
361 SDL_SetError("Semaphore operation error"); | |
362 retval = -1; | |
363 } | |
364 return retval; | |
365 } | |
366 | |
367 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) | |
368 { | |
369 int retval; | |
370 | |
371 if ( ! sem ) { | |
372 SDL_SetError("Passed a NULL semaphore"); | |
373 return -1; | |
374 } | |
375 | |
376 /* Try the easy cases first */ | |
377 if ( timeout == 0 ) { | |
378 return SDL_SemTryWait(sem); | |
379 } | |
380 if ( timeout == SDL_MUTEX_MAXWAIT ) { | |
381 return SDL_SemWait(sem); | |
382 } | |
383 | |
384 /* Ack! We have to busy wait... */ | |
385 timeout += SDL_GetTicks(); | |
386 do { | |
387 retval = SDL_SemTryWait(sem); | |
388 if ( retval == 0 ) { | |
389 break; | |
390 } | |
391 SDL_Delay(1); | |
392 } while ( SDL_GetTicks() < timeout ); | |
393 | |
394 return retval; | |
395 } | |
396 | |
397 Uint32 SDL_SemValue(SDL_sem *sem) | |
398 { | |
399 int semval; | |
400 Uint32 value; | |
401 | |
402 value = 0; | |
403 if ( sem ) { | |
404 tryagain: | |
405 #ifdef _SGI_SOURCE | |
406 semval = semctl(sem->id, 0, GETVAL); | |
407 #else | |
408 { | |
409 union semun arg; | |
410 arg.val = 0; | |
411 semval = semctl(sem->id, 0, GETVAL, arg); | |
412 } | |
413 #endif | |
414 if ( semval < 0 ) { | |
415 if ( errno == EINTR ) { | |
416 goto tryagain; | |
417 } | |
418 } else { | |
419 value = (Uint32)semval; | |
420 } | |
421 } | |
422 return value; | |
423 } | |
424 | |
425 int SDL_SemPost(SDL_sem *sem) | |
426 { | |
427 int retval; | |
428 | |
429 if ( ! sem ) { | |
430 SDL_SetError("Passed a NULL semaphore"); | |
431 return -1; | |
432 } | |
433 | |
434 retval = 0; | |
435 tryagain: | |
436 if ( semop(sem->id, op_post, 1) < 0 ) { | |
437 if ( errno == EINTR ) { | |
438 goto tryagain; | |
439 } | |
440 SDL_SetError("Semaphore operation error"); | |
441 retval = -1; | |
442 } | |
443 return retval; | |
444 } | |
445 | |
446 #endif /* SDL_USE_PTHREADS */ |