summaryrefslogtreecommitdiff
path: root/uisimulator/sdl
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-10-26 23:11:18 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-10-26 23:11:18 +0000
commitd6af28739747099f98f541d1b76ba501882e113c (patch)
treeb6ad8d89d0ef96dd4cea37dd89aad8d3fa345179 /uisimulator/sdl
parentf026c0fc826149a3c88d462cca02b69ef5690c30 (diff)
downloadrockbox-d6af28739747099f98f541d1b76ba501882e113c.tar.gz
rockbox-d6af28739747099f98f541d1b76ba501882e113c.zip
Implement as genuine a set_irq_level function for the sim as possible. The yield added earlier is still nescessary since other threads won't run anyway while viewing the database screen on either sim or target.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15321 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'uisimulator/sdl')
-rw-r--r--uisimulator/sdl/button.c25
-rw-r--r--uisimulator/sdl/kernel.c147
-rw-r--r--uisimulator/sdl/thread-sdl.c34
-rw-r--r--uisimulator/sdl/uisdl.c17
4 files changed, 175 insertions, 48 deletions
diff --git a/uisimulator/sdl/button.c b/uisimulator/sdl/button.c
index 62c2c33150..04475122b5 100644
--- a/uisimulator/sdl/button.c
+++ b/uisimulator/sdl/button.c
@@ -30,11 +30,6 @@
30 30
31static intptr_t button_data; /* data value from last message dequeued */ 31static intptr_t button_data; /* data value from last message dequeued */
32 32
33/* Special thread-synced queue_post for button driver or any other preemptive sim thread */
34extern void queue_syncpost(struct event_queue *q, long id, intptr_t data);
35/* Special thread-synced queue_broadcast for button driver or any other preemptive sim thread */
36extern int queue_syncbroadcast(long id, intptr_t data);
37
38/* how long until repeat kicks in */ 33/* how long until repeat kicks in */
39#define REPEAT_START 6 34#define REPEAT_START 6
40 35
@@ -115,9 +110,9 @@ void button_event(int key, bool pressed)
115 { 110 {
116 usb_connected = !usb_connected; 111 usb_connected = !usb_connected;
117 if (usb_connected) 112 if (usb_connected)
118 queue_syncpost(&button_queue, SYS_USB_CONNECTED, 0); 113 queue_post(&button_queue, SYS_USB_CONNECTED, 0);
119 else 114 else
120 queue_syncpost(&button_queue, SYS_USB_DISCONNECTED, 0); 115 queue_post(&button_queue, SYS_USB_DISCONNECTED, 0);
121 } 116 }
122 return; 117 return;
123 118
@@ -634,7 +629,7 @@ void button_event(int key, bool pressed)
634 case SDLK_F5: 629 case SDLK_F5:
635 if(pressed) 630 if(pressed)
636 { 631 {
637 queue_syncbroadcast(SYS_SCREENDUMP, 0); 632 queue_broadcast(SYS_SCREENDUMP, 0);
638 return; 633 return;
639 } 634 }
640 break; 635 break;
@@ -655,17 +650,17 @@ void button_event(int key, bool pressed)
655#ifdef HAVE_REMOTE_LCD 650#ifdef HAVE_REMOTE_LCD
656 if(diff & BUTTON_REMOTE) 651 if(diff & BUTTON_REMOTE)
657 if(!skip_remote_release) 652 if(!skip_remote_release)
658 queue_syncpost(&button_queue, BUTTON_REL | diff, 0); 653 queue_post(&button_queue, BUTTON_REL | diff, 0);
659 else 654 else
660 skip_remote_release = false; 655 skip_remote_release = false;
661 else 656 else
662#endif 657#endif
663 if(!skip_release) 658 if(!skip_release)
664 queue_syncpost(&button_queue, BUTTON_REL | diff, 0); 659 queue_post(&button_queue, BUTTON_REL | diff, 0);
665 else 660 else
666 skip_release = false; 661 skip_release = false;
667#else 662#else
668 queue_syncpost(&button_queue, BUTTON_REL | diff, 0); 663 queue_post(&button_queue, BUTTON_REL | diff, 0);
669#endif 664#endif
670 } 665 }
671 666
@@ -717,7 +712,7 @@ void button_event(int key, bool pressed)
717 { 712 {
718 if (queue_empty(&button_queue)) 713 if (queue_empty(&button_queue))
719 { 714 {
720 queue_syncpost(&button_queue, BUTTON_REPEAT | btn, 0); 715 queue_post(&button_queue, BUTTON_REPEAT | btn, 0);
721#ifdef HAVE_BACKLIGHT 716#ifdef HAVE_BACKLIGHT
722#ifdef HAVE_REMOTE_LCD 717#ifdef HAVE_REMOTE_LCD
723 if(btn & BUTTON_REMOTE) 718 if(btn & BUTTON_REMOTE)
@@ -739,18 +734,18 @@ void button_event(int key, bool pressed)
739#ifdef HAVE_REMOTE_LCD 734#ifdef HAVE_REMOTE_LCD
740 if (btn & BUTTON_REMOTE) { 735 if (btn & BUTTON_REMOTE) {
741 if (!remote_filter_first_keypress || is_remote_backlight_on()) 736 if (!remote_filter_first_keypress || is_remote_backlight_on())
742 queue_syncpost(&button_queue, btn, 0); 737 queue_post(&button_queue, btn, 0);
743 else 738 else
744 skip_remote_release = true; 739 skip_remote_release = true;
745 } 740 }
746 else 741 else
747#endif 742#endif
748 if (!filter_first_keypress || is_backlight_on()) 743 if (!filter_first_keypress || is_backlight_on())
749 queue_syncpost(&button_queue, btn, 0); 744 queue_post(&button_queue, btn, 0);
750 else 745 else
751 skip_release = true; 746 skip_release = true;
752#else /* no backlight, nothing to skip */ 747#else /* no backlight, nothing to skip */
753 queue_syncpost(&button_queue, btn, 0); 748 queue_post(&button_queue, btn, 0);
754#endif 749#endif
755 post = false; 750 post = false;
756 } 751 }
diff --git a/uisimulator/sdl/kernel.c b/uisimulator/sdl/kernel.c
index 6a8c9e4538..4e0a508f74 100644
--- a/uisimulator/sdl/kernel.c
+++ b/uisimulator/sdl/kernel.c
@@ -18,13 +18,93 @@
18 ****************************************************************************/ 18 ****************************************************************************/
19 19
20#include <stdlib.h> 20#include <stdlib.h>
21#include <SDL.h>
22#include <SDL_thread.h>
21#include "memory.h" 23#include "memory.h"
24#include "system-sdl.h"
22#include "uisdl.h" 25#include "uisdl.h"
23#include "kernel.h" 26#include "kernel.h"
24#include "thread-sdl.h" 27#include "thread-sdl.h"
25#include "thread.h" 28#include "thread.h"
26#include "debug.h" 29#include "debug.h"
27 30
31/* Prevent "irq handler" from thread concurrent access as well as current
32 * access on multiple handlers */
33static SDL_cond *sim_thread_cond;
34/* Protect sim irq object when it is being changed */
35static SDL_mutex *sim_irq_mtx;
36static int interrupt_level = HIGHEST_IRQ_LEVEL;
37static int status_reg = 0;
38
39extern struct core_entry cores[NUM_CORES];
40
41/* Nescessary logic:
42 * 1) All threads must pass unblocked
43 * 2) Current handler must always pass unblocked
44 * 3) Threads must be excluded when irq routine is running
45 * 4) No more than one handler routine should execute at a time
46 */
47int set_irq_level(int level)
48{
49 SDL_LockMutex(sim_irq_mtx);
50
51 int oldlevel = interrupt_level;
52
53 if (status_reg == 0 && level == 0 && oldlevel != 0)
54 {
55 /* Not in a handler and "interrupts" are being reenabled */
56 SDL_CondSignal(sim_thread_cond);
57 }
58
59 interrupt_level = level; /* save new level */
60
61 SDL_UnlockMutex(sim_irq_mtx);
62 return oldlevel;
63}
64
65void sim_enter_irq_handler(void)
66{
67 SDL_LockMutex(sim_irq_mtx);
68 if(interrupt_level != 0)
69 {
70 /* "Interrupts" are disabled. Wait for reenable */
71 SDL_CondWait(sim_thread_cond, sim_irq_mtx);
72 }
73 status_reg = 1;
74}
75
76void sim_exit_irq_handler(void)
77{
78 status_reg = 0;
79 SDL_UnlockMutex(sim_irq_mtx);
80}
81
82bool sim_kernel_init(void)
83{
84 sim_irq_mtx = SDL_CreateMutex();
85 if (sim_irq_mtx == NULL)
86 {
87 fprintf(stderr, "Cannot create sim_handler_mtx\n");
88 return false;
89 }
90
91 /* Create with a count of 0 to have interrupts disabled by default */
92 sim_thread_cond = SDL_CreateCond();
93 if (sim_thread_cond == NULL)
94 {
95 fprintf(stderr, "Cannot create sim_thread_cond\n");
96 return false;
97 }
98
99 return true;
100}
101
102void sim_kernel_shutdown(void)
103{
104 SDL_DestroyMutex(sim_irq_mtx);
105 SDL_DestroyCond(sim_thread_cond);
106}
107
28volatile long current_tick = 0; 108volatile long current_tick = 0;
29static void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); 109static void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
30 110
@@ -85,17 +165,21 @@ static void queue_release_all_senders(struct event_queue *q)
85void queue_enable_queue_send(struct event_queue *q, 165void queue_enable_queue_send(struct event_queue *q,
86 struct queue_sender_list *send) 166 struct queue_sender_list *send)
87{ 167{
168 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
88 q->send = NULL; 169 q->send = NULL;
89 if(send) 170 if(send)
90 { 171 {
91 q->send = send; 172 q->send = send;
92 memset(send, 0, sizeof(*send)); 173 memset(send, 0, sizeof(*send));
93 } 174 }
175 set_irq_level(oldlevel);
94} 176}
95#endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */ 177#endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */
96 178
97void queue_init(struct event_queue *q, bool register_queue) 179void queue_init(struct event_queue *q, bool register_queue)
98{ 180{
181 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
182
99 q->read = 0; 183 q->read = 0;
100 q->write = 0; 184 q->write = 0;
101 thread_queue_init(&q->queue); 185 thread_queue_init(&q->queue);
@@ -113,6 +197,8 @@ void queue_init(struct event_queue *q, bool register_queue)
113 /* Add it to the all_queues array */ 197 /* Add it to the all_queues array */
114 all_queues[num_queues++] = q; 198 all_queues[num_queues++] = q;
115 } 199 }
200
201 set_irq_level(oldlevel);
116} 202}
117 203
118void queue_delete(struct event_queue *q) 204void queue_delete(struct event_queue *q)
@@ -120,6 +206,8 @@ void queue_delete(struct event_queue *q)
120 int i; 206 int i;
121 bool found = false; 207 bool found = false;
122 208
209 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
210
123 /* Find the queue to be deleted */ 211 /* Find the queue to be deleted */
124 for(i = 0;i < num_queues;i++) 212 for(i = 0;i < num_queues;i++)
125 { 213 {
@@ -153,11 +241,14 @@ void queue_delete(struct event_queue *q)
153 241
154 q->read = 0; 242 q->read = 0;
155 q->write = 0; 243 q->write = 0;
244
245 set_irq_level(oldlevel);
156} 246}
157 247
158void queue_wait(struct event_queue *q, struct queue_event *ev) 248void queue_wait(struct event_queue *q, struct queue_event *ev)
159{ 249{
160 unsigned int rd; 250 unsigned int rd;
251 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
161 252
162#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 253#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
163 if (q->send && q->send->curr_sender) 254 if (q->send && q->send->curr_sender)
@@ -171,7 +262,9 @@ void queue_wait(struct event_queue *q, struct queue_event *ev)
171 { 262 {
172 do 263 do
173 { 264 {
265 cores[CURRENT_CORE].irq_level = oldlevel;
174 block_thread(&q->queue); 266 block_thread(&q->queue);
267 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
175 } 268 }
176 while (q->read == q->write); 269 while (q->read == q->write);
177 } 270 }
@@ -186,10 +279,14 @@ void queue_wait(struct event_queue *q, struct queue_event *ev)
186 queue_fetch_sender(q->send, rd); 279 queue_fetch_sender(q->send, rd);
187 } 280 }
188#endif 281#endif
282
283 set_irq_level(oldlevel);
189} 284}
190 285
191void queue_wait_w_tmo(struct event_queue *q, struct queue_event *ev, int ticks) 286void queue_wait_w_tmo(struct event_queue *q, struct queue_event *ev, int ticks)
192{ 287{
288 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
289
193#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 290#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
194 if (q->send && q->send->curr_sender) 291 if (q->send && q->send->curr_sender)
195 { 292 {
@@ -200,7 +297,9 @@ void queue_wait_w_tmo(struct event_queue *q, struct queue_event *ev, int ticks)
200 297
201 if (q->read == q->write && ticks > 0) 298 if (q->read == q->write && ticks > 0)
202 { 299 {
300 cores[CURRENT_CORE].irq_level = oldlevel;
203 block_thread_w_tmo(&q->queue, ticks); 301 block_thread_w_tmo(&q->queue, ticks);
302 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
204 } 303 }
205 304
206 if(q->read != q->write) 305 if(q->read != q->write)
@@ -220,10 +319,14 @@ void queue_wait_w_tmo(struct event_queue *q, struct queue_event *ev, int ticks)
220 { 319 {
221 ev->id = SYS_TIMEOUT; 320 ev->id = SYS_TIMEOUT;
222 } 321 }
322
323 set_irq_level(oldlevel);
223} 324}
224 325
225void queue_post(struct event_queue *q, long id, intptr_t data) 326void queue_post(struct event_queue *q, long id, intptr_t data)
226{ 327{
328 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
329
227 unsigned int wr = q->write++ & QUEUE_LENGTH_MASK; 330 unsigned int wr = q->write++ & QUEUE_LENGTH_MASK;
228 331
229 q->events[wr].id = id; 332 q->events[wr].id = id;
@@ -243,20 +346,15 @@ void queue_post(struct event_queue *q, long id, intptr_t data)
243#endif 346#endif
244 347
245 wakeup_thread(&q->queue); 348 wakeup_thread(&q->queue);
246}
247 349
248/* Special thread-synced queue_post for button driver or any other preemptive sim thread */ 350 set_irq_level(oldlevel);
249void queue_syncpost(struct event_queue *q, long id, intptr_t data)
250{
251 thread_sdl_lock();
252 /* No rockbox threads can be running here */
253 queue_post(q, id, data);
254 thread_sdl_unlock();
255} 351}
256 352
257#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 353#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
258intptr_t queue_send(struct event_queue *q, long id, intptr_t data) 354intptr_t queue_send(struct event_queue *q, long id, intptr_t data)
259{ 355{
356 int oldlevel = set_irq_level(oldlevel);
357
260 unsigned int wr = q->write++ & QUEUE_LENGTH_MASK; 358 unsigned int wr = q->write++ & QUEUE_LENGTH_MASK;
261 359
262 q->events[wr].id = id; 360 q->events[wr].id = id;
@@ -274,11 +372,14 @@ intptr_t queue_send(struct event_queue *q, long id, intptr_t data)
274 372
275 wakeup_thread(&q->queue); 373 wakeup_thread(&q->queue);
276 374
375 cores[CURRENT_CORE].irq_level = oldlevel;
277 block_thread_no_listlock(spp); 376 block_thread_no_listlock(spp);
278 return thread_get_current()->retval; 377 return thread_get_current()->retval;
279 } 378 }
280 379
281 /* Function as queue_post if sending is not enabled */ 380 /* Function as queue_post if sending is not enabled */
381 wakeup_thread(&q->queue);
382 set_irq_level(oldlevel);
282 return 0; 383 return 0;
283} 384}
284 385
@@ -307,6 +408,8 @@ bool queue_empty(const struct event_queue* q)
307 408
308void queue_clear(struct event_queue* q) 409void queue_clear(struct event_queue* q)
309{ 410{
411 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
412
310 /* fixme: This is potentially unsafe in case we do interrupt-like processing */ 413 /* fixme: This is potentially unsafe in case we do interrupt-like processing */
311#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 414#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
312 /* Release all thread waiting in the queue for a reply - 415 /* Release all thread waiting in the queue for a reply -
@@ -315,10 +418,14 @@ void queue_clear(struct event_queue* q)
315#endif 418#endif
316 q->read = 0; 419 q->read = 0;
317 q->write = 0; 420 q->write = 0;
421
422 set_irq_level(oldlevel);
318} 423}
319 424
320void queue_remove_from_head(struct event_queue *q, long id) 425void queue_remove_from_head(struct event_queue *q, long id)
321{ 426{
427 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
428
322 while(q->read != q->write) 429 while(q->read != q->write)
323 { 430 {
324 unsigned int rd = q->read & QUEUE_LENGTH_MASK; 431 unsigned int rd = q->read & QUEUE_LENGTH_MASK;
@@ -342,6 +449,8 @@ void queue_remove_from_head(struct event_queue *q, long id)
342#endif 449#endif
343 q->read++; 450 q->read++;
344 } 451 }
452
453 set_irq_level(oldlevel);
345} 454}
346 455
347int queue_count(const struct event_queue *q) 456int queue_count(const struct event_queue *q)
@@ -351,25 +460,16 @@ int queue_count(const struct event_queue *q)
351 460
352int queue_broadcast(long id, intptr_t data) 461int queue_broadcast(long id, intptr_t data)
353{ 462{
463 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
354 int i; 464 int i;
355 465
356 for(i = 0;i < num_queues;i++) 466 for(i = 0;i < num_queues;i++)
357 { 467 {
358 queue_post(all_queues[i], id, data); 468 queue_post(all_queues[i], id, data);
359 } 469 }
360
361 return num_queues;
362}
363 470
364/* Special thread-synced queue_broadcast for button driver or any other preemptive sim thread */ 471 set_irq_level(oldlevel);
365int queue_syncbroadcast(long id, intptr_t data) 472 return num_queues;
366{
367 int i;
368 thread_sdl_lock();
369 /* No rockbox threads can be running here */
370 i = queue_broadcast(id, data);
371 thread_sdl_unlock();
372 return i;
373} 473}
374 474
375void yield(void) 475void yield(void)
@@ -398,6 +498,7 @@ void sim_tick_tasks(void)
398 498
399int tick_add_task(void (*f)(void)) 499int tick_add_task(void (*f)(void))
400{ 500{
501 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
401 int i; 502 int i;
402 503
403 /* Add a task if there is room */ 504 /* Add a task if there is room */
@@ -406,6 +507,7 @@ int tick_add_task(void (*f)(void))
406 if(tick_funcs[i] == NULL) 507 if(tick_funcs[i] == NULL)
407 { 508 {
408 tick_funcs[i] = f; 509 tick_funcs[i] = f;
510 set_irq_level(oldlevel);
409 return 0; 511 return 0;
410 } 512 }
411 } 513 }
@@ -416,6 +518,7 @@ int tick_add_task(void (*f)(void))
416 518
417int tick_remove_task(void (*f)(void)) 519int tick_remove_task(void (*f)(void))
418{ 520{
521 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
419 int i; 522 int i;
420 523
421 /* Remove a task if it is there */ 524 /* Remove a task if it is there */
@@ -424,10 +527,12 @@ int tick_remove_task(void (*f)(void))
424 if(tick_funcs[i] == f) 527 if(tick_funcs[i] == f)
425 { 528 {
426 tick_funcs[i] = NULL; 529 tick_funcs[i] = NULL;
530 set_irq_level(oldlevel);
427 return 0; 531 return 0;
428 } 532 }
429 } 533 }
430 534
535 set_irq_level(oldlevel);
431 return -1; 536 return -1;
432} 537}
433 538
diff --git a/uisimulator/sdl/thread-sdl.c b/uisimulator/sdl/thread-sdl.c
index 6a3c4af9eb..a07ac29738 100644
--- a/uisimulator/sdl/thread-sdl.c
+++ b/uisimulator/sdl/thread-sdl.c
@@ -24,6 +24,7 @@
24#include <stdlib.h> 24#include <stdlib.h>
25#include <memory.h> 25#include <memory.h>
26#include <setjmp.h> 26#include <setjmp.h>
27#include "system-sdl.h"
27#include "thread-sdl.h" 28#include "thread-sdl.h"
28#include "kernel.h" 29#include "kernel.h"
29#include "thread.h" 30#include "thread.h"
@@ -45,7 +46,8 @@ static char __name[32];
45#define THREAD_PANICF(str...) \ 46#define THREAD_PANICF(str...) \
46 ({ fprintf(stderr, str); exit(-1); }) 47 ({ fprintf(stderr, str); exit(-1); })
47 48
48/* Thread entries as in core */ 49/* Thread/core entries as in rockbox core */
50struct core_entry cores[NUM_CORES];
49struct thread_entry threads[MAXTHREADS]; 51struct thread_entry threads[MAXTHREADS];
50/* Jump buffers for graceful exit - kernel threads don't stay neatly 52/* Jump buffers for graceful exit - kernel threads don't stay neatly
51 * in their start routines responding to messages so this is the only 53 * in their start routines responding to messages so this is the only
@@ -133,6 +135,7 @@ bool thread_sdl_init(void *param)
133 running->name = "main"; 135 running->name = "main";
134 running->state = STATE_RUNNING; 136 running->state = STATE_RUNNING;
135 running->context.c = SDL_CreateCond(); 137 running->context.c = SDL_CreateCond();
138 cores[CURRENT_CORE].irq_level = STAY_IRQ_LEVEL;
136 139
137 if (running->context.c == NULL) 140 if (running->context.c == NULL)
138 { 141 {
@@ -154,16 +157,6 @@ bool thread_sdl_init(void *param)
154 return true; 157 return true;
155} 158}
156 159
157void thread_sdl_lock(void)
158{
159 SDL_LockMutex(m);
160}
161
162void thread_sdl_unlock(void)
163{
164 SDL_UnlockMutex(m);
165}
166
167static int find_empty_thread_slot(void) 160static int find_empty_thread_slot(void)
168{ 161{
169 int n; 162 int n;
@@ -220,6 +213,17 @@ static void remove_from_list_l(struct thread_entry **list,
220 thread->l.next->l.prev = thread->l.prev; 213 thread->l.next->l.prev = thread->l.prev;
221} 214}
222 215
216static void run_blocking_ops(void)
217{
218 int level = cores[CURRENT_CORE].irq_level;
219
220 if (level != STAY_IRQ_LEVEL)
221 {
222 cores[CURRENT_CORE].irq_level = STAY_IRQ_LEVEL;
223 set_irq_level(level);
224 }
225}
226
223struct thread_entry *thread_get_current(void) 227struct thread_entry *thread_get_current(void)
224{ 228{
225 return running; 229 return running;
@@ -373,6 +377,8 @@ void _block_thread(struct thread_queue *tq)
373 thread->bqp = tq; 377 thread->bqp = tq;
374 add_to_list_l(&tq->queue, thread); 378 add_to_list_l(&tq->queue, thread);
375 379
380 run_blocking_ops();
381
376 SDL_CondWait(thread->context.c, m); 382 SDL_CondWait(thread->context.c, m);
377 running = thread; 383 running = thread;
378 384
@@ -388,6 +394,8 @@ void block_thread_w_tmo(struct thread_queue *tq, int ticks)
388 thread->bqp = tq; 394 thread->bqp = tq;
389 add_to_list_l(&tq->queue, thread); 395 add_to_list_l(&tq->queue, thread);
390 396
397 run_blocking_ops();
398
391 SDL_CondWaitTimeout(thread->context.c, m, (1000/HZ) * ticks); 399 SDL_CondWaitTimeout(thread->context.c, m, (1000/HZ) * ticks);
392 running = thread; 400 running = thread;
393 401
@@ -451,6 +459,8 @@ void remove_thread(struct thread_entry *thread)
451 SDL_Thread *t; 459 SDL_Thread *t;
452 SDL_cond *c; 460 SDL_cond *c;
453 461
462 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
463
454 if (thread == NULL) 464 if (thread == NULL)
455 { 465 {
456 thread = current; 466 thread = current;
@@ -486,10 +496,12 @@ void remove_thread(struct thread_entry *thread)
486 { 496 {
487 /* Do a graceful exit - perform the longjmp back into the thread 497 /* Do a graceful exit - perform the longjmp back into the thread
488 function to return */ 498 function to return */
499 set_irq_level(oldlevel);
489 longjmp(thread_jmpbufs[current - threads], 1); 500 longjmp(thread_jmpbufs[current - threads], 1);
490 } 501 }
491 502
492 SDL_KillThread(t); 503 SDL_KillThread(t);
504 set_irq_level(oldlevel);
493} 505}
494 506
495void thread_wait(struct thread_entry *thread) 507void thread_wait(struct thread_entry *thread)
diff --git a/uisimulator/sdl/uisdl.c b/uisimulator/sdl/uisdl.c
index 9dcdbc7e26..d9c64abce2 100644
--- a/uisimulator/sdl/uisdl.c
+++ b/uisimulator/sdl/uisdl.c
@@ -22,6 +22,7 @@
22#include <setjmp.h> 22#include <setjmp.h>
23#include "autoconf.h" 23#include "autoconf.h"
24#include "button.h" 24#include "button.h"
25#include "system-sdl.h"
25#include "thread.h" 26#include "thread.h"
26#include "kernel.h" 27#include "kernel.h"
27#include "uisdl.h" 28#include "uisdl.h"
@@ -75,7 +76,11 @@ Uint32 tick_timer(Uint32 interval, void *param)
75 if (new_tick != current_tick) { 76 if (new_tick != current_tick) {
76 long i; 77 long i;
77 for (i = new_tick - current_tick; i > 0; i--) 78 for (i = new_tick - current_tick; i > 0; i--)
79 {
80 sim_enter_irq_handler();
78 sim_tick_tasks(); 81 sim_tick_tasks();
82 sim_exit_irq_handler();
83 }
79 current_tick = new_tick; 84 current_tick = new_tick;
80 } 85 }
81 86
@@ -92,10 +97,14 @@ void gui_message_loop(void)
92 switch(event.type) 97 switch(event.type)
93 { 98 {
94 case SDL_KEYDOWN: 99 case SDL_KEYDOWN:
100 sim_enter_irq_handler();
95 button_event(event.key.keysym.sym, true); 101 button_event(event.key.keysym.sym, true);
102 sim_exit_irq_handler();
96 break; 103 break;
97 case SDL_KEYUP: 104 case SDL_KEYUP:
105 sim_enter_irq_handler();
98 button_event(event.key.keysym.sym, false); 106 button_event(event.key.keysym.sym, false);
107 sim_exit_irq_handler();
99 break; 108 break;
100 case SDL_QUIT: 109 case SDL_QUIT:
101 done = true; 110 done = true;
@@ -170,11 +179,12 @@ bool gui_startup(void)
170 179
171bool gui_shutdown(void) 180bool gui_shutdown(void)
172{ 181{
173 SDL_RemoveTimer(tick_timer_id);
174 /* Order here is relevent to prevent deadlocks and use of destroyed 182 /* Order here is relevent to prevent deadlocks and use of destroyed
175 sync primitives by kernel threads */ 183 sync primitives by kernel threads */
176 thread_sdl_shutdown(); 184 thread_sdl_shutdown();
185 SDL_RemoveTimer(tick_timer_id);
177 sim_io_shutdown(); 186 sim_io_shutdown();
187 sim_kernel_shutdown();
178 return true; 188 return true;
179} 189}
180 190
@@ -228,6 +238,11 @@ int main(int argc, char *argv[])
228 background = false; 238 background = false;
229 } 239 }
230 240
241 if (!sim_kernel_init()) {
242 fprintf(stderr, "sim_kernel_init failed\n");
243 return -1;
244 }
245
231 if (!sim_io_init()) { 246 if (!sim_io_init()) {
232 fprintf(stderr, "sim_io_init failed\n"); 247 fprintf(stderr, "sim_io_init failed\n");
233 return -1; 248 return -1;