diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2007-03-26 03:24:36 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2007-03-26 03:24:36 +0000 |
commit | 165f62d0cd771660e4b8d2ba7475e14d0d6f2e9f (patch) | |
tree | 2818158a5c6f250dc928319d7cc6c91788519b78 /firmware/kernel.c | |
parent | 5e2984ad80a732f39b8d0df130176e67b30b9469 (diff) | |
download | rockbox-165f62d0cd771660e4b8d2ba7475e14d0d6f2e9f.tar.gz rockbox-165f62d0cd771660e4b8d2ba7475e14d0d6f2e9f.zip |
Fix a hole in the scheduler where collisions between waking blocked threads in mutexes with interrupts waking blocked threads in message queues can occur. Queue posts will put the threads on a separate list that is then added to the running list with IRQs disabled on the next task switch or CPU wakeup. Basically no overhead for other operations. Seems a likely cause of my occasional observation of the backlight fade causing playback threads to stop running and a recently reported blocking violation upon USB plugging. Time will tell but banging the backlight on and off frequently hasn't hiccuped again for me on H120.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12915 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/kernel.c')
-rw-r--r-- | firmware/kernel.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/firmware/kernel.c b/firmware/kernel.c index c5e47a81ff..e09edeff77 100644 --- a/firmware/kernel.c +++ b/firmware/kernel.c | |||
@@ -126,7 +126,7 @@ static void queue_release_sender(struct thread_entry **sender, | |||
126 | intptr_t retval) | 126 | intptr_t retval) |
127 | { | 127 | { |
128 | (*sender)->retval = retval; | 128 | (*sender)->retval = retval; |
129 | wakeup_thread(sender); | 129 | wakeup_thread_irq_safe(sender); |
130 | #if 0 | 130 | #if 0 |
131 | /* This should _never_ happen - there must never be multiple | 131 | /* This should _never_ happen - there must never be multiple |
132 | threads in this list and it is a corrupt state */ | 132 | threads in this list and it is a corrupt state */ |
@@ -289,11 +289,14 @@ void queue_post(struct event_queue *q, long id, intptr_t data) | |||
289 | } | 289 | } |
290 | #endif | 290 | #endif |
291 | 291 | ||
292 | wakeup_thread(&q->thread); | 292 | wakeup_thread_irq_safe(&q->thread); |
293 | set_irq_level(oldlevel); | 293 | set_irq_level(oldlevel); |
294 | } | 294 | } |
295 | 295 | ||
296 | #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME | 296 | #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME |
297 | /* No wakeup_thread_irq_safe here because IRQ handlers are not allowed | ||
298 | use of this function - we only aim to protect the queue integrity by | ||
299 | turning them off. */ | ||
297 | intptr_t queue_send(struct event_queue *q, long id, intptr_t data) | 300 | intptr_t queue_send(struct event_queue *q, long id, intptr_t data) |
298 | { | 301 | { |
299 | int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); | 302 | int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); |