diff options
Diffstat (limited to 'uisimulator/sdl/thread-sdl.c')
-rw-r--r-- | uisimulator/sdl/thread-sdl.c | 372 |
1 files changed, 211 insertions, 161 deletions
diff --git a/uisimulator/sdl/thread-sdl.c b/uisimulator/sdl/thread-sdl.c index d1a8e60d01..78a66f72a7 100644 --- a/uisimulator/sdl/thread-sdl.c +++ b/uisimulator/sdl/thread-sdl.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <setjmp.h> | 26 | #include <setjmp.h> |
27 | #include "system-sdl.h" | 27 | #include "system-sdl.h" |
28 | #include "thread-sdl.h" | 28 | #include "thread-sdl.h" |
29 | #include "system.h" | ||
29 | #include "kernel.h" | 30 | #include "kernel.h" |
30 | #include "thread.h" | 31 | #include "thread.h" |
31 | #include "debug.h" | 32 | #include "debug.h" |
@@ -37,7 +38,7 @@ | |||
37 | #define THREAD_SDL_DEBUGF(...) DEBUGF(__VA_ARGS__) | 38 | #define THREAD_SDL_DEBUGF(...) DEBUGF(__VA_ARGS__) |
38 | static char __name[32]; | 39 | static char __name[32]; |
39 | #define THREAD_SDL_GET_NAME(thread) \ | 40 | #define THREAD_SDL_GET_NAME(thread) \ |
40 | ({ thread_get_name(__name, sizeof(__name)/sizeof(__name[0]), thread); __name; }) | 41 | ({ thread_get_name(__name, ARRAYLEN(__name), thread); __name; }) |
41 | #else | 42 | #else |
42 | #define THREAD_SDL_DEBUGF(...) | 43 | #define THREAD_SDL_DEBUGF(...) |
43 | #define THREAD_SDL_GET_NAME(thread) | 44 | #define THREAD_SDL_GET_NAME(thread) |
@@ -54,7 +55,6 @@ struct thread_entry threads[MAXTHREADS]; | |||
54 | * way to get them back in there so they may exit */ | 55 | * way to get them back in there so they may exit */ |
55 | static jmp_buf thread_jmpbufs[MAXTHREADS]; | 56 | static jmp_buf thread_jmpbufs[MAXTHREADS]; |
56 | static SDL_mutex *m; | 57 | static SDL_mutex *m; |
57 | static struct thread_entry *running; | ||
58 | static bool threads_exit = false; | 58 | static bool threads_exit = false; |
59 | 59 | ||
60 | extern long start_tick; | 60 | extern long start_tick; |
@@ -78,7 +78,7 @@ void thread_sdl_shutdown(void) | |||
78 | { | 78 | { |
79 | /* Signal thread on delay or block */ | 79 | /* Signal thread on delay or block */ |
80 | SDL_Thread *t = thread->context.t; | 80 | SDL_Thread *t = thread->context.t; |
81 | SDL_CondSignal(thread->context.c); | 81 | SDL_SemPost(thread->context.s); |
82 | SDL_UnlockMutex(m); | 82 | SDL_UnlockMutex(m); |
83 | /* Wait for it to finish */ | 83 | /* Wait for it to finish */ |
84 | SDL_WaitThread(t, NULL); | 84 | SDL_WaitThread(t, NULL); |
@@ -98,7 +98,7 @@ extern void app_main(void *param); | |||
98 | static int thread_sdl_app_main(void *param) | 98 | static int thread_sdl_app_main(void *param) |
99 | { | 99 | { |
100 | SDL_LockMutex(m); | 100 | SDL_LockMutex(m); |
101 | running = &threads[0]; | 101 | cores[CURRENT_CORE].running = &threads[0]; |
102 | 102 | ||
103 | /* Set the jump address for return */ | 103 | /* Set the jump address for return */ |
104 | if (setjmp(thread_jmpbufs[0]) == 0) | 104 | if (setjmp(thread_jmpbufs[0]) == 0) |
@@ -116,6 +116,8 @@ static int thread_sdl_app_main(void *param) | |||
116 | /* Initialize SDL threading */ | 116 | /* Initialize SDL threading */ |
117 | bool thread_sdl_init(void *param) | 117 | bool thread_sdl_init(void *param) |
118 | { | 118 | { |
119 | struct thread_entry *thread; | ||
120 | memset(cores, 0, sizeof(cores)); | ||
119 | memset(threads, 0, sizeof(threads)); | 121 | memset(threads, 0, sizeof(threads)); |
120 | 122 | ||
121 | m = SDL_CreateMutex(); | 123 | m = SDL_CreateMutex(); |
@@ -129,28 +131,30 @@ bool thread_sdl_init(void *param) | |||
129 | /* Slot 0 is reserved for the main thread - initialize it here and | 131 | /* Slot 0 is reserved for the main thread - initialize it here and |
130 | then create the SDL thread - it is possible to have a quick, early | 132 | then create the SDL thread - it is possible to have a quick, early |
131 | shutdown try to access the structure. */ | 133 | shutdown try to access the structure. */ |
132 | running = &threads[0]; | 134 | thread = &threads[0]; |
133 | running->stack = " "; | 135 | thread->stack = (uintptr_t *)" "; |
134 | running->stack_size = 8; | 136 | thread->stack_size = 8; |
135 | running->name = "main"; | 137 | thread->name = "main"; |
136 | running->state = STATE_RUNNING; | 138 | thread->state = STATE_RUNNING; |
137 | running->context.c = SDL_CreateCond(); | 139 | thread->context.s = SDL_CreateSemaphore(0); |
140 | cores[CURRENT_CORE].running = thread; | ||
138 | 141 | ||
139 | if (running->context.c == NULL) | 142 | if (thread->context.s == NULL) |
140 | { | 143 | { |
141 | fprintf(stderr, "Failed to create main condition variable\n"); | 144 | fprintf(stderr, "Failed to create main semaphore\n"); |
142 | return false; | 145 | return false; |
143 | } | 146 | } |
144 | 147 | ||
145 | running->context.t = SDL_CreateThread(thread_sdl_app_main, param); | 148 | thread->context.t = SDL_CreateThread(thread_sdl_app_main, param); |
146 | 149 | ||
147 | if (running->context.t == NULL) | 150 | if (thread->context.t == NULL) |
148 | { | 151 | { |
152 | SDL_DestroySemaphore(thread->context.s); | ||
149 | fprintf(stderr, "Failed to create main thread\n"); | 153 | fprintf(stderr, "Failed to create main thread\n"); |
150 | return false; | 154 | return false; |
151 | } | 155 | } |
152 | 156 | ||
153 | THREAD_SDL_DEBUGF("Main thread: %p\n", running); | 157 | THREAD_SDL_DEBUGF("Main thread: %p\n", thread); |
154 | 158 | ||
155 | SDL_UnlockMutex(m); | 159 | SDL_UnlockMutex(m); |
156 | return true; | 160 | return true; |
@@ -160,21 +164,22 @@ bool thread_sdl_init(void *param) | |||
160 | void thread_sdl_thread_lock(void *me) | 164 | void thread_sdl_thread_lock(void *me) |
161 | { | 165 | { |
162 | SDL_LockMutex(m); | 166 | SDL_LockMutex(m); |
163 | running = (struct thread_entry *)me; | 167 | cores[CURRENT_CORE].running = (struct thread_entry *)me; |
164 | 168 | ||
165 | if (threads_exit) | 169 | if (threads_exit) |
166 | remove_thread(NULL); | 170 | thread_exit(); |
167 | } | 171 | } |
168 | 172 | ||
169 | void * thread_sdl_thread_unlock(void) | 173 | void * thread_sdl_thread_unlock(void) |
170 | { | 174 | { |
171 | struct thread_entry *current = running; | 175 | struct thread_entry *current = cores[CURRENT_CORE].running; |
172 | SDL_UnlockMutex(m); | 176 | SDL_UnlockMutex(m); |
173 | return current; | 177 | return current; |
174 | } | 178 | } |
175 | 179 | ||
176 | static int find_empty_thread_slot(void) | 180 | static struct thread_entry * find_empty_thread_slot(void) |
177 | { | 181 | { |
182 | struct thread_entry *thread = NULL; | ||
178 | int n; | 183 | int n; |
179 | 184 | ||
180 | for (n = 0; n < MAXTHREADS; n++) | 185 | for (n = 0; n < MAXTHREADS; n++) |
@@ -182,10 +187,13 @@ static int find_empty_thread_slot(void) | |||
182 | int state = threads[n].state; | 187 | int state = threads[n].state; |
183 | 188 | ||
184 | if (state == STATE_KILLED) | 189 | if (state == STATE_KILLED) |
190 | { | ||
191 | thread = &threads[n]; | ||
185 | break; | 192 | break; |
193 | } | ||
186 | } | 194 | } |
187 | 195 | ||
188 | return n; | 196 | return thread; |
189 | } | 197 | } |
190 | 198 | ||
191 | static void add_to_list_l(struct thread_entry **list, | 199 | static void add_to_list_l(struct thread_entry **list, |
@@ -229,64 +237,163 @@ static void remove_from_list_l(struct thread_entry **list, | |||
229 | thread->l.next->l.prev = thread->l.prev; | 237 | thread->l.next->l.prev = thread->l.prev; |
230 | } | 238 | } |
231 | 239 | ||
232 | static inline void run_blocking_ops(void) | ||
233 | { | ||
234 | set_irq_level(0); | ||
235 | } | ||
236 | |||
237 | struct thread_entry *thread_get_current(void) | 240 | struct thread_entry *thread_get_current(void) |
238 | { | 241 | { |
239 | return running; | 242 | return cores[CURRENT_CORE].running; |
240 | } | 243 | } |
241 | 244 | ||
242 | void switch_thread(struct thread_entry *old) | 245 | void switch_thread(void) |
243 | { | 246 | { |
244 | struct thread_entry *current = running; | 247 | struct thread_entry *current = cores[CURRENT_CORE].running; |
245 | 248 | ||
246 | SDL_UnlockMutex(m); | 249 | set_irq_level(0); |
247 | /* Any other thread waiting already will get it first */ | ||
248 | SDL_LockMutex(m); | ||
249 | running = current; | ||
250 | 250 | ||
251 | if (threads_exit) | 251 | switch (current->state) |
252 | remove_thread(NULL); | 252 | { |
253 | case STATE_RUNNING: | ||
254 | { | ||
255 | SDL_UnlockMutex(m); | ||
256 | /* Any other thread waiting already will get it first */ | ||
257 | SDL_LockMutex(m); | ||
258 | break; | ||
259 | } /* STATE_RUNNING: */ | ||
260 | |||
261 | case STATE_BLOCKED: | ||
262 | { | ||
263 | int oldlevel; | ||
264 | |||
265 | SDL_UnlockMutex(m); | ||
266 | SDL_SemWait(current->context.s); | ||
267 | SDL_LockMutex(m); | ||
268 | |||
269 | oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); | ||
270 | current->state = STATE_RUNNING; | ||
271 | set_irq_level(oldlevel); | ||
272 | break; | ||
273 | } /* STATE_BLOCKED: */ | ||
274 | |||
275 | case STATE_BLOCKED_W_TMO: | ||
276 | { | ||
277 | int result, oldlevel; | ||
278 | |||
279 | SDL_UnlockMutex(m); | ||
280 | result = SDL_SemWaitTimeout(current->context.s, current->tmo_tick); | ||
281 | SDL_LockMutex(m); | ||
282 | |||
283 | oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); | ||
284 | |||
285 | if (current->state == STATE_BLOCKED_W_TMO) | ||
286 | { | ||
287 | /* Timed out */ | ||
288 | remove_from_list_l(current->bqp, current); | ||
289 | |||
290 | #ifdef HAVE_WAKEUP_EXT_CB | ||
291 | if (current->wakeup_ext_cb != NULL) | ||
292 | current->wakeup_ext_cb(current); | ||
293 | #endif | ||
294 | current->state = STATE_RUNNING; | ||
295 | } | ||
253 | 296 | ||
254 | (void)old; | 297 | if (result == SDL_MUTEX_TIMEDOUT) |
298 | { | ||
299 | /* Other signals from an explicit wake could have been made before | ||
300 | * arriving here if we timed out waiting for the semaphore. Make | ||
301 | * sure the count is reset. */ | ||
302 | while (SDL_SemValue(current->context.s) > 0) | ||
303 | SDL_SemTryWait(current->context.s); | ||
304 | } | ||
305 | |||
306 | set_irq_level(oldlevel); | ||
307 | break; | ||
308 | } /* STATE_BLOCKED_W_TMO: */ | ||
309 | |||
310 | case STATE_SLEEPING: | ||
311 | { | ||
312 | SDL_UnlockMutex(m); | ||
313 | SDL_SemWaitTimeout(current->context.s, current->tmo_tick); | ||
314 | SDL_LockMutex(m); | ||
315 | current->state = STATE_RUNNING; | ||
316 | break; | ||
317 | } /* STATE_SLEEPING: */ | ||
318 | } | ||
319 | |||
320 | cores[CURRENT_CORE].running = current; | ||
321 | |||
322 | if (threads_exit) | ||
323 | thread_exit(); | ||
255 | } | 324 | } |
256 | 325 | ||
257 | void sleep_thread(int ticks) | 326 | void sleep_thread(int ticks) |
258 | { | 327 | { |
259 | struct thread_entry *current; | 328 | struct thread_entry *current = cores[CURRENT_CORE].running; |
260 | int rem; | 329 | int rem; |
261 | 330 | ||
262 | current = running; | ||
263 | current->state = STATE_SLEEPING; | 331 | current->state = STATE_SLEEPING; |
264 | 332 | ||
265 | rem = (SDL_GetTicks() - start_tick) % (1000/HZ); | 333 | rem = (SDL_GetTicks() - start_tick) % (1000/HZ); |
266 | if (rem < 0) | 334 | if (rem < 0) |
267 | rem = 0; | 335 | rem = 0; |
268 | 336 | ||
269 | rem = (1000/HZ) * ticks + ((1000/HZ)-1) - rem; | 337 | current->tmo_tick = (1000/HZ) * ticks + ((1000/HZ)-1) - rem; |
338 | } | ||
339 | |||
340 | void block_thread(struct thread_entry *current) | ||
341 | { | ||
342 | current->state = STATE_BLOCKED; | ||
343 | add_to_list_l(current->bqp, current); | ||
344 | } | ||
345 | |||
346 | void block_thread_w_tmo(struct thread_entry *current, int ticks) | ||
347 | { | ||
348 | current->state = STATE_BLOCKED_W_TMO; | ||
349 | current->tmo_tick = (1000/HZ)*ticks; | ||
350 | add_to_list_l(current->bqp, current); | ||
351 | } | ||
352 | |||
353 | unsigned int wakeup_thread(struct thread_entry **list) | ||
354 | { | ||
355 | struct thread_entry *thread = *list; | ||
270 | 356 | ||
271 | if (rem == 0) | 357 | if (thread != NULL) |
272 | { | 358 | { |
273 | /* Unlock and give up rest of quantum */ | 359 | switch (thread->state) |
274 | SDL_UnlockMutex(m); | 360 | { |
275 | SDL_Delay(0); | 361 | case STATE_BLOCKED: |
276 | SDL_LockMutex(m); | 362 | case STATE_BLOCKED_W_TMO: |
363 | remove_from_list_l(list, thread); | ||
364 | thread->state = STATE_RUNNING; | ||
365 | SDL_SemPost(thread->context.s); | ||
366 | return THREAD_OK; | ||
367 | } | ||
277 | } | 368 | } |
278 | else | 369 | |
370 | return THREAD_NONE; | ||
371 | } | ||
372 | |||
373 | unsigned int thread_queue_wake(struct thread_entry **list) | ||
374 | { | ||
375 | unsigned int result = THREAD_NONE; | ||
376 | |||
377 | for (;;) | ||
279 | { | 378 | { |
280 | /* These sleeps must be signalable for thread exit */ | 379 | unsigned int rc = wakeup_thread(list); |
281 | SDL_CondWaitTimeout(current->context.c, m, rem); | ||
282 | } | ||
283 | 380 | ||
284 | running = current; | 381 | if (rc == THREAD_NONE) |
382 | break; | ||
285 | 383 | ||
286 | current->state = STATE_RUNNING; | 384 | result |= rc; |
385 | } | ||
287 | 386 | ||
288 | if (threads_exit) | 387 | return result; |
289 | remove_thread(NULL); | 388 | } |
389 | |||
390 | void thread_thaw(struct thread_entry *thread) | ||
391 | { | ||
392 | if (thread->state == STATE_FROZEN) | ||
393 | { | ||
394 | thread->state = STATE_RUNNING; | ||
395 | SDL_SemPost(thread->context.s); | ||
396 | } | ||
290 | } | 397 | } |
291 | 398 | ||
292 | int runthread(void *data) | 399 | int runthread(void *data) |
@@ -297,9 +404,9 @@ int runthread(void *data) | |||
297 | /* Cannot access thread variables before locking the mutex as the | 404 | /* Cannot access thread variables before locking the mutex as the |
298 | data structures may not be filled-in yet. */ | 405 | data structures may not be filled-in yet. */ |
299 | SDL_LockMutex(m); | 406 | SDL_LockMutex(m); |
300 | running = (struct thread_entry *)data; | 407 | cores[CURRENT_CORE].running = (struct thread_entry *)data; |
301 | current = running; | 408 | current = cores[CURRENT_CORE].running; |
302 | current_jmpbuf = &thread_jmpbufs[running - threads]; | 409 | current_jmpbuf = &thread_jmpbufs[current - threads]; |
303 | 410 | ||
304 | /* Setup jump for exit */ | 411 | /* Setup jump for exit */ |
305 | if (setjmp(*current_jmpbuf) == 0) | 412 | if (setjmp(*current_jmpbuf) == 0) |
@@ -307,9 +414,10 @@ int runthread(void *data) | |||
307 | /* Run the thread routine */ | 414 | /* Run the thread routine */ |
308 | if (current->state == STATE_FROZEN) | 415 | if (current->state == STATE_FROZEN) |
309 | { | 416 | { |
310 | SDL_CondWait(current->context.c, m); | 417 | SDL_UnlockMutex(m); |
311 | running = current; | 418 | SDL_SemWait(current->context.s); |
312 | 419 | SDL_LockMutex(m); | |
420 | cores[CURRENT_CORE].running = current; | ||
313 | } | 421 | } |
314 | 422 | ||
315 | if (!threads_exit) | 423 | if (!threads_exit) |
@@ -320,7 +428,7 @@ int runthread(void *data) | |||
320 | /* Thread routine returned - suicide */ | 428 | /* Thread routine returned - suicide */ |
321 | } | 429 | } |
322 | 430 | ||
323 | remove_thread(NULL); | 431 | thread_exit(); |
324 | } | 432 | } |
325 | else | 433 | else |
326 | { | 434 | { |
@@ -332,131 +440,59 @@ int runthread(void *data) | |||
332 | } | 440 | } |
333 | 441 | ||
334 | struct thread_entry* | 442 | struct thread_entry* |
335 | create_thread(void (*function)(void), void* stack, int stack_size, | 443 | create_thread(void (*function)(void), void* stack, size_t stack_size, |
336 | unsigned flags, const char *name) | 444 | unsigned flags, const char *name) |
337 | { | 445 | { |
338 | /** Avoid compiler warnings */ | 446 | struct thread_entry *thread; |
339 | SDL_Thread* t; | 447 | SDL_Thread* t; |
340 | SDL_cond *cond; | 448 | SDL_sem *s; |
341 | int slot; | ||
342 | 449 | ||
343 | THREAD_SDL_DEBUGF("Creating thread: (%s)\n", name ? name : ""); | 450 | THREAD_SDL_DEBUGF("Creating thread: (%s)\n", name ? name : ""); |
344 | 451 | ||
345 | slot = find_empty_thread_slot(); | 452 | thread = find_empty_thread_slot(); |
346 | if (slot >= MAXTHREADS) | 453 | if (thread == NULL) |
347 | { | 454 | { |
348 | DEBUGF("Failed to find thread slot\n"); | 455 | DEBUGF("Failed to find thread slot\n"); |
349 | return NULL; | 456 | return NULL; |
350 | } | 457 | } |
351 | 458 | ||
352 | cond = SDL_CreateCond(); | 459 | s = SDL_CreateSemaphore(0); |
353 | if (cond == NULL) | 460 | if (s == NULL) |
354 | { | 461 | { |
355 | DEBUGF("Failed to create condition variable\n"); | 462 | DEBUGF("Failed to create semaphore\n"); |
356 | return NULL; | 463 | return NULL; |
357 | } | 464 | } |
358 | 465 | ||
359 | t = SDL_CreateThread(runthread, &threads[slot]); | 466 | t = SDL_CreateThread(runthread, thread); |
360 | if (t == NULL) | 467 | if (t == NULL) |
361 | { | 468 | { |
362 | DEBUGF("Failed to create SDL thread\n"); | 469 | DEBUGF("Failed to create SDL thread\n"); |
363 | SDL_DestroyCond(cond); | 470 | SDL_DestroySemaphore(s); |
364 | return NULL; | 471 | return NULL; |
365 | } | 472 | } |
366 | 473 | ||
367 | threads[slot].stack = stack; | 474 | thread->stack = stack; |
368 | threads[slot].stack_size = stack_size; | 475 | thread->stack_size = stack_size; |
369 | threads[slot].name = name; | 476 | thread->name = name; |
370 | threads[slot].state = (flags & CREATE_THREAD_FROZEN) ? | 477 | thread->state = (flags & CREATE_THREAD_FROZEN) ? |
371 | STATE_FROZEN : STATE_RUNNING; | 478 | STATE_FROZEN : STATE_RUNNING; |
372 | threads[slot].context.start = function; | 479 | thread->context.start = function; |
373 | threads[slot].context.t = t; | 480 | thread->context.t = t; |
374 | threads[slot].context.c = cond; | 481 | thread->context.s = s; |
375 | 482 | ||
376 | THREAD_SDL_DEBUGF("New Thread: %d (%s)\n", | 483 | THREAD_SDL_DEBUGF("New Thread: %d (%s)\n", |
377 | slot, THREAD_SDL_GET_NAME(&threads[slot])); | 484 | thread - threads, THREAD_SDL_GET_NAME(thread)); |
378 | 485 | ||
379 | return &threads[slot]; | 486 | return thread; |
380 | } | ||
381 | |||
382 | void _block_thread(struct thread_queue *tq) | ||
383 | { | ||
384 | struct thread_entry *thread = running; | ||
385 | |||
386 | thread->state = STATE_BLOCKED; | ||
387 | thread->bqp = tq; | ||
388 | add_to_list_l(&tq->queue, thread); | ||
389 | |||
390 | run_blocking_ops(); | ||
391 | |||
392 | SDL_CondWait(thread->context.c, m); | ||
393 | running = thread; | ||
394 | |||
395 | if (threads_exit) | ||
396 | remove_thread(NULL); | ||
397 | } | ||
398 | |||
399 | void block_thread_w_tmo(struct thread_queue *tq, int ticks) | ||
400 | { | ||
401 | struct thread_entry *thread = running; | ||
402 | |||
403 | thread->state = STATE_BLOCKED_W_TMO; | ||
404 | thread->bqp = tq; | ||
405 | add_to_list_l(&tq->queue, thread); | ||
406 | |||
407 | run_blocking_ops(); | ||
408 | |||
409 | SDL_CondWaitTimeout(thread->context.c, m, (1000/HZ) * ticks); | ||
410 | running = thread; | ||
411 | |||
412 | if (thread->state == STATE_BLOCKED_W_TMO) | ||
413 | { | ||
414 | /* Timed out */ | ||
415 | remove_from_list_l(&tq->queue, thread); | ||
416 | thread->state = STATE_RUNNING; | ||
417 | } | ||
418 | |||
419 | if (threads_exit) | ||
420 | remove_thread(NULL); | ||
421 | } | ||
422 | |||
423 | struct thread_entry * _wakeup_thread(struct thread_queue *tq) | ||
424 | { | ||
425 | struct thread_entry *thread = tq->queue; | ||
426 | |||
427 | if (thread == NULL) | ||
428 | { | ||
429 | return NULL; | ||
430 | } | ||
431 | |||
432 | switch (thread->state) | ||
433 | { | ||
434 | case STATE_BLOCKED: | ||
435 | case STATE_BLOCKED_W_TMO: | ||
436 | remove_from_list_l(&tq->queue, thread); | ||
437 | thread->state = STATE_RUNNING; | ||
438 | SDL_CondSignal(thread->context.c); | ||
439 | return thread; | ||
440 | default: | ||
441 | return NULL; | ||
442 | } | ||
443 | } | ||
444 | |||
445 | void thread_thaw(struct thread_entry *thread) | ||
446 | { | ||
447 | if (thread->state == STATE_FROZEN) | ||
448 | { | ||
449 | thread->state = STATE_RUNNING; | ||
450 | SDL_CondSignal(thread->context.c); | ||
451 | } | ||
452 | } | 487 | } |
453 | 488 | ||
454 | void init_threads(void) | 489 | void init_threads(void) |
455 | { | 490 | { |
456 | /* Main thread is already initialized */ | 491 | /* Main thread is already initialized */ |
457 | if (running != &threads[0]) | 492 | if (cores[CURRENT_CORE].running != &threads[0]) |
458 | { | 493 | { |
459 | THREAD_PANICF("Wrong main thread in init_threads: %p\n", running); | 494 | THREAD_PANICF("Wrong main thread in init_threads: %p\n", |
495 | cores[CURRENT_CORE].running); | ||
460 | } | 496 | } |
461 | 497 | ||
462 | THREAD_SDL_DEBUGF("First Thread: %d (%s)\n", | 498 | THREAD_SDL_DEBUGF("First Thread: %d (%s)\n", |
@@ -465,9 +501,9 @@ void init_threads(void) | |||
465 | 501 | ||
466 | void remove_thread(struct thread_entry *thread) | 502 | void remove_thread(struct thread_entry *thread) |
467 | { | 503 | { |
468 | struct thread_entry *current = running; | 504 | struct thread_entry *current = cores[CURRENT_CORE].running; |
469 | SDL_Thread *t; | 505 | SDL_Thread *t; |
470 | SDL_cond *c; | 506 | SDL_sem *s; |
471 | 507 | ||
472 | int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); | 508 | int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); |
473 | 509 | ||
@@ -477,7 +513,7 @@ void remove_thread(struct thread_entry *thread) | |||
477 | } | 513 | } |
478 | 514 | ||
479 | t = thread->context.t; | 515 | t = thread->context.t; |
480 | c = thread->context.c; | 516 | s = thread->context.s; |
481 | thread->context.t = NULL; | 517 | thread->context.t = NULL; |
482 | 518 | ||
483 | if (thread != current) | 519 | if (thread != current) |
@@ -487,20 +523,25 @@ void remove_thread(struct thread_entry *thread) | |||
487 | case STATE_BLOCKED: | 523 | case STATE_BLOCKED: |
488 | case STATE_BLOCKED_W_TMO: | 524 | case STATE_BLOCKED_W_TMO: |
489 | /* Remove thread from object it's waiting on */ | 525 | /* Remove thread from object it's waiting on */ |
490 | remove_from_list_l(&thread->bqp->queue, thread); | 526 | remove_from_list_l(thread->bqp, thread); |
527 | |||
528 | #ifdef HAVE_WAKEUP_EXT_CB | ||
529 | if (thread->wakeup_ext_cb != NULL) | ||
530 | thread->wakeup_ext_cb(thread); | ||
531 | #endif | ||
491 | break; | 532 | break; |
492 | } | 533 | } |
493 | 534 | ||
494 | SDL_CondSignal(c); | 535 | SDL_SemPost(s); |
495 | } | 536 | } |
496 | 537 | ||
497 | THREAD_SDL_DEBUGF("Removing thread: %d (%s)\n", | 538 | THREAD_SDL_DEBUGF("Removing thread: %d (%s)\n", |
498 | thread - threads, THREAD_SDL_GET_NAME(thread)); | 539 | thread - threads, THREAD_SDL_GET_NAME(thread)); |
499 | 540 | ||
500 | thread_queue_wake_no_listlock(&thread->queue); | ||
501 | thread->state = STATE_KILLED; | 541 | thread->state = STATE_KILLED; |
542 | thread_queue_wake(&thread->queue); | ||
502 | 543 | ||
503 | SDL_DestroyCond(c); | 544 | SDL_DestroySemaphore(s); |
504 | 545 | ||
505 | if (thread == current) | 546 | if (thread == current) |
506 | { | 547 | { |
@@ -514,14 +555,23 @@ void remove_thread(struct thread_entry *thread) | |||
514 | set_irq_level(oldlevel); | 555 | set_irq_level(oldlevel); |
515 | } | 556 | } |
516 | 557 | ||
558 | void thread_exit(void) | ||
559 | { | ||
560 | remove_thread(NULL); | ||
561 | } | ||
562 | |||
517 | void thread_wait(struct thread_entry *thread) | 563 | void thread_wait(struct thread_entry *thread) |
518 | { | 564 | { |
565 | struct thread_entry *current = cores[CURRENT_CORE].running; | ||
566 | |||
519 | if (thread == NULL) | 567 | if (thread == NULL) |
520 | thread = running; | 568 | thread = current; |
521 | 569 | ||
522 | if (thread->state != STATE_KILLED) | 570 | if (thread->state != STATE_KILLED) |
523 | { | 571 | { |
524 | block_thread_no_listlock(&thread->queue); | 572 | current->bqp = &thread->queue; |
573 | block_thread(current); | ||
574 | switch_thread(); | ||
525 | } | 575 | } |
526 | } | 576 | } |
527 | 577 | ||