summaryrefslogtreecommitdiff
path: root/uisimulator
diff options
context:
space:
mode:
Diffstat (limited to 'uisimulator')
-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;