comparison src/thread/linux/SDL_syscond.c @ 0:74212992fb08

Initial revision
author Sam Lantinga <slouken@lokigames.com>
date Thu, 26 Apr 2001 16:45:43 +0000
parents
children dc660aee7d7d
comparison
equal deleted inserted replaced
-1:000000000000 0:74212992fb08
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga
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
20 slouken@devolution.com
21 */
22
23 #ifdef SAVE_RCSID
24 static char rcsid =
25 "@(#) $Id$";
26 #endif
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 mutexes.
39 */
40 #endif /* glibc 2.0 */
41 #endif /* linux */
42
43 #ifdef SDL_USE_PTHREADS
44
45 #include <sys/time.h>
46 #include <unistd.h>
47 #include <errno.h>
48 #include <stdlib.h>
49 #include <pthread.h>
50
51 #include "SDL_error.h"
52 #include "SDL_thread.h"
53 #include "SDL_sysmutex_c.h"
54
55
56 #if defined(PTHREAD_NO_RECURSIVE_MUTEX) && !defined(__bsdi__)
57 #error You need to use the generic condition variable implementation
58 #endif
59
60 struct SDL_cond
61 {
62 pthread_cond_t cond;
63 };
64
65 /* Create a condition variable */
66 SDL_cond * SDL_CreateCond(void)
67 {
68 SDL_cond *cond;
69
70 cond = (SDL_cond *) malloc(sizeof(SDL_cond));
71 if ( cond ) {
72 if ( pthread_cond_init(&cond->cond, NULL) < 0 ) {
73 SDL_SetError("pthread_cond_init() failed");
74 free(cond);
75 cond = NULL;
76 }
77 }
78 return(cond);
79 }
80
81 /* Destroy a condition variable */
82 void SDL_DestroyCond(SDL_cond *cond)
83 {
84 if ( cond ) {
85 pthread_cond_destroy(&cond->cond);
86 free(cond);
87 }
88 }
89
90 /* Restart one of the threads that are waiting on the condition variable */
91 int SDL_CondSignal(SDL_cond *cond)
92 {
93 int retval;
94
95 if ( ! cond ) {
96 SDL_SetError("Passed a NULL condition variable");
97 return -1;
98 }
99
100 retval = 0;
101 if ( pthread_cond_signal(&cond->cond) != 0 ) {
102 SDL_SetError("pthread_cond_signal() failed");
103 retval = -1;
104 }
105 return retval;
106 }
107
108 /* Restart all threads that are waiting on the condition variable */
109 int SDL_CondBroadcast(SDL_cond *cond)
110 {
111 int retval;
112
113 if ( ! cond ) {
114 SDL_SetError("Passed a NULL condition variable");
115 return -1;
116 }
117
118 retval = 0;
119 if ( pthread_cond_broadcast(&cond->cond) != 0 ) {
120 SDL_SetError("pthread_cond_broadcast() failed");
121 retval = -1;
122 }
123 return retval;
124 }
125
126 int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
127 {
128 int retval;
129 struct timeval delta;
130 struct timespec abstime;
131
132 if ( ! cond ) {
133 SDL_SetError("Passed a NULL condition variable");
134 return -1;
135 }
136
137 gettimeofday(&delta, NULL);
138
139 abstime.tv_sec = delta.tv_sec + (ms/1000);
140 abstime.tv_nsec = (delta.tv_usec+(ms%1000)) * 1000;
141 if ( abstime.tv_nsec > 1000000 ) {
142 abstime.tv_sec += 1;
143 abstime.tv_nsec -= 1000000;
144 }
145
146 tryagain:
147 retval = pthread_cond_timedwait(&cond->cond, &mutex->id, &abstime);
148 switch (retval) {
149 case EINTR:
150 goto tryagain;
151 break;
152 case ETIMEDOUT:
153 retval = SDL_MUTEX_TIMEDOUT;
154 break;
155 case 0:
156 break;
157 default:
158 SDL_SetError("pthread_cond_timedwait() failed");
159 retval = -1;
160 break;
161 }
162 return retval;
163 }
164
165 /* Wait on the condition variable, unlocking the provided mutex.
166 The mutex must be locked before entering this function!
167 */
168 int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
169 {
170 int retval;
171
172 if ( ! cond ) {
173 SDL_SetError("Passed a NULL condition variable");
174 return -1;
175 }
176
177 retval = 0;
178 if ( pthread_cond_wait(&cond->cond, &mutex->id) != 0 ) {
179 SDL_SetError("pthread_cond_wait() failed");
180 retval = -1;
181 }
182 return retval;
183 }
184
185 #else /* Use semaphore implementation */
186
187 #include "generic/SDL_syscond.c"
188
189 #endif /* SDL_USE_PTHREADS */