diff options
Diffstat (limited to 'uisimulator/sdl/thread-sdl.c')
-rw-r--r-- | uisimulator/sdl/thread-sdl.c | 649 |
1 files changed, 0 insertions, 649 deletions
diff --git a/uisimulator/sdl/thread-sdl.c b/uisimulator/sdl/thread-sdl.c deleted file mode 100644 index e9b5fc205d..0000000000 --- a/uisimulator/sdl/thread-sdl.c +++ /dev/null | |||
@@ -1,649 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2006 Dan Everton | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include <stdbool.h> | ||
23 | #include <time.h> | ||
24 | #include <SDL.h> | ||
25 | #include <SDL_thread.h> | ||
26 | #include <stdlib.h> | ||
27 | #include <memory.h> | ||
28 | #include <setjmp.h> | ||
29 | #include "system-sdl.h" | ||
30 | #include "thread-sdl.h" | ||
31 | #include "system.h" | ||
32 | #include "kernel.h" | ||
33 | #include "thread.h" | ||
34 | #include "debug.h" | ||
35 | |||
36 | /* Define this as 1 to show informational messages that are not errors. */ | ||
37 | #define THREAD_SDL_DEBUGF_ENABLED 0 | ||
38 | |||
39 | #if THREAD_SDL_DEBUGF_ENABLED | ||
40 | #define THREAD_SDL_DEBUGF(...) DEBUGF(__VA_ARGS__) | ||
41 | static char __name[32]; | ||
42 | #define THREAD_SDL_GET_NAME(thread) \ | ||
43 | ({ thread_get_name(__name, ARRAYLEN(__name), thread); __name; }) | ||
44 | #else | ||
45 | #define THREAD_SDL_DEBUGF(...) | ||
46 | #define THREAD_SDL_GET_NAME(thread) | ||
47 | #endif | ||
48 | |||
49 | #define THREAD_PANICF(str...) \ | ||
50 | ({ fprintf(stderr, str); exit(-1); }) | ||
51 | |||
52 | /* Thread/core entries as in rockbox core */ | ||
53 | static struct core_entry cores[NUM_CORES]; | ||
54 | struct thread_entry threads[MAXTHREADS]; | ||
55 | /* Jump buffers for graceful exit - kernel threads don't stay neatly | ||
56 | * in their start routines responding to messages so this is the only | ||
57 | * way to get them back in there so they may exit */ | ||
58 | static jmp_buf thread_jmpbufs[MAXTHREADS]; | ||
59 | static SDL_mutex *m; | ||
60 | static volatile bool threads_exit = false; | ||
61 | |||
62 | extern long start_tick; | ||
63 | |||
64 | void thread_sdl_shutdown(void) | ||
65 | { | ||
66 | int i; | ||
67 | |||
68 | /* Tell all threads jump back to their start routines, unlock and exit | ||
69 | gracefully - we'll check each one in turn for it's status. Threads | ||
70 | _could_ terminate via remove_thread or multiple threads could exit | ||
71 | on each unlock but that is safe. */ | ||
72 | |||
73 | /* Do this before trying to acquire lock */ | ||
74 | threads_exit = true; | ||
75 | |||
76 | /* Take control */ | ||
77 | SDL_LockMutex(m); | ||
78 | |||
79 | for (i = 0; i < MAXTHREADS; i++) | ||
80 | { | ||
81 | struct thread_entry *thread = &threads[i]; | ||
82 | if (thread->context.t != NULL) | ||
83 | { | ||
84 | /* Signal thread on delay or block */ | ||
85 | SDL_Thread *t = thread->context.t; | ||
86 | SDL_SemPost(thread->context.s); | ||
87 | SDL_UnlockMutex(m); | ||
88 | /* Wait for it to finish */ | ||
89 | SDL_WaitThread(t, NULL); | ||
90 | /* Relock for next thread signal */ | ||
91 | SDL_LockMutex(m); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | SDL_UnlockMutex(m); | ||
96 | SDL_DestroyMutex(m); | ||
97 | } | ||
98 | |||
99 | static void new_thread_id(unsigned int slot_num, | ||
100 | struct thread_entry *thread) | ||
101 | { | ||
102 | unsigned int version = | ||
103 | (thread->id + (1u << THREAD_ID_VERSION_SHIFT)) | ||
104 | & THREAD_ID_VERSION_MASK; | ||
105 | |||
106 | if (version == 0) | ||
107 | version = 1u << THREAD_ID_VERSION_SHIFT; | ||
108 | |||
109 | thread->id = version | (slot_num & THREAD_ID_SLOT_MASK); | ||
110 | } | ||
111 | |||
112 | static struct thread_entry * find_empty_thread_slot(void) | ||
113 | { | ||
114 | struct thread_entry *thread = NULL; | ||
115 | int n; | ||
116 | |||
117 | for (n = 0; n < MAXTHREADS; n++) | ||
118 | { | ||
119 | int state = threads[n].state; | ||
120 | |||
121 | if (state == STATE_KILLED) | ||
122 | { | ||
123 | thread = &threads[n]; | ||
124 | break; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | return thread; | ||
129 | } | ||
130 | |||
131 | /* Do main thread creation in this file scope to avoid the need to double- | ||
132 | return to a prior call-level which would be unaware of the fact setjmp | ||
133 | was used */ | ||
134 | extern void app_main(void *param); | ||
135 | static int thread_sdl_app_main(void *param) | ||
136 | { | ||
137 | SDL_LockMutex(m); | ||
138 | cores[CURRENT_CORE].running = &threads[0]; | ||
139 | |||
140 | /* Set the jump address for return */ | ||
141 | if (setjmp(thread_jmpbufs[0]) == 0) | ||
142 | { | ||
143 | app_main(param); | ||
144 | /* should not ever be reached but... */ | ||
145 | THREAD_PANICF("app_main returned!\n"); | ||
146 | } | ||
147 | |||
148 | /* Unlock and exit */ | ||
149 | SDL_UnlockMutex(m); | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | /* Initialize SDL threading */ | ||
154 | bool thread_sdl_init(void *param) | ||
155 | { | ||
156 | struct thread_entry *thread; | ||
157 | int n; | ||
158 | |||
159 | memset(cores, 0, sizeof(cores)); | ||
160 | memset(threads, 0, sizeof(threads)); | ||
161 | |||
162 | m = SDL_CreateMutex(); | ||
163 | |||
164 | if (SDL_LockMutex(m) == -1) | ||
165 | { | ||
166 | fprintf(stderr, "Couldn't lock mutex\n"); | ||
167 | return false; | ||
168 | } | ||
169 | |||
170 | /* Initialize all IDs */ | ||
171 | for (n = 0; n < MAXTHREADS; n++) | ||
172 | threads[n].id = THREAD_ID_INIT(n); | ||
173 | |||
174 | /* Slot 0 is reserved for the main thread - initialize it here and | ||
175 | then create the SDL thread - it is possible to have a quick, early | ||
176 | shutdown try to access the structure. */ | ||
177 | thread = &threads[0]; | ||
178 | thread->stack = (uintptr_t *)" "; | ||
179 | thread->stack_size = 8; | ||
180 | thread->name = "main"; | ||
181 | thread->state = STATE_RUNNING; | ||
182 | thread->context.s = SDL_CreateSemaphore(0); | ||
183 | cores[CURRENT_CORE].running = thread; | ||
184 | |||
185 | if (thread->context.s == NULL) | ||
186 | { | ||
187 | fprintf(stderr, "Failed to create main semaphore\n"); | ||
188 | return false; | ||
189 | } | ||
190 | |||
191 | thread->context.t = SDL_CreateThread(thread_sdl_app_main, param); | ||
192 | |||
193 | if (thread->context.t == NULL) | ||
194 | { | ||
195 | SDL_DestroySemaphore(thread->context.s); | ||
196 | fprintf(stderr, "Failed to create main thread\n"); | ||
197 | return false; | ||
198 | } | ||
199 | |||
200 | THREAD_SDL_DEBUGF("Main thread: %p\n", thread); | ||
201 | |||
202 | SDL_UnlockMutex(m); | ||
203 | return true; | ||
204 | } | ||
205 | |||
206 | void thread_sdl_exception_wait(void) | ||
207 | { | ||
208 | while (1) | ||
209 | { | ||
210 | SDL_Delay(HZ/10); | ||
211 | if (threads_exit) | ||
212 | thread_exit(); | ||
213 | } | ||
214 | } | ||
215 | |||
216 | /* A way to yield and leave the threading system for extended periods */ | ||
217 | void thread_sdl_thread_lock(void *me) | ||
218 | { | ||
219 | SDL_LockMutex(m); | ||
220 | cores[CURRENT_CORE].running = (struct thread_entry *)me; | ||
221 | |||
222 | if (threads_exit) | ||
223 | thread_exit(); | ||
224 | } | ||
225 | |||
226 | void * thread_sdl_thread_unlock(void) | ||
227 | { | ||
228 | struct thread_entry *current = cores[CURRENT_CORE].running; | ||
229 | SDL_UnlockMutex(m); | ||
230 | return current; | ||
231 | } | ||
232 | |||
233 | struct thread_entry * thread_id_entry(unsigned int thread_id) | ||
234 | { | ||
235 | return (thread_id == THREAD_ID_CURRENT) ? | ||
236 | cores[CURRENT_CORE].running : | ||
237 | &threads[thread_id & THREAD_ID_SLOT_MASK]; | ||
238 | } | ||
239 | |||
240 | static void add_to_list_l(struct thread_entry **list, | ||
241 | struct thread_entry *thread) | ||
242 | { | ||
243 | if (*list == NULL) | ||
244 | { | ||
245 | /* Insert into unoccupied list */ | ||
246 | thread->l.next = thread; | ||
247 | thread->l.prev = thread; | ||
248 | *list = thread; | ||
249 | } | ||
250 | else | ||
251 | { | ||
252 | /* Insert last */ | ||
253 | thread->l.next = *list; | ||
254 | thread->l.prev = (*list)->l.prev; | ||
255 | thread->l.prev->l.next = thread; | ||
256 | (*list)->l.prev = thread; | ||
257 | } | ||
258 | } | ||
259 | |||
260 | static void remove_from_list_l(struct thread_entry **list, | ||
261 | struct thread_entry *thread) | ||
262 | { | ||
263 | if (thread == thread->l.next) | ||
264 | { | ||
265 | /* The only item */ | ||
266 | *list = NULL; | ||
267 | return; | ||
268 | } | ||
269 | |||
270 | if (thread == *list) | ||
271 | { | ||
272 | /* List becomes next item */ | ||
273 | *list = thread->l.next; | ||
274 | } | ||
275 | |||
276 | /* Fix links to jump over the removed entry. */ | ||
277 | thread->l.prev->l.next = thread->l.next; | ||
278 | thread->l.next->l.prev = thread->l.prev; | ||
279 | } | ||
280 | |||
281 | unsigned int thread_get_current(void) | ||
282 | { | ||
283 | return cores[CURRENT_CORE].running->id; | ||
284 | } | ||
285 | |||
286 | void switch_thread(void) | ||
287 | { | ||
288 | struct thread_entry *current = cores[CURRENT_CORE].running; | ||
289 | |||
290 | enable_irq(); | ||
291 | |||
292 | switch (current->state) | ||
293 | { | ||
294 | case STATE_RUNNING: | ||
295 | { | ||
296 | SDL_UnlockMutex(m); | ||
297 | /* Any other thread waiting already will get it first */ | ||
298 | SDL_LockMutex(m); | ||
299 | break; | ||
300 | } /* STATE_RUNNING: */ | ||
301 | |||
302 | case STATE_BLOCKED: | ||
303 | { | ||
304 | int oldlevel; | ||
305 | |||
306 | SDL_UnlockMutex(m); | ||
307 | SDL_SemWait(current->context.s); | ||
308 | SDL_LockMutex(m); | ||
309 | |||
310 | oldlevel = disable_irq_save(); | ||
311 | current->state = STATE_RUNNING; | ||
312 | restore_irq(oldlevel); | ||
313 | break; | ||
314 | } /* STATE_BLOCKED: */ | ||
315 | |||
316 | case STATE_BLOCKED_W_TMO: | ||
317 | { | ||
318 | int result, oldlevel; | ||
319 | |||
320 | SDL_UnlockMutex(m); | ||
321 | result = SDL_SemWaitTimeout(current->context.s, current->tmo_tick); | ||
322 | SDL_LockMutex(m); | ||
323 | |||
324 | oldlevel = disable_irq_save(); | ||
325 | |||
326 | if (current->state == STATE_BLOCKED_W_TMO) | ||
327 | { | ||
328 | /* Timed out */ | ||
329 | remove_from_list_l(current->bqp, current); | ||
330 | |||
331 | #ifdef HAVE_WAKEUP_EXT_CB | ||
332 | if (current->wakeup_ext_cb != NULL) | ||
333 | current->wakeup_ext_cb(current); | ||
334 | #endif | ||
335 | current->state = STATE_RUNNING; | ||
336 | } | ||
337 | |||
338 | if (result == SDL_MUTEX_TIMEDOUT) | ||
339 | { | ||
340 | /* Other signals from an explicit wake could have been made before | ||
341 | * arriving here if we timed out waiting for the semaphore. Make | ||
342 | * sure the count is reset. */ | ||
343 | while (SDL_SemValue(current->context.s) > 0) | ||
344 | SDL_SemTryWait(current->context.s); | ||
345 | } | ||
346 | |||
347 | restore_irq(oldlevel); | ||
348 | break; | ||
349 | } /* STATE_BLOCKED_W_TMO: */ | ||
350 | |||
351 | case STATE_SLEEPING: | ||
352 | { | ||
353 | SDL_UnlockMutex(m); | ||
354 | SDL_SemWaitTimeout(current->context.s, current->tmo_tick); | ||
355 | SDL_LockMutex(m); | ||
356 | current->state = STATE_RUNNING; | ||
357 | break; | ||
358 | } /* STATE_SLEEPING: */ | ||
359 | } | ||
360 | |||
361 | cores[CURRENT_CORE].running = current; | ||
362 | |||
363 | if (threads_exit) | ||
364 | thread_exit(); | ||
365 | } | ||
366 | |||
367 | void sleep_thread(int ticks) | ||
368 | { | ||
369 | struct thread_entry *current = cores[CURRENT_CORE].running; | ||
370 | int rem; | ||
371 | |||
372 | current->state = STATE_SLEEPING; | ||
373 | |||
374 | rem = (SDL_GetTicks() - start_tick) % (1000/HZ); | ||
375 | if (rem < 0) | ||
376 | rem = 0; | ||
377 | |||
378 | current->tmo_tick = (1000/HZ) * ticks + ((1000/HZ)-1) - rem; | ||
379 | } | ||
380 | |||
381 | void block_thread(struct thread_entry *current) | ||
382 | { | ||
383 | current->state = STATE_BLOCKED; | ||
384 | add_to_list_l(current->bqp, current); | ||
385 | } | ||
386 | |||
387 | void block_thread_w_tmo(struct thread_entry *current, int ticks) | ||
388 | { | ||
389 | current->state = STATE_BLOCKED_W_TMO; | ||
390 | current->tmo_tick = (1000/HZ)*ticks; | ||
391 | add_to_list_l(current->bqp, current); | ||
392 | } | ||
393 | |||
394 | unsigned int wakeup_thread(struct thread_entry **list) | ||
395 | { | ||
396 | struct thread_entry *thread = *list; | ||
397 | |||
398 | if (thread != NULL) | ||
399 | { | ||
400 | switch (thread->state) | ||
401 | { | ||
402 | case STATE_BLOCKED: | ||
403 | case STATE_BLOCKED_W_TMO: | ||
404 | remove_from_list_l(list, thread); | ||
405 | thread->state = STATE_RUNNING; | ||
406 | SDL_SemPost(thread->context.s); | ||
407 | return THREAD_OK; | ||
408 | } | ||
409 | } | ||
410 | |||
411 | return THREAD_NONE; | ||
412 | } | ||
413 | |||
414 | unsigned int thread_queue_wake(struct thread_entry **list) | ||
415 | { | ||
416 | unsigned int result = THREAD_NONE; | ||
417 | |||
418 | for (;;) | ||
419 | { | ||
420 | unsigned int rc = wakeup_thread(list); | ||
421 | |||
422 | if (rc == THREAD_NONE) | ||
423 | break; | ||
424 | |||
425 | result |= rc; | ||
426 | } | ||
427 | |||
428 | return result; | ||
429 | } | ||
430 | |||
431 | void thread_thaw(unsigned int thread_id) | ||
432 | { | ||
433 | struct thread_entry *thread = thread_id_entry(thread_id); | ||
434 | |||
435 | if (thread->id == thread_id && thread->state == STATE_FROZEN) | ||
436 | { | ||
437 | thread->state = STATE_RUNNING; | ||
438 | SDL_SemPost(thread->context.s); | ||
439 | } | ||
440 | } | ||
441 | |||
442 | int runthread(void *data) | ||
443 | { | ||
444 | struct thread_entry *current; | ||
445 | jmp_buf *current_jmpbuf; | ||
446 | |||
447 | /* Cannot access thread variables before locking the mutex as the | ||
448 | data structures may not be filled-in yet. */ | ||
449 | SDL_LockMutex(m); | ||
450 | cores[CURRENT_CORE].running = (struct thread_entry *)data; | ||
451 | current = cores[CURRENT_CORE].running; | ||
452 | current_jmpbuf = &thread_jmpbufs[current - threads]; | ||
453 | |||
454 | /* Setup jump for exit */ | ||
455 | if (setjmp(*current_jmpbuf) == 0) | ||
456 | { | ||
457 | /* Run the thread routine */ | ||
458 | if (current->state == STATE_FROZEN) | ||
459 | { | ||
460 | SDL_UnlockMutex(m); | ||
461 | SDL_SemWait(current->context.s); | ||
462 | SDL_LockMutex(m); | ||
463 | cores[CURRENT_CORE].running = current; | ||
464 | } | ||
465 | |||
466 | if (!threads_exit) | ||
467 | { | ||
468 | current->context.start(); | ||
469 | THREAD_SDL_DEBUGF("Thread Done: %d (%s)\n", | ||
470 | current - threads, THREAD_SDL_GET_NAME(current)); | ||
471 | /* Thread routine returned - suicide */ | ||
472 | } | ||
473 | |||
474 | thread_exit(); | ||
475 | } | ||
476 | else | ||
477 | { | ||
478 | /* Unlock and exit */ | ||
479 | SDL_UnlockMutex(m); | ||
480 | } | ||
481 | |||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | unsigned int create_thread(void (*function)(void), | ||
486 | void* stack, size_t stack_size, | ||
487 | unsigned flags, const char *name) | ||
488 | { | ||
489 | struct thread_entry *thread; | ||
490 | SDL_Thread* t; | ||
491 | SDL_sem *s; | ||
492 | |||
493 | THREAD_SDL_DEBUGF("Creating thread: (%s)\n", name ? name : ""); | ||
494 | |||
495 | thread = find_empty_thread_slot(); | ||
496 | if (thread == NULL) | ||
497 | { | ||
498 | DEBUGF("Failed to find thread slot\n"); | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | s = SDL_CreateSemaphore(0); | ||
503 | if (s == NULL) | ||
504 | { | ||
505 | DEBUGF("Failed to create semaphore\n"); | ||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | t = SDL_CreateThread(runthread, thread); | ||
510 | if (t == NULL) | ||
511 | { | ||
512 | DEBUGF("Failed to create SDL thread\n"); | ||
513 | SDL_DestroySemaphore(s); | ||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | thread->stack = stack; | ||
518 | thread->stack_size = stack_size; | ||
519 | thread->name = name; | ||
520 | thread->state = (flags & CREATE_THREAD_FROZEN) ? | ||
521 | STATE_FROZEN : STATE_RUNNING; | ||
522 | thread->context.start = function; | ||
523 | thread->context.t = t; | ||
524 | thread->context.s = s; | ||
525 | |||
526 | THREAD_SDL_DEBUGF("New Thread: %d (%s)\n", | ||
527 | thread - threads, THREAD_SDL_GET_NAME(thread)); | ||
528 | |||
529 | return thread->id; | ||
530 | } | ||
531 | |||
532 | void init_threads(void) | ||
533 | { | ||
534 | /* Main thread is already initialized */ | ||
535 | if (cores[CURRENT_CORE].running != &threads[0]) | ||
536 | { | ||
537 | THREAD_PANICF("Wrong main thread in init_threads: %p\n", | ||
538 | cores[CURRENT_CORE].running); | ||
539 | } | ||
540 | |||
541 | THREAD_SDL_DEBUGF("First Thread: %d (%s)\n", | ||
542 | 0, THREAD_SDL_GET_NAME(&threads[0])); | ||
543 | } | ||
544 | |||
545 | #ifndef ALLOW_REMOVE_THREAD | ||
546 | static void remove_thread(unsigned int thread_id) | ||
547 | #else | ||
548 | void remove_thread(unsigned int thread_id) | ||
549 | #endif | ||
550 | { | ||
551 | struct thread_entry *current = cores[CURRENT_CORE].running; | ||
552 | struct thread_entry *thread = thread_id_entry(thread_id); | ||
553 | |||
554 | SDL_Thread *t; | ||
555 | SDL_sem *s; | ||
556 | |||
557 | if (thread_id != THREAD_ID_CURRENT && thread->id != thread_id) | ||
558 | return; | ||
559 | |||
560 | int oldlevel = disable_irq_save(); | ||
561 | |||
562 | t = thread->context.t; | ||
563 | s = thread->context.s; | ||
564 | thread->context.t = NULL; | ||
565 | |||
566 | if (thread != current) | ||
567 | { | ||
568 | switch (thread->state) | ||
569 | { | ||
570 | case STATE_BLOCKED: | ||
571 | case STATE_BLOCKED_W_TMO: | ||
572 | /* Remove thread from object it's waiting on */ | ||
573 | remove_from_list_l(thread->bqp, thread); | ||
574 | |||
575 | #ifdef HAVE_WAKEUP_EXT_CB | ||
576 | if (thread->wakeup_ext_cb != NULL) | ||
577 | thread->wakeup_ext_cb(thread); | ||
578 | #endif | ||
579 | break; | ||
580 | } | ||
581 | |||
582 | SDL_SemPost(s); | ||
583 | } | ||
584 | |||
585 | THREAD_SDL_DEBUGF("Removing thread: %d (%s)\n", | ||
586 | thread - threads, THREAD_SDL_GET_NAME(thread)); | ||
587 | |||
588 | new_thread_id(thread->id, thread); | ||
589 | thread->state = STATE_KILLED; | ||
590 | thread_queue_wake(&thread->queue); | ||
591 | |||
592 | SDL_DestroySemaphore(s); | ||
593 | |||
594 | if (thread == current) | ||
595 | { | ||
596 | /* Do a graceful exit - perform the longjmp back into the thread | ||
597 | function to return */ | ||
598 | restore_irq(oldlevel); | ||
599 | longjmp(thread_jmpbufs[current - threads], 1); | ||
600 | } | ||
601 | |||
602 | SDL_KillThread(t); | ||
603 | restore_irq(oldlevel); | ||
604 | } | ||
605 | |||
606 | void thread_exit(void) | ||
607 | { | ||
608 | remove_thread(THREAD_ID_CURRENT); | ||
609 | } | ||
610 | |||
611 | void thread_wait(unsigned int thread_id) | ||
612 | { | ||
613 | struct thread_entry *current = cores[CURRENT_CORE].running; | ||
614 | struct thread_entry *thread = thread_id_entry(thread_id); | ||
615 | |||
616 | if (thread_id == THREAD_ID_CURRENT || | ||
617 | (thread->id == thread_id && thread->state != STATE_KILLED)) | ||
618 | { | ||
619 | current->bqp = &thread->queue; | ||
620 | block_thread(current); | ||
621 | switch_thread(); | ||
622 | } | ||
623 | } | ||
624 | |||
625 | int thread_stack_usage(const struct thread_entry *thread) | ||
626 | { | ||
627 | return 50; | ||
628 | (void)thread; | ||
629 | } | ||
630 | |||
631 | /* Return name if one or ID if none */ | ||
632 | void thread_get_name(char *buffer, int size, | ||
633 | struct thread_entry *thread) | ||
634 | { | ||
635 | if (size <= 0) | ||
636 | return; | ||
637 | |||
638 | *buffer = '\0'; | ||
639 | |||
640 | if (thread) | ||
641 | { | ||
642 | /* Display thread name if one or ID if none */ | ||
643 | bool named = thread->name && *thread->name; | ||
644 | const char *fmt = named ? "%s" : "%08lX"; | ||
645 | intptr_t name = named ? | ||
646 | (intptr_t)thread->name : (intptr_t)thread; | ||
647 | snprintf(buffer, size, fmt, name); | ||
648 | } | ||
649 | } | ||