Mercurial > sdl-ios-xcode
comparison src/thread/riscos/SDL_syssem.c @ 1099:1ccbb2b7d905
Date: Fri, 15 Jul 2005 08:29:01 +0100
From: "alan buckley"
Subject: SDL Improved semiphore implementation for RISC OS (version 2)
I've attached a new version of the patch for the RISC OS
semaphore processing (in a zip file) that updates it to use
the improved semaphores support in UnixLiib.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Thu, 21 Jul 2005 06:19:18 +0000 |
parents | d74fbf56f2f6 |
children | c9b51268668f |
comparison
equal
deleted
inserted
replaced
1098:2911ff0a32bb | 1099:1ccbb2b7d905 |
---|---|
18 | 18 |
19 Sam Lantinga | 19 Sam Lantinga |
20 slouken@libsdl.org | 20 slouken@libsdl.org |
21 */ | 21 */ |
22 | 22 |
23 /* RISC OS doesn't have semiphores so use code based on generic implementation */ | 23 /* RISC OS semiphores based on linux code */ |
24 | 24 |
25 #ifdef SAVE_RCSID | 25 #ifdef SAVE_RCSID |
26 static char rcsid = | 26 static char rcsid = |
27 "@(#) $Id$"; | 27 "@(#) $Id$"; |
28 #endif | 28 #endif |
29 | 29 |
30 /* An implementation of semaphores using mutexes and condition variables */ | |
31 | 30 |
32 #include <stdlib.h> | 31 #include <stdlib.h> |
33 | 32 |
34 #include "SDL_error.h" | 33 #include "SDL_error.h" |
35 #include "SDL_timer.h" | 34 #include "SDL_timer.h" |
79 return -1; | 78 return -1; |
80 } | 79 } |
81 | 80 |
82 #else | 81 #else |
83 | 82 |
84 struct SDL_semaphore | 83 |
85 { | 84 #include <stdio.h> |
86 Uint32 count; | 85 #include <stdlib.h> |
87 Uint32 waiters_count; | 86 #include <unistd.h> /* For getpid() */ |
88 SDL_mutex *count_lock; | 87 #include <pthread.h> |
89 SDL_cond *count_nonzero; | 88 #include <semaphore.h> |
89 | |
90 struct SDL_semaphore { | |
91 sem_t *sem; | |
92 sem_t sem_data; | |
90 }; | 93 }; |
91 | 94 |
95 /* Create a semaphore, initialized with value */ | |
92 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) | 96 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) |
93 { | 97 { |
94 SDL_sem *sem; | 98 SDL_sem *sem = (SDL_sem *) malloc(sizeof(SDL_sem)); |
95 | 99 if ( sem ) { |
96 sem = (SDL_sem *)malloc(sizeof(*sem)); | 100 if ( sem_init(&sem->sem_data, 0, initial_value) < 0 ) { |
97 if ( ! sem ) { | 101 SDL_SetError("sem_init() failed"); |
102 free(sem); | |
103 sem = NULL; | |
104 } else { | |
105 sem->sem = &sem->sem_data; | |
106 } | |
107 } else { | |
98 SDL_OutOfMemory(); | 108 SDL_OutOfMemory(); |
99 return(0); | 109 } |
100 } | 110 return sem; |
101 sem->count = initial_value; | 111 } |
102 sem->waiters_count = 0; | 112 |
103 | |
104 sem->count_lock = SDL_CreateMutex(); | |
105 sem->count_nonzero = SDL_CreateCond(); | |
106 if ( ! sem->count_lock || ! sem->count_nonzero ) { | |
107 SDL_DestroySemaphore(sem); | |
108 return(0); | |
109 } | |
110 | |
111 return(sem); | |
112 } | |
113 | |
114 /* WARNING: | |
115 You cannot call this function when another thread is using the semaphore. | |
116 */ | |
117 void SDL_DestroySemaphore(SDL_sem *sem) | 113 void SDL_DestroySemaphore(SDL_sem *sem) |
118 { | 114 { |
119 if ( sem ) { | 115 if ( sem ) { |
120 sem->count = 0xFFFFFFFF; | 116 sem_destroy(sem->sem); |
121 while ( sem->waiters_count > 0) { | |
122 SDL_CondSignal(sem->count_nonzero); | |
123 SDL_Delay(10); | |
124 } | |
125 SDL_DestroyCond(sem->count_nonzero); | |
126 SDL_mutexP(sem->count_lock); | |
127 SDL_mutexV(sem->count_lock); | |
128 SDL_DestroyMutex(sem->count_lock); | |
129 free(sem); | 117 free(sem); |
130 } | 118 } |
131 } | 119 } |
132 | 120 |
133 int SDL_SemTryWait(SDL_sem *sem) | 121 int SDL_SemTryWait(SDL_sem *sem) |
136 | 124 |
137 if ( ! sem ) { | 125 if ( ! sem ) { |
138 SDL_SetError("Passed a NULL semaphore"); | 126 SDL_SetError("Passed a NULL semaphore"); |
139 return -1; | 127 return -1; |
140 } | 128 } |
141 | |
142 retval = SDL_MUTEX_TIMEDOUT; | 129 retval = SDL_MUTEX_TIMEDOUT; |
143 SDL_LockMutex(sem->count_lock); | 130 if ( sem_trywait(sem->sem) == 0 ) { |
144 if ( sem->count > 0 ) { | |
145 --sem->count; | |
146 retval = 0; | 131 retval = 0; |
147 } | 132 } |
148 SDL_UnlockMutex(sem->count_lock); | 133 return retval; |
149 | 134 } |
135 | |
136 int SDL_SemWait(SDL_sem *sem) | |
137 { | |
138 int retval; | |
139 | |
140 if ( ! sem ) { | |
141 SDL_SetError("Passed a NULL semaphore"); | |
142 return -1; | |
143 } | |
144 | |
145 retval = sem_wait(sem->sem); | |
146 if ( retval < 0 ) { | |
147 SDL_SetError("sem_wait() failed"); | |
148 } | |
150 return retval; | 149 return retval; |
151 } | 150 } |
152 | 151 |
153 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) | 152 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) |
154 { | 153 { |
157 if ( ! sem ) { | 156 if ( ! sem ) { |
158 SDL_SetError("Passed a NULL semaphore"); | 157 SDL_SetError("Passed a NULL semaphore"); |
159 return -1; | 158 return -1; |
160 } | 159 } |
161 | 160 |
162 /* A timeout of 0 is an easy case */ | 161 /* Try the easy cases first */ |
163 if ( timeout == 0 ) { | 162 if ( timeout == 0 ) { |
164 return SDL_SemTryWait(sem); | 163 return SDL_SemTryWait(sem); |
165 } | 164 } |
166 | 165 if ( timeout == SDL_MUTEX_MAXWAIT ) { |
167 SDL_LockMutex(sem->count_lock); | 166 return SDL_SemWait(sem); |
168 ++sem->waiters_count; | 167 } |
169 retval = 0; | 168 |
170 while ( (sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT) ) { | 169 /* Ack! We have to busy wait... */ |
171 retval = SDL_CondWaitTimeout(sem->count_nonzero, | 170 timeout += SDL_GetTicks(); |
172 sem->count_lock, timeout); | 171 do { |
173 } | 172 retval = SDL_SemTryWait(sem); |
174 --sem->waiters_count; | 173 if ( retval == 0 ) { |
175 --sem->count; | 174 break; |
176 SDL_UnlockMutex(sem->count_lock); | 175 } |
177 | 176 SDL_Delay(1); |
178 return retval; | 177 } while ( SDL_GetTicks() < timeout ); |
179 } | 178 |
180 | 179 return retval; |
181 int SDL_SemWait(SDL_sem *sem) | |
182 { | |
183 return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); | |
184 } | 180 } |
185 | 181 |
186 Uint32 SDL_SemValue(SDL_sem *sem) | 182 Uint32 SDL_SemValue(SDL_sem *sem) |
187 { | 183 { |
188 Uint32 value; | 184 int ret = 0; |
189 | |
190 value = 0; | |
191 if ( sem ) { | 185 if ( sem ) { |
192 SDL_LockMutex(sem->count_lock); | 186 sem_getvalue(sem->sem, &ret); |
193 value = sem->count; | 187 if ( ret < 0 ) { |
194 SDL_UnlockMutex(sem->count_lock); | 188 ret = 0; |
195 } | 189 } |
196 return value; | 190 } |
191 return (Uint32)ret; | |
197 } | 192 } |
198 | 193 |
199 int SDL_SemPost(SDL_sem *sem) | 194 int SDL_SemPost(SDL_sem *sem) |
200 { | 195 { |
201 if ( ! sem ) { | 196 int retval; |
202 SDL_SetError("Passed a NULL semaphore"); | 197 |
203 return -1; | 198 if ( ! sem ) { |
204 } | 199 SDL_SetError("Passed a NULL semaphore"); |
205 | 200 return -1; |
206 SDL_LockMutex(sem->count_lock); | 201 } |
207 if ( sem->waiters_count > 0 ) { | 202 |
208 SDL_CondSignal(sem->count_nonzero); | 203 retval = sem_post(sem->sem); |
209 } | 204 if ( retval < 0 ) { |
210 ++sem->count; | 205 SDL_SetError("sem_post() failed"); |
211 SDL_UnlockMutex(sem->count_lock); | 206 } |
212 | 207 return retval; |
213 return 0; | |
214 } | 208 } |
215 | 209 |
216 #endif /* DISABLE_THREADS */ | 210 #endif /* DISABLE_THREADS */ |