summaryrefslogtreecommitdiff
path: root/firmware/kernel.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-03-26 03:24:36 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-03-26 03:24:36 +0000
commit165f62d0cd771660e4b8d2ba7475e14d0d6f2e9f (patch)
tree2818158a5c6f250dc928319d7cc6c91788519b78 /firmware/kernel.c
parent5e2984ad80a732f39b8d0df130176e67b30b9469 (diff)
downloadrockbox-165f62d0cd771660e4b8d2ba7475e14d0d6f2e9f.zip
rockbox-165f62d0cd771660e4b8d2ba7475e14d0d6f2e9f.tar.gz
rockbox-165f62d0cd771660e4b8d2ba7475e14d0d6f2e9f.tar.bz2
rockbox-165f62d0cd771660e4b8d2ba7475e14d0d6f2e9f.tar.xz
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.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/firmware/kernel.c b/firmware/kernel.c
index c5e47a8..e09edef 100644
--- a/firmware/kernel.c
+++ b/firmware/kernel.c
@@ -126,7 +126,7 @@ static void queue_release_sender(struct thread_entry **sender,
intptr_t retval)
{
(*sender)->retval = retval;
- wakeup_thread(sender);
+ wakeup_thread_irq_safe(sender);
#if 0
/* This should _never_ happen - there must never be multiple
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)
}
#endif
- wakeup_thread(&q->thread);
+ wakeup_thread_irq_safe(&q->thread);
set_irq_level(oldlevel);
}
#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
+/* No wakeup_thread_irq_safe here because IRQ handlers are not allowed
+ use of this function - we only aim to protect the queue integrity by
+ turning them off. */
intptr_t queue_send(struct event_queue *q, long id, intptr_t data)
{
int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);