1
0
Fork 0
forked from len0rd/rockbox

In reponse to a report of a blocking violation, give sync queues a going over and catch any old, obscure leftover issues. A couple spots needed interrupt stopage where there could be confict if an IRQ post wakes a waiting thread because the queue is overflowing. There does appear to be an issue with wakeup_thread, interrupts and running list modification in general.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12895 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sevakis 2007-03-23 01:00:13 +00:00
parent 8b40769554
commit 6d87513aa2

View file

@ -100,6 +100,7 @@ void yield(void)
static void queue_fetch_sender(struct queue_sender_list *send,
unsigned int i)
{
/* Disable interrupts to protect against collision in this slot */
int old_level = set_irq_level(HIGHEST_IRQ_LEVEL);
struct thread_entry **spp = &send->senders[i];
@ -113,17 +114,31 @@ static void queue_fetch_sender(struct queue_sender_list *send,
}
/* Puts the specified return value in the waiting thread's return value
and wakes the thread - a sender should be confirmed to exist first */
* and wakes the thread.
* 1) A sender should be confirmed to exist before calling which makes it
* more efficent to reject the majority of cases that don't need this
called.
* 2) Requires interrupts disabled since queue overflows can cause posts
* from interrupt handlers to wake threads. Not doing so could cause
* an attempt at multiple wakes or other problems.
*/
static void queue_release_sender(struct thread_entry **sender,
intptr_t retval)
{
(*sender)->retval = retval;
wakeup_thread(sender);
*sender = NULL;
#if 0
/* This should _never_ happen - there must never be multiple
threads in this list and it is a corrupt state */
if (*sender != NULL)
panicf("Queue: send slot ovf");
#endif
}
/* Releases any waiting threads that are queued with queue_send -
reply with NULL */
* reply with 0.
* Disable IRQs before calling since it uses queue_release_sender.
*/
static void queue_release_all_senders(struct event_queue *q)
{
if(q->send)
@ -191,8 +206,10 @@ void queue_delete(struct event_queue *q)
#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
/* Release waiting threads and reply to any dequeued message
waiting for one. */
int level = set_irq_level(HIGHEST_IRQ_LEVEL);
queue_release_all_senders(q);
queue_reply(q, NULL);
set_irq_level(level);
#endif
/* Move the following queues up in the list */
for(;i < num_queues-1;i++)
@ -318,9 +335,14 @@ bool queue_in_queue_send(struct event_queue *q)
void queue_reply(struct event_queue *q, intptr_t retval)
{
if(q->send && q->send->curr_sender)
{
int level = set_irq_level(HIGHEST_IRQ_LEVEL);
if(q->send->curr_sender)
{
queue_release_sender(&q->send->curr_sender, retval);
}
set_irq_level(level);
}
}
#endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */