/* Scan the even queue from head to tail, returning any event from the message list that was found, optionally removing the event. Returns true if an event was found, false otherwise. */ bool queue_peek_ex(struct event_queue *q, struct queue_event *ev, bool remove, long id_list[], unsigned int id_list_length) { bool have_msg; unsigned int rd, wr; int oldlevel; if(LIKELY(q->read == q->write)) return false; have_msg = false; oldlevel = disable_irq_save(); corelock_lock(&q->cl); rd = q->read; wr = q->write; /* Find first instance of message(s) starting at head */ for(; rd != wr; rd++) { /* Remember the event at rd */ struct queue_event e = q->events[rd & QUEUE_LENGTH_MASK]; unsigned int i = id_list_length; while(i-- > 0) { if(LIKELY(id_list[i] != e.id)) continue; /* An event from the list exists */ have_msg = true; *ev = e; if(!remove) goto peek_complete; /* Do event removal */ i = q->read; q->read = i + 1; /* Auto-reply */ queue_do_auto_reply(q->send); /* Get the thread waiting for reply, if any */ queue_do_fetch_sender(q->send, rd & QUEUE_LENGTH_MASK); /* Slide messages forward into the gap if not at the head */ while (rd != i) { unsigned int dst = rd & QUEUE_LENGTH_MASK; unsigned int src = --rd & QUEUE_LENGTH_MASK; q->events[dst] = q->events[src]; #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME /* Keep sender wait list in sync */ if(q->send) q->send.senders[dst] = q->send.senders[src]; #endif } goto peek_complete; } } peek_complete: corelock_unlock(&q->cl); restore_irq(oldlevel); return have_msg; }