diff options
Diffstat (limited to 'uisimulator/sdl/thread-sdl.c')
-rw-r--r-- | uisimulator/sdl/thread-sdl.c | 160 |
1 files changed, 105 insertions, 55 deletions
diff --git a/uisimulator/sdl/thread-sdl.c b/uisimulator/sdl/thread-sdl.c index 0bd7d2534e..6a3c4af9eb 100644 --- a/uisimulator/sdl/thread-sdl.c +++ b/uisimulator/sdl/thread-sdl.c | |||
@@ -131,7 +131,7 @@ bool thread_sdl_init(void *param) | |||
131 | running->stack = " "; | 131 | running->stack = " "; |
132 | running->stack_size = 8; | 132 | running->stack_size = 8; |
133 | running->name = "main"; | 133 | running->name = "main"; |
134 | running->statearg = STATE_RUNNING; | 134 | running->state = STATE_RUNNING; |
135 | running->context.c = SDL_CreateCond(); | 135 | running->context.c = SDL_CreateCond(); |
136 | 136 | ||
137 | if (running->context.c == NULL) | 137 | if (running->context.c == NULL) |
@@ -154,43 +154,55 @@ bool thread_sdl_init(void *param) | |||
154 | return true; | 154 | return true; |
155 | } | 155 | } |
156 | 156 | ||
157 | void thread_sdl_lock(void) | ||
158 | { | ||
159 | SDL_LockMutex(m); | ||
160 | } | ||
161 | |||
162 | void thread_sdl_unlock(void) | ||
163 | { | ||
164 | SDL_UnlockMutex(m); | ||
165 | } | ||
166 | |||
157 | static int find_empty_thread_slot(void) | 167 | static int find_empty_thread_slot(void) |
158 | { | 168 | { |
159 | int n; | 169 | int n; |
160 | 170 | ||
161 | for (n = 0; n < MAXTHREADS; n++) | 171 | for (n = 0; n < MAXTHREADS; n++) |
162 | { | 172 | { |
163 | if (threads[n].name == NULL) | 173 | int state = threads[n].state; |
174 | |||
175 | if (state == STATE_KILLED) | ||
164 | break; | 176 | break; |
165 | } | 177 | } |
166 | 178 | ||
167 | return n; | 179 | return n; |
168 | } | 180 | } |
169 | 181 | ||
170 | static void add_to_list(struct thread_entry **list, | 182 | static void add_to_list_l(struct thread_entry **list, |
171 | struct thread_entry *thread) | 183 | struct thread_entry *thread) |
172 | { | 184 | { |
173 | if (*list == NULL) | 185 | if (*list == NULL) |
174 | { | 186 | { |
175 | /* Insert into unoccupied list */ | 187 | /* Insert into unoccupied list */ |
176 | thread->next = thread; | 188 | thread->l.next = thread; |
177 | thread->prev = thread; | 189 | thread->l.prev = thread; |
178 | *list = thread; | 190 | *list = thread; |
179 | } | 191 | } |
180 | else | 192 | else |
181 | { | 193 | { |
182 | /* Insert last */ | 194 | /* Insert last */ |
183 | thread->next = *list; | 195 | thread->l.next = *list; |
184 | thread->prev = (*list)->prev; | 196 | thread->l.prev = (*list)->l.prev; |
185 | thread->prev->next = thread; | 197 | thread->l.prev->l.next = thread; |
186 | (*list)->prev = thread; | 198 | (*list)->l.prev = thread; |
187 | } | 199 | } |
188 | } | 200 | } |
189 | 201 | ||
190 | static void remove_from_list(struct thread_entry **list, | 202 | static void remove_from_list_l(struct thread_entry **list, |
191 | struct thread_entry *thread) | 203 | struct thread_entry *thread) |
192 | { | 204 | { |
193 | if (thread == thread->next) | 205 | if (thread == thread->l.next) |
194 | { | 206 | { |
195 | /* The only item */ | 207 | /* The only item */ |
196 | *list = NULL; | 208 | *list = NULL; |
@@ -200,12 +212,12 @@ static void remove_from_list(struct thread_entry **list, | |||
200 | if (thread == *list) | 212 | if (thread == *list) |
201 | { | 213 | { |
202 | /* List becomes next item */ | 214 | /* List becomes next item */ |
203 | *list = thread->next; | 215 | *list = thread->l.next; |
204 | } | 216 | } |
205 | 217 | ||
206 | /* Fix links to jump over the removed entry. */ | 218 | /* Fix links to jump over the removed entry. */ |
207 | thread->prev->next = thread->next; | 219 | thread->l.prev->l.next = thread->l.next; |
208 | thread->next->prev = thread->prev; | 220 | thread->l.next->l.prev = thread->l.prev; |
209 | } | 221 | } |
210 | 222 | ||
211 | struct thread_entry *thread_get_current(void) | 223 | struct thread_entry *thread_get_current(void) |
@@ -213,17 +225,7 @@ struct thread_entry *thread_get_current(void) | |||
213 | return running; | 225 | return running; |
214 | } | 226 | } |
215 | 227 | ||
216 | void thread_sdl_lock(void) | 228 | void switch_thread(struct thread_entry *old) |
217 | { | ||
218 | SDL_LockMutex(m); | ||
219 | } | ||
220 | |||
221 | void thread_sdl_unlock(void) | ||
222 | { | ||
223 | SDL_UnlockMutex(m); | ||
224 | } | ||
225 | |||
226 | void switch_thread(bool save_context, struct thread_entry **blocked_list) | ||
227 | { | 229 | { |
228 | struct thread_entry *current = running; | 230 | struct thread_entry *current = running; |
229 | 231 | ||
@@ -235,7 +237,7 @@ void switch_thread(bool save_context, struct thread_entry **blocked_list) | |||
235 | if (threads_exit) | 237 | if (threads_exit) |
236 | remove_thread(NULL); | 238 | remove_thread(NULL); |
237 | 239 | ||
238 | (void)save_context; (void)blocked_list; | 240 | (void)old; |
239 | } | 241 | } |
240 | 242 | ||
241 | void sleep_thread(int ticks) | 243 | void sleep_thread(int ticks) |
@@ -244,7 +246,7 @@ void sleep_thread(int ticks) | |||
244 | int rem; | 246 | int rem; |
245 | 247 | ||
246 | current = running; | 248 | current = running; |
247 | current->statearg = STATE_SLEEPING; | 249 | current->state = STATE_SLEEPING; |
248 | 250 | ||
249 | rem = (SDL_GetTicks() - start_tick) % (1000/HZ); | 251 | rem = (SDL_GetTicks() - start_tick) % (1000/HZ); |
250 | if (rem < 0) | 252 | if (rem < 0) |
@@ -267,7 +269,7 @@ void sleep_thread(int ticks) | |||
267 | 269 | ||
268 | running = current; | 270 | running = current; |
269 | 271 | ||
270 | current->statearg = STATE_RUNNING; | 272 | current->state = STATE_RUNNING; |
271 | 273 | ||
272 | if (threads_exit) | 274 | if (threads_exit) |
273 | remove_thread(NULL); | 275 | remove_thread(NULL); |
@@ -289,10 +291,21 @@ int runthread(void *data) | |||
289 | if (setjmp(*current_jmpbuf) == 0) | 291 | if (setjmp(*current_jmpbuf) == 0) |
290 | { | 292 | { |
291 | /* Run the thread routine */ | 293 | /* Run the thread routine */ |
292 | current->context.start(); | 294 | if (current->state == STATE_FROZEN) |
293 | THREAD_SDL_DEBUGF("Thread Done: %d (%s)\n", | 295 | { |
294 | current - threads, THREAD_SDL_GET_NAME(current)); | 296 | SDL_CondWait(current->context.c, m); |
295 | /* Thread routine returned - suicide */ | 297 | running = current; |
298 | |||
299 | } | ||
300 | |||
301 | if (!threads_exit) | ||
302 | { | ||
303 | current->context.start(); | ||
304 | THREAD_SDL_DEBUGF("Thread Done: %d (%s)\n", | ||
305 | current - threads, THREAD_SDL_GET_NAME(current)); | ||
306 | /* Thread routine returned - suicide */ | ||
307 | } | ||
308 | |||
296 | remove_thread(NULL); | 309 | remove_thread(NULL); |
297 | } | 310 | } |
298 | else | 311 | else |
@@ -306,7 +319,7 @@ int runthread(void *data) | |||
306 | 319 | ||
307 | struct thread_entry* | 320 | struct thread_entry* |
308 | create_thread(void (*function)(void), void* stack, int stack_size, | 321 | create_thread(void (*function)(void), void* stack, int stack_size, |
309 | const char *name) | 322 | unsigned flags, const char *name) |
310 | { | 323 | { |
311 | /** Avoid compiler warnings */ | 324 | /** Avoid compiler warnings */ |
312 | SDL_Thread* t; | 325 | SDL_Thread* t; |
@@ -340,7 +353,8 @@ struct thread_entry* | |||
340 | threads[slot].stack = stack; | 353 | threads[slot].stack = stack; |
341 | threads[slot].stack_size = stack_size; | 354 | threads[slot].stack_size = stack_size; |
342 | threads[slot].name = name; | 355 | threads[slot].name = name; |
343 | threads[slot].statearg = STATE_RUNNING; | 356 | threads[slot].state = (flags & CREATE_THREAD_FROZEN) ? |
357 | STATE_FROZEN : STATE_RUNNING; | ||
344 | threads[slot].context.start = function; | 358 | threads[slot].context.start = function; |
345 | threads[slot].context.t = t; | 359 | threads[slot].context.t = t; |
346 | threads[slot].context.c = cond; | 360 | threads[slot].context.c = cond; |
@@ -351,12 +365,13 @@ struct thread_entry* | |||
351 | return &threads[slot]; | 365 | return &threads[slot]; |
352 | } | 366 | } |
353 | 367 | ||
354 | void block_thread(struct thread_entry **list) | 368 | void _block_thread(struct thread_queue *tq) |
355 | { | 369 | { |
356 | struct thread_entry *thread = running; | 370 | struct thread_entry *thread = running; |
357 | 371 | ||
358 | thread->statearg = STATE_BLOCKED; | 372 | thread->state = STATE_BLOCKED; |
359 | add_to_list(list, thread); | 373 | thread->bqp = tq; |
374 | add_to_list_l(&tq->queue, thread); | ||
360 | 375 | ||
361 | SDL_CondWait(thread->context.c, m); | 376 | SDL_CondWait(thread->context.c, m); |
362 | running = thread; | 377 | running = thread; |
@@ -365,44 +380,56 @@ void block_thread(struct thread_entry **list) | |||
365 | remove_thread(NULL); | 380 | remove_thread(NULL); |
366 | } | 381 | } |
367 | 382 | ||
368 | void block_thread_w_tmo(struct thread_entry **list, int ticks) | 383 | void block_thread_w_tmo(struct thread_queue *tq, int ticks) |
369 | { | 384 | { |
370 | struct thread_entry *thread = running; | 385 | struct thread_entry *thread = running; |
371 | 386 | ||
372 | thread->statearg = STATE_BLOCKED_W_TMO; | 387 | thread->state = STATE_BLOCKED_W_TMO; |
373 | add_to_list(list, thread); | 388 | thread->bqp = tq; |
389 | add_to_list_l(&tq->queue, thread); | ||
374 | 390 | ||
375 | SDL_CondWaitTimeout(thread->context.c, m, (1000/HZ) * ticks); | 391 | SDL_CondWaitTimeout(thread->context.c, m, (1000/HZ) * ticks); |
376 | running = thread; | 392 | running = thread; |
377 | 393 | ||
378 | if (thread->statearg == STATE_BLOCKED_W_TMO) | 394 | if (thread->state == STATE_BLOCKED_W_TMO) |
379 | { | 395 | { |
380 | /* Timed out */ | 396 | /* Timed out */ |
381 | remove_from_list(list, thread); | 397 | remove_from_list_l(&tq->queue, thread); |
382 | thread->statearg = STATE_RUNNING; | 398 | thread->state = STATE_RUNNING; |
383 | } | 399 | } |
384 | 400 | ||
385 | if (threads_exit) | 401 | if (threads_exit) |
386 | remove_thread(NULL); | 402 | remove_thread(NULL); |
387 | } | 403 | } |
388 | 404 | ||
389 | void wakeup_thread(struct thread_entry **list) | 405 | struct thread_entry * _wakeup_thread(struct thread_queue *tq) |
390 | { | 406 | { |
391 | struct thread_entry *thread = *list; | 407 | struct thread_entry *thread = tq->queue; |
392 | 408 | ||
393 | if (thread == NULL) | 409 | if (thread == NULL) |
394 | { | 410 | { |
395 | return; | 411 | return NULL; |
396 | } | 412 | } |
397 | 413 | ||
398 | switch (thread->statearg) | 414 | switch (thread->state) |
399 | { | 415 | { |
400 | case STATE_BLOCKED: | 416 | case STATE_BLOCKED: |
401 | case STATE_BLOCKED_W_TMO: | 417 | case STATE_BLOCKED_W_TMO: |
402 | remove_from_list(list, thread); | 418 | remove_from_list_l(&tq->queue, thread); |
403 | thread->statearg = STATE_RUNNING; | 419 | thread->state = STATE_RUNNING; |
420 | SDL_CondSignal(thread->context.c); | ||
421 | return thread; | ||
422 | default: | ||
423 | return NULL; | ||
424 | } | ||
425 | } | ||
426 | |||
427 | void thread_thaw(struct thread_entry *thread) | ||
428 | { | ||
429 | if (thread->state == STATE_FROZEN) | ||
430 | { | ||
431 | thread->state = STATE_RUNNING; | ||
404 | SDL_CondSignal(thread->context.c); | 432 | SDL_CondSignal(thread->context.c); |
405 | break; | ||
406 | } | 433 | } |
407 | } | 434 | } |
408 | 435 | ||
@@ -434,12 +461,24 @@ void remove_thread(struct thread_entry *thread) | |||
434 | thread->context.t = NULL; | 461 | thread->context.t = NULL; |
435 | 462 | ||
436 | if (thread != current) | 463 | if (thread != current) |
464 | { | ||
465 | switch (thread->state) | ||
466 | { | ||
467 | case STATE_BLOCKED: | ||
468 | case STATE_BLOCKED_W_TMO: | ||
469 | /* Remove thread from object it's waiting on */ | ||
470 | remove_from_list_l(&thread->bqp->queue, thread); | ||
471 | break; | ||
472 | } | ||
473 | |||
437 | SDL_CondSignal(c); | 474 | SDL_CondSignal(c); |
475 | } | ||
438 | 476 | ||
439 | THREAD_SDL_DEBUGF("Removing thread: %d (%s)\n", | 477 | THREAD_SDL_DEBUGF("Removing thread: %d (%s)\n", |
440 | thread - threads, THREAD_SDL_GET_NAME(thread)); | 478 | thread - threads, THREAD_SDL_GET_NAME(thread)); |
441 | 479 | ||
442 | thread->name = NULL; | 480 | thread_queue_wake_no_listlock(&thread->queue); |
481 | thread->state = STATE_KILLED; | ||
443 | 482 | ||
444 | SDL_DestroyCond(c); | 483 | SDL_DestroyCond(c); |
445 | 484 | ||
@@ -453,15 +492,26 @@ void remove_thread(struct thread_entry *thread) | |||
453 | SDL_KillThread(t); | 492 | SDL_KillThread(t); |
454 | } | 493 | } |
455 | 494 | ||
495 | void thread_wait(struct thread_entry *thread) | ||
496 | { | ||
497 | if (thread == NULL) | ||
498 | thread = running; | ||
499 | |||
500 | if (thread->state != STATE_KILLED) | ||
501 | { | ||
502 | block_thread_no_listlock(&thread->queue); | ||
503 | } | ||
504 | } | ||
505 | |||
456 | int thread_stack_usage(const struct thread_entry *thread) | 506 | int thread_stack_usage(const struct thread_entry *thread) |
457 | { | 507 | { |
458 | return 50; | 508 | return 50; |
459 | (void)thread; | 509 | (void)thread; |
460 | } | 510 | } |
461 | 511 | ||
462 | int thread_get_status(const struct thread_entry *thread) | 512 | unsigned thread_get_status(const struct thread_entry *thread) |
463 | { | 513 | { |
464 | return thread->statearg; | 514 | return thread->state; |
465 | } | 515 | } |
466 | 516 | ||
467 | /* Return name if one or ID if none */ | 517 | /* Return name if one or ID if none */ |