summaryrefslogtreecommitdiff
path: root/uisimulator/sdl/thread-sdl.c
diff options
context:
space:
mode:
Diffstat (limited to 'uisimulator/sdl/thread-sdl.c')
-rw-r--r--uisimulator/sdl/thread-sdl.c160
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
157void thread_sdl_lock(void)
158{
159 SDL_LockMutex(m);
160}
161
162void thread_sdl_unlock(void)
163{
164 SDL_UnlockMutex(m);
165}
166
157static int find_empty_thread_slot(void) 167static 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
170static void add_to_list(struct thread_entry **list, 182static 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
190static void remove_from_list(struct thread_entry **list, 202static 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
211struct thread_entry *thread_get_current(void) 223struct 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
216void thread_sdl_lock(void) 228void switch_thread(struct thread_entry *old)
217{
218 SDL_LockMutex(m);
219}
220
221void thread_sdl_unlock(void)
222{
223 SDL_UnlockMutex(m);
224}
225
226void 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
241void sleep_thread(int ticks) 243void 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
307struct thread_entry* 320struct 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
354void block_thread(struct thread_entry **list) 368void _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
368void block_thread_w_tmo(struct thread_entry **list, int ticks) 383void 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
389void wakeup_thread(struct thread_entry **list) 405struct 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
427void 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
495void 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
456int thread_stack_usage(const struct thread_entry *thread) 506int 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
462int thread_get_status(const struct thread_entry *thread) 512unsigned 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 */