diff options
author | Matthias Kretz <kretz@kde.org> | 2007-12-03 16:47:53 +0100 |
---|---|---|
committer | Matthias Kretz <kretz@kde.org> | 2007-12-03 16:47:53 +0100 |
commit | b312cde90d985df949beac9708476af28bc82113 (patch) | |
tree | 674ed617f5da1db44b8db8b201320449302aadae | |
parent | 948b8dd9bfc33de61ff8c8bacf32eae53aa3b528 (diff) | |
download | xine-lib-b312cde90d985df949beac9708476af28bc82113.tar.gz xine-lib-b312cde90d985df949beac9708476af28bc82113.tar.bz2 |
Fixed a race condition between ao_loop and ao_close to not lose the last buffer.
In ao_loop only read the first buffer and remove it from the fifo only when the
buffer has been written or is about to be discarded. This fixes the race between
ao_loop and ao_close for good. Now fifo_remove_int may signal empty again right
after removing the last buffer from the fifo.
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | src/xine-engine/audio_out.c | 27 |
2 files changed, 24 insertions, 5 deletions
@@ -20,6 +20,8 @@ xine-lib (1.1.9) (unreleased) wakeups/s). * Fixed ALSA close function to not discard all data that had been written but not played yet. + * Fixed a race condition between ao_loop and ao_close to not lose the last + buffer. xine-lib (1.1.8) * Send a channel-changed event to the frontend when receiving the SYNC diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index de74ac578..7519c3067 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -338,9 +338,7 @@ static void fifo_append (audio_fifo_t *fifo, pthread_mutex_unlock (&fifo->mutex); } -static audio_buffer_t *fifo_remove_int (audio_fifo_t *fifo, int blocking) { - audio_buffer_t *buf; - +static audio_buffer_t *fifo_peek_int (audio_fifo_t *fifo, int blocking) { while (!fifo->first) { pthread_cond_signal (&fifo->empty); if (blocking) @@ -355,8 +353,11 @@ static audio_buffer_t *fifo_remove_int (audio_fifo_t *fifo, int blocking) { return NULL; } } + return fifo->first; +} - buf = fifo->first; +static audio_buffer_t *fifo_remove_int (audio_fifo_t *fifo, int blocking) { + audio_buffer_t *buf = fifo_peek_int(fifo, blocking); fifo->first = buf->next; @@ -364,6 +365,7 @@ static audio_buffer_t *fifo_remove_int (audio_fifo_t *fifo, int blocking) { fifo->last = NULL; fifo->num_buffers = 0; + pthread_cond_signal (&fifo->empty); } else fifo->num_buffers--; @@ -373,6 +375,17 @@ static audio_buffer_t *fifo_remove_int (audio_fifo_t *fifo, int blocking) { return buf; } +static audio_buffer_t *fifo_peek (audio_fifo_t *fifo) { + + audio_buffer_t *buf; + + pthread_mutex_lock (&fifo->mutex); + buf = fifo_peek_int(fifo, 1); + pthread_mutex_unlock (&fifo->mutex); + + return buf; +} + static audio_buffer_t *fifo_remove (audio_fifo_t *fifo) { audio_buffer_t *buf; @@ -994,7 +1007,7 @@ static void *ao_loop (void *this_gen) { if (!in_buf) { lprintf ("loop: get buf from fifo\n"); - in_buf = fifo_remove (this->out_fifo); + in_buf = fifo_peek (this->out_fifo); bufs_since_sync++; lprintf ("got a buffer\n"); } @@ -1007,6 +1020,7 @@ static void *ao_loop (void *this_gen) { } if (this->discard_buffers) { + fifo_remove (this->out_fifo); if (in_buf->stream) _x_refcounter_dec(in_buf->stream->refcounter); fifo_append (this->free_fifo, in_buf); @@ -1033,6 +1047,7 @@ static void *ao_loop (void *this_gen) { cur_time = this->clock->get_current_time (this->clock); if (in_buf->vpts < cur_time ) { lprintf ("loop: next fifo\n"); + fifo_remove (this->out_fifo); if (in_buf->stream) _x_refcounter_dec(in_buf->stream->refcounter); fifo_append (this->free_fifo, in_buf); @@ -1157,6 +1172,7 @@ static void *ao_loop (void *this_gen) { /* drop package */ lprintf ("loop: drop package, next fifo\n"); + fifo_remove (this->out_fifo); if (in_buf->stream) _x_refcounter_dec(in_buf->stream->refcounter); fifo_append (this->free_fifo, in_buf); @@ -1223,6 +1239,7 @@ static void *ao_loop (void *this_gen) { } else { result = 0; } + fifo_remove (this->out_fifo); if( result < 0 ) { /* device unplugged. */ |