summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Roitzsch <mroi@users.sourceforge.net>2003-12-24 13:06:10 +0000
committerMichael Roitzsch <mroi@users.sourceforge.net>2003-12-24 13:06:10 +0000
commit5df09f99f17cf51ae657331dec51277ea80965b8 (patch)
tree49a72fd4c09a338aa5e0c42cc73d515cf207eace
parent79f4997de5d05c1ed1e7f16cd5a73b4c537973b6 (diff)
downloadxine-lib-5df09f99f17cf51ae657331dec51277ea80965b8.tar.gz
xine-lib-5df09f99f17cf51ae657331dec51277ea80965b8.tar.bz2
thanks to Carsten Weinhold for finding and fixing this:
pthread locks are _not_ fair (shocking news for me), so audio out has a problem: the audio out loop holds the driver_lock almost always (since the write() to the driver takes most of the time); other threads who want that lock (like the frontend trying to change the volume) can starve; the problem shows on kernel 2.6 with NPTL, but the potential is there in all pthread implementations CVS patchset: 5938 CVS date: 2003/12/24 13:06:10
-rw-r--r--AUTHORS2
-rw-r--r--src/xine-engine/audio_out.c41
2 files changed, 40 insertions, 3 deletions
diff --git a/AUTHORS b/AUTHORS
index 46ef15a19..e0dad39e6 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -286,7 +286,7 @@ Giovanni Baronetti and Mauro Borghi <mauro.borghi@tilab.com>
Carsten Weinhold <news.cw@gmx.net>
patch to improve quality of linearblend filter, new AV sync
- method by resampling audio.
+ method by resampling audio, fixed pthread starvation in audio out
Claire Griffin <claire@comedia.com>
demux_ts fixes for ATSC streams
diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c
index 688709a4a..530a677c4 100644
--- a/src/xine-engine/audio_out.c
+++ b/src/xine-engine/audio_out.c
@@ -17,7 +17,7 @@
* along with self program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: audio_out.c,v 1.158 2003/12/12 01:44:40 f1rmb Exp $
+ * $Id: audio_out.c,v 1.159 2003/12/24 13:06:12 mroi Exp $
*
* 22-8-2001 James imported some useful AC3 sections from the previous alsa driver.
* (c) 2001 Andy Lo A Foe <andy@alsaplayer.org>
@@ -205,6 +205,9 @@ typedef struct {
ao_driver_t *driver;
pthread_mutex_t driver_lock;
int driver_open;
+ pthread_mutex_t driver_action_lock; /* protects num_driver_actions */
+ int num_driver_actions; /* number of threads, that wish to call
+ * functions needing driver_lock */
metronom_clock_t *clock;
xine_t *xine;
xine_list_t *streams;
@@ -1086,6 +1089,12 @@ static void *ao_loop (void *this_gen) {
fifo_append (this->free_fifo, in_buf);
in_buf = NULL;
}
+
+ /* Give other threads a chance to use functions which require this->driver_lock to
+ * be available. This is needed when using NPTL on Linux (and probably PThreads
+ * on Solaris as well). */
+ if (this->num_driver_actions > 0)
+ sched_yield();
}
if (in_buf)
@@ -1247,6 +1256,23 @@ static int ao_change_settings(aos_t *this, uint32_t bits, uint32_t rate, int mod
return this->output.rate;
}
+
+static inline void inc_num_driver_actions(aos_t *this) {
+
+ pthread_mutex_lock(&this->driver_action_lock);
+ this->num_driver_actions++;
+ pthread_mutex_unlock(&this->driver_action_lock);
+}
+
+
+static inline void dec_num_driver_actions(aos_t *this) {
+
+ pthread_mutex_lock(&this->driver_action_lock);
+ this->num_driver_actions--;
+ pthread_mutex_unlock(&this->driver_action_lock);
+}
+
+
/*
* open the audio device for writing to
*/
@@ -1416,6 +1442,7 @@ static void ao_exit(xine_audio_port_t *this_gen) {
}
pthread_mutex_destroy(&this->driver_lock);
+ pthread_mutex_destroy(&this->driver_action_lock);
pthread_mutex_destroy(&this->streams_lock);
xine_list_free(this->streams);
@@ -1481,7 +1508,9 @@ static uint32_t ao_get_capabilities (xine_audio_port_t *this_gen) {
| AO_CAP_MODE_5_1CHANNEL | AO_CAP_8BITS;
*/
} else {
+ inc_num_driver_actions(this);
pthread_mutex_lock( &this->driver_lock );
+ dec_num_driver_actions(this);
result=this->driver->get_capabilities(this->driver);
pthread_mutex_unlock( &this->driver_lock );
}
@@ -1523,7 +1552,9 @@ static int ao_get_property (xine_audio_port_t *this_gen, int property) {
break;
default:
+ inc_num_driver_actions(this);
pthread_mutex_lock( &this->driver_lock );
+ dec_num_driver_actions(this);
ret = this->driver->get_property(this->driver, property);
pthread_mutex_unlock( &this->driver_lock );
}
@@ -1616,7 +1647,9 @@ static int ao_set_property (xine_audio_port_t *this_gen, int property, int value
break;
case AO_PROP_CLOSE_DEVICE:
+ inc_num_driver_actions(this);
pthread_mutex_lock( &this->driver_lock );
+ dec_num_driver_actions(this);
if(this->driver_open)
this->driver->close(this->driver);
this->driver_open = 0;
@@ -1643,7 +1676,9 @@ static int ao_control (xine_audio_port_t *this_gen, int cmd, ...) {
if (this->grab_only)
return 0;
+ inc_num_driver_actions(this);
pthread_mutex_lock( &this->driver_lock );
+ dec_num_driver_actions(this);
if(this->driver_open) {
va_start(args, cmd);
arg = va_arg(args, void*);
@@ -1758,6 +1793,7 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver,
pthread_mutex_init( &this->streams_lock, NULL );
pthread_mutex_init( &this->driver_lock, NULL );
+ pthread_mutex_init( &this->driver_action_lock, NULL );
this->ao.open = ao_open;
this->ao.get_buffer = ao_get_buffer;
@@ -1770,7 +1806,8 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver,
this->ao.control = ao_control;
this->ao.flush = ao_flush;
this->ao.status = ao_status;
-
+
+ this->num_driver_actions = 0;
this->audio_loop_running = 0;
this->grab_only = grab_only;
this->audio_paused = 0;