diff options
-rw-r--r-- | apps/gui/list.c | 8 | ||||
-rw-r--r-- | apps/main.c | 5 | ||||
-rw-r--r-- | uisimulator/sdl/button.c | 25 | ||||
-rw-r--r-- | uisimulator/sdl/kernel.c | 147 | ||||
-rw-r--r-- | uisimulator/sdl/thread-sdl.c | 34 | ||||
-rw-r--r-- | uisimulator/sdl/uisdl.c | 17 |
6 files changed, 184 insertions, 52 deletions
diff --git a/apps/gui/list.c b/apps/gui/list.c index 4d19bbdf96..38cecaefcc 100644 --- a/apps/gui/list.c +++ b/apps/gui/list.c | |||
@@ -1285,11 +1285,11 @@ bool simplelist_show_list(struct simplelist_info *info) | |||
1285 | gui_syncstatusbar_draw(&statusbars, true); | 1285 | gui_syncstatusbar_draw(&statusbars, true); |
1286 | list_do_action(CONTEXT_STD, info->timeout, | 1286 | list_do_action(CONTEXT_STD, info->timeout, |
1287 | &lists, &action, LIST_WRAP_UNLESS_HELD); | 1287 | &lists, &action, LIST_WRAP_UNLESS_HELD); |
1288 | #ifdef SIMULATOR | 1288 | |
1289 | /* Sim has no interrupts, so this is needed for buttons to be recognised */ | 1289 | /* We must yield in this case or no other thread can run */ |
1290 | if (info->timeout == TIMEOUT_NOBLOCK) | 1290 | if (info->timeout == TIMEOUT_NOBLOCK) |
1291 | yield(); | 1291 | yield(); |
1292 | #endif | 1292 | |
1293 | if (info->action_callback) | 1293 | if (info->action_callback) |
1294 | { | 1294 | { |
1295 | action = info->action_callback(action, &lists); | 1295 | action = info->action_callback(action, &lists); |
diff --git a/apps/main.c b/apps/main.c index 366fed9585..d75bb726cf 100644 --- a/apps/main.c +++ b/apps/main.c | |||
@@ -113,6 +113,10 @@ | |||
113 | 113 | ||
114 | #include "cuesheet.h" | 114 | #include "cuesheet.h" |
115 | 115 | ||
116 | #ifdef SIMULATOR | ||
117 | #include "system-sdl.h" | ||
118 | #endif | ||
119 | |||
116 | /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */ | 120 | /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */ |
117 | 121 | ||
118 | const char appsversion[]=APPSVERSION; | 122 | const char appsversion[]=APPSVERSION; |
@@ -267,6 +271,7 @@ static void init(void) | |||
267 | { | 271 | { |
268 | init_threads(); | 272 | init_threads(); |
269 | buffer_init(); | 273 | buffer_init(); |
274 | set_irq_level(0); | ||
270 | lcd_init(); | 275 | lcd_init(); |
271 | #ifdef HAVE_REMOTE_LCD | 276 | #ifdef HAVE_REMOTE_LCD |
272 | lcd_remote_init(); | 277 | lcd_remote_init(); |
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 | ||
31 | static intptr_t button_data; /* data value from last message dequeued */ | 31 | static 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 */ | ||
34 | extern 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 */ | ||
36 | extern 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 */ | ||
33 | static SDL_cond *sim_thread_cond; | ||
34 | /* Protect sim irq object when it is being changed */ | ||
35 | static SDL_mutex *sim_irq_mtx; | ||
36 | static int interrupt_level = HIGHEST_IRQ_LEVEL; | ||
37 | static int status_reg = 0; | ||
38 | |||
39 | extern 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 | */ | ||
47 | int 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 | |||
65 | void 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 | |||
76 | void sim_exit_irq_handler(void) | ||
77 | { | ||
78 | status_reg = 0; | ||
79 | SDL_UnlockMutex(sim_irq_mtx); | ||
80 | } | ||
81 | |||
82 | bool 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 | |||
102 | void sim_kernel_shutdown(void) | ||
103 | { | ||
104 | SDL_DestroyMutex(sim_irq_mtx); | ||
105 | SDL_DestroyCond(sim_thread_cond); | ||
106 | } | ||
107 | |||
28 | volatile long current_tick = 0; | 108 | volatile long current_tick = 0; |
29 | static void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); | 109 | static void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); |
30 | 110 | ||
@@ -85,17 +165,21 @@ static void queue_release_all_senders(struct event_queue *q) | |||
85 | void queue_enable_queue_send(struct event_queue *q, | 165 | void 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 | ||
97 | void queue_init(struct event_queue *q, bool register_queue) | 179 | void 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 | ||
118 | void queue_delete(struct event_queue *q) | 204 | void 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 | ||
158 | void queue_wait(struct event_queue *q, struct queue_event *ev) | 248 | void 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 | ||
191 | void queue_wait_w_tmo(struct event_queue *q, struct queue_event *ev, int ticks) | 286 | void 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 | ||
225 | void queue_post(struct event_queue *q, long id, intptr_t data) | 326 | void 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); |
249 | void 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 |
258 | intptr_t queue_send(struct event_queue *q, long id, intptr_t data) | 354 | intptr_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 | ||
308 | void queue_clear(struct event_queue* q) | 409 | void 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 | ||
320 | void queue_remove_from_head(struct event_queue *q, long id) | 425 | void 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 | ||
347 | int queue_count(const struct event_queue *q) | 456 | int queue_count(const struct event_queue *q) |
@@ -351,25 +460,16 @@ int queue_count(const struct event_queue *q) | |||
351 | 460 | ||
352 | int queue_broadcast(long id, intptr_t data) | 461 | int 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); |
365 | int 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 | ||
375 | void yield(void) | 475 | void yield(void) |
@@ -398,6 +498,7 @@ void sim_tick_tasks(void) | |||
398 | 498 | ||
399 | int tick_add_task(void (*f)(void)) | 499 | int 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 | ||
417 | int tick_remove_task(void (*f)(void)) | 519 | int 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 */ |
50 | struct core_entry cores[NUM_CORES]; | ||
49 | struct thread_entry threads[MAXTHREADS]; | 51 | struct 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 | ||
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 | |||
167 | static int find_empty_thread_slot(void) | 160 | static 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 | ||
216 | static 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 | |||
223 | struct thread_entry *thread_get_current(void) | 227 | struct 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 | ||
495 | void thread_wait(struct thread_entry *thread) | 507 | void 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 | ||
171 | bool gui_shutdown(void) | 180 | bool 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; |