diff options
-rw-r--r-- | firmware/kernel.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/firmware/kernel.c b/firmware/kernel.c index cddaf41656..192728bdb2 100644 --- a/firmware/kernel.c +++ b/firmware/kernel.c | |||
@@ -100,6 +100,7 @@ void yield(void) | |||
100 | static void queue_fetch_sender(struct queue_sender_list *send, | 100 | static void queue_fetch_sender(struct queue_sender_list *send, |
101 | unsigned int i) | 101 | unsigned int i) |
102 | { | 102 | { |
103 | /* Disable interrupts to protect against collision in this slot */ | ||
103 | int old_level = set_irq_level(HIGHEST_IRQ_LEVEL); | 104 | int old_level = set_irq_level(HIGHEST_IRQ_LEVEL); |
104 | struct thread_entry **spp = &send->senders[i]; | 105 | struct thread_entry **spp = &send->senders[i]; |
105 | 106 | ||
@@ -113,17 +114,31 @@ static void queue_fetch_sender(struct queue_sender_list *send, | |||
113 | } | 114 | } |
114 | 115 | ||
115 | /* Puts the specified return value in the waiting thread's return value | 116 | /* Puts the specified return value in the waiting thread's return value |
116 | and wakes the thread - a sender should be confirmed to exist first */ | 117 | * and wakes the thread. |
118 | * 1) A sender should be confirmed to exist before calling which makes it | ||
119 | * more efficent to reject the majority of cases that don't need this | ||
120 | called. | ||
121 | * 2) Requires interrupts disabled since queue overflows can cause posts | ||
122 | * from interrupt handlers to wake threads. Not doing so could cause | ||
123 | * an attempt at multiple wakes or other problems. | ||
124 | */ | ||
117 | static void queue_release_sender(struct thread_entry **sender, | 125 | static void queue_release_sender(struct thread_entry **sender, |
118 | intptr_t retval) | 126 | intptr_t retval) |
119 | { | 127 | { |
120 | (*sender)->retval = retval; | 128 | (*sender)->retval = retval; |
121 | wakeup_thread(sender); | 129 | wakeup_thread(sender); |
122 | *sender = NULL; | 130 | #if 0 |
131 | /* This should _never_ happen - there must never be multiple | ||
132 | threads in this list and it is a corrupt state */ | ||
133 | if (*sender != NULL) | ||
134 | panicf("Queue: send slot ovf"); | ||
135 | #endif | ||
123 | } | 136 | } |
124 | 137 | ||
125 | /* Releases any waiting threads that are queued with queue_send - | 138 | /* Releases any waiting threads that are queued with queue_send - |
126 | reply with NULL */ | 139 | * reply with 0. |
140 | * Disable IRQs before calling since it uses queue_release_sender. | ||
141 | */ | ||
127 | static void queue_release_all_senders(struct event_queue *q) | 142 | static void queue_release_all_senders(struct event_queue *q) |
128 | { | 143 | { |
129 | if(q->send) | 144 | if(q->send) |
@@ -191,8 +206,10 @@ void queue_delete(struct event_queue *q) | |||
191 | #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME | 206 | #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME |
192 | /* Release waiting threads and reply to any dequeued message | 207 | /* Release waiting threads and reply to any dequeued message |
193 | waiting for one. */ | 208 | waiting for one. */ |
209 | int level = set_irq_level(HIGHEST_IRQ_LEVEL); | ||
194 | queue_release_all_senders(q); | 210 | queue_release_all_senders(q); |
195 | queue_reply(q, NULL); | 211 | queue_reply(q, NULL); |
212 | set_irq_level(level); | ||
196 | #endif | 213 | #endif |
197 | /* Move the following queues up in the list */ | 214 | /* Move the following queues up in the list */ |
198 | for(;i < num_queues-1;i++) | 215 | for(;i < num_queues-1;i++) |
@@ -319,7 +336,12 @@ void queue_reply(struct event_queue *q, intptr_t retval) | |||
319 | { | 336 | { |
320 | if(q->send && q->send->curr_sender) | 337 | if(q->send && q->send->curr_sender) |
321 | { | 338 | { |
322 | queue_release_sender(&q->send->curr_sender, retval); | 339 | int level = set_irq_level(HIGHEST_IRQ_LEVEL); |
340 | if(q->send->curr_sender) | ||
341 | { | ||
342 | queue_release_sender(&q->send->curr_sender, retval); | ||
343 | } | ||
344 | set_irq_level(level); | ||
323 | } | 345 | } |
324 | } | 346 | } |
325 | #endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */ | 347 | #endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */ |