notify: protect notify->pending with the mutex

There was a known deadlocking bug in the notify library: when the
other thread set notify->pending after the according check in
notify_wait(), the latter thread was deadlocked.  Resolve this by
synchronizing all accesses to notify->pending with the notify object's
mutex.  Since notify_signal_sync() was never used, we can remove it.
As a consequence, we don't need notify_enter() and notify_leave()
anymore; eliminate them, too.
This commit is contained in:
Max Kellermann 2008-09-26 09:57:11 +02:00
parent 323e86489f
commit 58554e14f9
6 changed files with 4 additions and 41 deletions

View File

@ -167,8 +167,6 @@ stop_no_close:
static void * decoder_task(mpd_unused void *arg) static void * decoder_task(mpd_unused void *arg)
{ {
notify_enter(&dc.notify);
while (1) { while (1) {
assert(dc.state == DECODE_STATE_STOP); assert(dc.state == DECODE_STATE_STOP);

View File

@ -115,8 +115,6 @@ void wait_main_task(void)
{ {
assert(pthread_equal(main_task, pthread_self())); assert(pthread_equal(main_task, pthread_self()));
notify_enter(&main_notify);
notify_wait(&main_notify); notify_wait(&main_notify);
notify_leave(&main_notify);
} }

View File

@ -40,32 +40,20 @@ void notify_deinit(struct notify *notify)
pthread_cond_destroy(&notify->cond); pthread_cond_destroy(&notify->cond);
} }
void notify_enter(struct notify *notify)
{
pthread_mutex_lock(&notify->mutex);
}
void notify_leave(struct notify *notify)
{
pthread_mutex_unlock(&notify->mutex);
}
void notify_wait(struct notify *notify) void notify_wait(struct notify *notify)
{ {
pthread_mutex_lock(&notify->mutex);
if (!notify->pending) if (!notify->pending)
pthread_cond_wait(&notify->cond, &notify->mutex); pthread_cond_wait(&notify->cond, &notify->mutex);
assert(notify->pending);
notify->pending = 0; notify->pending = 0;
pthread_mutex_unlock(&notify->mutex);
} }
void notify_signal(struct notify *notify) void notify_signal(struct notify *notify)
{ {
pthread_mutex_lock(&notify->mutex);
notify->pending = 1; notify->pending = 1;
pthread_cond_signal(&notify->cond); pthread_cond_signal(&notify->cond);
}
void notify_signal_sync(struct notify *notify)
{
pthread_mutex_lock(&notify->mutex);
notify_signal(notify);
pthread_mutex_unlock(&notify->mutex); pthread_mutex_unlock(&notify->mutex);
} }

View File

@ -36,17 +36,6 @@ void notify_init(struct notify *notify);
void notify_deinit(struct notify *notify); void notify_deinit(struct notify *notify);
/**
* The thread which shall be notified by this object must call this
* function before any notify_wait() invocation. It locks the mutex.
*/
void notify_enter(struct notify *notify);
/**
* Neutralize notify_leave().
*/
void notify_leave(struct notify *notify);
/** /**
* Wait for a notification. Return immediately if we have already * Wait for a notification. Return immediately if we have already
* been notified since we last returned from notify_wait(). * been notified since we last returned from notify_wait().
@ -58,10 +47,4 @@ void notify_wait(struct notify *notify);
*/ */
void notify_signal(struct notify *notify); void notify_signal(struct notify *notify);
/**
* Notify the thread synchonously, i.e. wait until it has received the
* notification.
*/
void notify_signal_sync(struct notify *notify);
#endif #endif

View File

@ -67,8 +67,6 @@ static void *audio_output_task(void *arg)
{ {
struct audio_output *ao = arg; struct audio_output *ao = arg;
notify_enter(&ao->notify);
while (1) { while (1) {
switch (ao->command) { switch (ao->command) {
case AO_COMMAND_NONE: case AO_COMMAND_NONE:

View File

@ -384,8 +384,6 @@ static void do_play(void)
static void * player_task(mpd_unused void *arg) static void * player_task(mpd_unused void *arg)
{ {
notify_enter(&pc.notify);
while (1) { while (1) {
switch (pc.command) { switch (pc.command) {
case PLAYER_COMMAND_PLAY: case PLAYER_COMMAND_PLAY: