From 1839edf64ad0a4b6d96a5dd5ce24ab8075954dc6 Mon Sep 17 00:00:00 2001 From: Nicolas Pennequin Date: Sat, 27 Oct 2007 18:08:18 +0000 Subject: Add queue_peek to the kernel (written by Mike Sevakis), and use it to improve upon my previous commit. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15336 a1c6a512-1295-4272-9138-f99709370657 --- apps/playback.c | 12 +++++++++--- firmware/export/kernel.h | 1 + firmware/kernel.c | 22 ++++++++++++++++++++++ uisimulator/sdl/kernel.c | 20 ++++++++++++++++++++ 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/apps/playback.c b/apps/playback.c index 2ac54e7d74..3c1dd37d3f 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -2569,6 +2569,7 @@ static void low_buffer_callback(void) static void audio_fill_file_buffer(bool start_play, size_t offset) { + struct queue_event ev; bool had_next_track = audio_next_track() != NULL; bool continue_buffering; @@ -2591,9 +2592,14 @@ static void audio_fill_file_buffer(bool start_play, size_t offset) start_play = false; offset = 0; sleep(1); - if (!queue_empty(&audio_queue)) { - /* There's a message in the queue. break the loop to treat it, - and go back to filling after that. */ + if (queue_peek(&audio_queue, &ev)) { + if (ev.id != Q_AUDIO_FILL_BUFFER) + { + /* There's a message in the queue. break the loop to treat it, + and go back to filling after that. */ + LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER"); + queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0); + } break; } } while (continue_buffering); diff --git a/firmware/export/kernel.h b/firmware/export/kernel.h index a72e004b33..041f846380 100644 --- a/firmware/export/kernel.h +++ b/firmware/export/kernel.h @@ -219,6 +219,7 @@ extern void queue_reply(struct event_queue *q, intptr_t retval); extern bool queue_in_queue_send(struct event_queue *q); #endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */ extern bool queue_empty(const struct event_queue* q); +extern bool queue_peek(struct event_queue *q, struct queue_event *ev); extern void queue_clear(struct event_queue* q); extern void queue_remove_from_head(struct event_queue *q, long id); extern int queue_count(const struct event_queue *q); diff --git a/firmware/kernel.c b/firmware/kernel.c index 006a06dfe0..25249c6148 100644 --- a/firmware/kernel.c +++ b/firmware/kernel.c @@ -537,6 +537,28 @@ bool queue_empty(const struct event_queue* q) return ( q->read == q->write ); } +bool queue_peek(struct event_queue *q, struct queue_event *ev) +{ + if (q->read == q->write) + return false; + + bool have_msg = false; + + int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); + corelock_lock(&q->cl); + + if (q->read != q->write) + { + *ev = q->events[q->read & QUEUE_LENGTH_MASK]; + have_msg = true; + } + + corelock_unlock(&q->cl); + set_irq_level(oldlevel); + + return have_msg; +} + void queue_clear(struct event_queue* q) { int oldlevel; diff --git a/uisimulator/sdl/kernel.c b/uisimulator/sdl/kernel.c index 96654d50ac..220d069721 100644 --- a/uisimulator/sdl/kernel.c +++ b/uisimulator/sdl/kernel.c @@ -405,6 +405,26 @@ bool queue_empty(const struct event_queue* q) return ( q->read == q->write ); } +bool queue_peek(struct event_queue *q, struct queue_event *ev) +{ + if (q->read == q->write) + return false; + + bool have_msg = false; + + int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); + + if (q->read != q->write) + { + *ev = q->events[q->read & QUEUE_LENGTH_MASK]; + have_msg = true; + } + + set_irq_level(oldlevel); + + return have_msg; +} + void queue_clear(struct event_queue* q) { int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); -- cgit