diff options
Diffstat (limited to 'uisimulator/sdl')
-rw-r--r-- | uisimulator/sdl/thread-sdl.c | 115 |
1 files changed, 71 insertions, 44 deletions
diff --git a/uisimulator/sdl/thread-sdl.c b/uisimulator/sdl/thread-sdl.c index 905a017ee0..ab1086dd7d 100644 --- a/uisimulator/sdl/thread-sdl.c +++ b/uisimulator/sdl/thread-sdl.c | |||
@@ -93,6 +93,38 @@ void thread_sdl_shutdown(void) | |||
93 | SDL_DestroyMutex(m); | 93 | SDL_DestroyMutex(m); |
94 | } | 94 | } |
95 | 95 | ||
96 | static void new_thread_id(unsigned int slot_num, | ||
97 | struct thread_entry *thread) | ||
98 | { | ||
99 | unsigned int version = | ||
100 | (thread->id + (1u << THREAD_ID_VERSION_SHIFT)) | ||
101 | & THREAD_ID_VERSION_MASK; | ||
102 | |||
103 | if (version == 0) | ||
104 | version = 1u << THREAD_ID_VERSION_SHIFT; | ||
105 | |||
106 | thread->id = version | (slot_num & THREAD_ID_SLOT_MASK); | ||
107 | } | ||
108 | |||
109 | static struct thread_entry * find_empty_thread_slot(void) | ||
110 | { | ||
111 | struct thread_entry *thread = NULL; | ||
112 | int n; | ||
113 | |||
114 | for (n = 0; n < MAXTHREADS; n++) | ||
115 | { | ||
116 | int state = threads[n].state; | ||
117 | |||
118 | if (state == STATE_KILLED) | ||
119 | { | ||
120 | thread = &threads[n]; | ||
121 | break; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | return thread; | ||
126 | } | ||
127 | |||
96 | /* Do main thread creation in this file scope to avoid the need to double- | 128 | /* Do main thread creation in this file scope to avoid the need to double- |
97 | return to a prior call-level which would be unaware of the fact setjmp | 129 | return to a prior call-level which would be unaware of the fact setjmp |
98 | was used */ | 130 | was used */ |
@@ -119,6 +151,8 @@ static int thread_sdl_app_main(void *param) | |||
119 | bool thread_sdl_init(void *param) | 151 | bool thread_sdl_init(void *param) |
120 | { | 152 | { |
121 | struct thread_entry *thread; | 153 | struct thread_entry *thread; |
154 | int n; | ||
155 | |||
122 | memset(cores, 0, sizeof(cores)); | 156 | memset(cores, 0, sizeof(cores)); |
123 | memset(threads, 0, sizeof(threads)); | 157 | memset(threads, 0, sizeof(threads)); |
124 | 158 | ||
@@ -130,6 +164,10 @@ bool thread_sdl_init(void *param) | |||
130 | return false; | 164 | return false; |
131 | } | 165 | } |
132 | 166 | ||
167 | /* Initialize all IDs */ | ||
168 | for (n = 0; n < MAXTHREADS; n++) | ||
169 | threads[n].id = THREAD_ID_INIT(n); | ||
170 | |||
133 | /* Slot 0 is reserved for the main thread - initialize it here and | 171 | /* Slot 0 is reserved for the main thread - initialize it here and |
134 | then create the SDL thread - it is possible to have a quick, early | 172 | then create the SDL thread - it is possible to have a quick, early |
135 | shutdown try to access the structure. */ | 173 | shutdown try to access the structure. */ |
@@ -179,23 +217,11 @@ void * thread_sdl_thread_unlock(void) | |||
179 | return current; | 217 | return current; |
180 | } | 218 | } |
181 | 219 | ||
182 | static struct thread_entry * find_empty_thread_slot(void) | 220 | struct thread_entry * thread_id_entry(unsigned int thread_id) |
183 | { | 221 | { |
184 | struct thread_entry *thread = NULL; | 222 | return (thread_id == THREAD_ID_CURRENT) ? |
185 | int n; | 223 | cores[CURRENT_CORE].running : |
186 | 224 | &threads[thread_id & THREAD_ID_SLOT_MASK]; | |
187 | for (n = 0; n < MAXTHREADS; n++) | ||
188 | { | ||
189 | int state = threads[n].state; | ||
190 | |||
191 | if (state == STATE_KILLED) | ||
192 | { | ||
193 | thread = &threads[n]; | ||
194 | break; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | return thread; | ||
199 | } | 225 | } |
200 | 226 | ||
201 | static void add_to_list_l(struct thread_entry **list, | 227 | static void add_to_list_l(struct thread_entry **list, |
@@ -239,9 +265,9 @@ static void remove_from_list_l(struct thread_entry **list, | |||
239 | thread->l.next->l.prev = thread->l.prev; | 265 | thread->l.next->l.prev = thread->l.prev; |
240 | } | 266 | } |
241 | 267 | ||
242 | struct thread_entry *thread_get_current(void) | 268 | unsigned int thread_get_current(void) |
243 | { | 269 | { |
244 | return cores[CURRENT_CORE].running; | 270 | return cores[CURRENT_CORE].running->id; |
245 | } | 271 | } |
246 | 272 | ||
247 | void switch_thread(void) | 273 | void switch_thread(void) |
@@ -389,9 +415,11 @@ unsigned int thread_queue_wake(struct thread_entry **list) | |||
389 | return result; | 415 | return result; |
390 | } | 416 | } |
391 | 417 | ||
392 | void thread_thaw(struct thread_entry *thread) | 418 | void thread_thaw(unsigned int thread_id) |
393 | { | 419 | { |
394 | if (thread->state == STATE_FROZEN) | 420 | struct thread_entry *thread = thread_id_entry(thread_id); |
421 | |||
422 | if (thread->id == thread_id && thread->state == STATE_FROZEN) | ||
395 | { | 423 | { |
396 | thread->state = STATE_RUNNING; | 424 | thread->state = STATE_RUNNING; |
397 | SDL_SemPost(thread->context.s); | 425 | SDL_SemPost(thread->context.s); |
@@ -441,9 +469,9 @@ int runthread(void *data) | |||
441 | return 0; | 469 | return 0; |
442 | } | 470 | } |
443 | 471 | ||
444 | struct thread_entry* | 472 | unsigned int create_thread(void (*function)(void), |
445 | create_thread(void (*function)(void), void* stack, size_t stack_size, | 473 | void* stack, size_t stack_size, |
446 | unsigned flags, const char *name) | 474 | unsigned flags, const char *name) |
447 | { | 475 | { |
448 | struct thread_entry *thread; | 476 | struct thread_entry *thread; |
449 | SDL_Thread* t; | 477 | SDL_Thread* t; |
@@ -455,14 +483,14 @@ struct thread_entry* | |||
455 | if (thread == NULL) | 483 | if (thread == NULL) |
456 | { | 484 | { |
457 | DEBUGF("Failed to find thread slot\n"); | 485 | DEBUGF("Failed to find thread slot\n"); |
458 | return NULL; | 486 | return 0; |
459 | } | 487 | } |
460 | 488 | ||
461 | s = SDL_CreateSemaphore(0); | 489 | s = SDL_CreateSemaphore(0); |
462 | if (s == NULL) | 490 | if (s == NULL) |
463 | { | 491 | { |
464 | DEBUGF("Failed to create semaphore\n"); | 492 | DEBUGF("Failed to create semaphore\n"); |
465 | return NULL; | 493 | return 0; |
466 | } | 494 | } |
467 | 495 | ||
468 | t = SDL_CreateThread(runthread, thread); | 496 | t = SDL_CreateThread(runthread, thread); |
@@ -470,7 +498,7 @@ struct thread_entry* | |||
470 | { | 498 | { |
471 | DEBUGF("Failed to create SDL thread\n"); | 499 | DEBUGF("Failed to create SDL thread\n"); |
472 | SDL_DestroySemaphore(s); | 500 | SDL_DestroySemaphore(s); |
473 | return NULL; | 501 | return 0; |
474 | } | 502 | } |
475 | 503 | ||
476 | thread->stack = stack; | 504 | thread->stack = stack; |
@@ -485,7 +513,7 @@ struct thread_entry* | |||
485 | THREAD_SDL_DEBUGF("New Thread: %d (%s)\n", | 513 | THREAD_SDL_DEBUGF("New Thread: %d (%s)\n", |
486 | thread - threads, THREAD_SDL_GET_NAME(thread)); | 514 | thread - threads, THREAD_SDL_GET_NAME(thread)); |
487 | 515 | ||
488 | return thread; | 516 | return thread->id; |
489 | } | 517 | } |
490 | 518 | ||
491 | void init_threads(void) | 519 | void init_threads(void) |
@@ -501,18 +529,22 @@ void init_threads(void) | |||
501 | 0, THREAD_SDL_GET_NAME(&threads[0])); | 529 | 0, THREAD_SDL_GET_NAME(&threads[0])); |
502 | } | 530 | } |
503 | 531 | ||
504 | void remove_thread(struct thread_entry *thread) | 532 | #ifndef ALLOW_REMOVE_THREAD |
533 | static void remove_thread(unsigned int thread_id) | ||
534 | #else | ||
535 | void remove_thread(unsigned int thread_id) | ||
536 | #endif | ||
505 | { | 537 | { |
506 | struct thread_entry *current = cores[CURRENT_CORE].running; | 538 | struct thread_entry *current = cores[CURRENT_CORE].running; |
539 | struct thread_entry *thread = thread_id_entry(thread_id); | ||
540 | |||
507 | SDL_Thread *t; | 541 | SDL_Thread *t; |
508 | SDL_sem *s; | 542 | SDL_sem *s; |
509 | 543 | ||
510 | int oldlevel = disable_irq_save(); | 544 | if (thread_id != THREAD_ID_CURRENT && thread->id != thread_id) |
545 | return; | ||
511 | 546 | ||
512 | if (thread == NULL) | 547 | int oldlevel = disable_irq_save(); |
513 | { | ||
514 | thread = current; | ||
515 | } | ||
516 | 548 | ||
517 | t = thread->context.t; | 549 | t = thread->context.t; |
518 | s = thread->context.s; | 550 | s = thread->context.s; |
@@ -540,6 +572,7 @@ void remove_thread(struct thread_entry *thread) | |||
540 | THREAD_SDL_DEBUGF("Removing thread: %d (%s)\n", | 572 | THREAD_SDL_DEBUGF("Removing thread: %d (%s)\n", |
541 | thread - threads, THREAD_SDL_GET_NAME(thread)); | 573 | thread - threads, THREAD_SDL_GET_NAME(thread)); |
542 | 574 | ||
575 | new_thread_id(thread->id, thread); | ||
543 | thread->state = STATE_KILLED; | 576 | thread->state = STATE_KILLED; |
544 | thread_queue_wake(&thread->queue); | 577 | thread_queue_wake(&thread->queue); |
545 | 578 | ||
@@ -559,17 +592,16 @@ void remove_thread(struct thread_entry *thread) | |||
559 | 592 | ||
560 | void thread_exit(void) | 593 | void thread_exit(void) |
561 | { | 594 | { |
562 | remove_thread(NULL); | 595 | remove_thread(THREAD_ID_CURRENT); |
563 | } | 596 | } |
564 | 597 | ||
565 | void thread_wait(struct thread_entry *thread) | 598 | void thread_wait(unsigned int thread_id) |
566 | { | 599 | { |
567 | struct thread_entry *current = cores[CURRENT_CORE].running; | 600 | struct thread_entry *current = cores[CURRENT_CORE].running; |
601 | struct thread_entry *thread = thread_id_entry(thread_id); | ||
568 | 602 | ||
569 | if (thread == NULL) | 603 | if (thread_id == THREAD_ID_CURRENT || |
570 | thread = current; | 604 | (thread->id == thread_id && thread->state != STATE_KILLED)) |
571 | |||
572 | if (thread->state != STATE_KILLED) | ||
573 | { | 605 | { |
574 | current->bqp = &thread->queue; | 606 | current->bqp = &thread->queue; |
575 | block_thread(current); | 607 | block_thread(current); |
@@ -583,11 +615,6 @@ int thread_stack_usage(const struct thread_entry *thread) | |||
583 | (void)thread; | 615 | (void)thread; |
584 | } | 616 | } |
585 | 617 | ||
586 | unsigned thread_get_status(const struct thread_entry *thread) | ||
587 | { | ||
588 | return thread->state; | ||
589 | } | ||
590 | |||
591 | /* Return name if one or ID if none */ | 618 | /* Return name if one or ID if none */ |
592 | void thread_get_name(char *buffer, int size, | 619 | void thread_get_name(char *buffer, int size, |
593 | struct thread_entry *thread) | 620 | struct thread_entry *thread) |