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 */