From b322f09ab8ea89f5c78aede7a2f524025be62a42 Mon Sep 17 00:00:00 2001 From: Mikael Djurfeldt Date: Thu, 19 Nov 1998 08:15:22 +0000 Subject: [PATCH] * coop.c (coop_condition_variable_wait): Removed (coop_condition_variable_wait_mutex): Folded logic of coop_mutex_unlock into coop_condition_variable_wait_mutex to prevent condvar signal lossage. Previously, another thread could start to run after unlocking the mutex but before putting the current thread on the wait queue. If that thread then would signal the first, the signal would be lost. (Thanks to Christian Lynbech.) --- THANKS | 1 + libguile/ChangeLog | 14 ++++++++++++ libguile/coop.c | 55 +++++++++++++++++++++++----------------------- 3 files changed, 42 insertions(+), 28 deletions(-) diff --git a/THANKS b/THANKS index 6737f3353..5fa4680b1 100644 --- a/THANKS +++ b/THANKS @@ -4,6 +4,7 @@ Bug reports and fixes from: Etienne Bernard Brad Bowman + Ian Grant Christian Lynbech Russ McManus Nicolas Neuss diff --git a/libguile/ChangeLog b/libguile/ChangeLog index 9d2922ce5..96bd81cae 100644 --- a/libguile/ChangeLog +++ b/libguile/ChangeLog @@ -1,3 +1,17 @@ +1998-11-19 Mikael Djurfeldt + + * readline.c (scm_init_readline): Set + rl_basic_word_break_characters. (Thanks to Ian Grant.) + + * coop.c (coop_condition_variable_wait): Removed + (coop_condition_variable_wait_mutex): Folded logic of + coop_mutex_unlock into coop_condition_variable_wait_mutex to + prevent condvar signal lossage. Previously, another thread could + start to run after unlocking the mutex but before putting the + current thread on the wait queue. If that thread then would + signal the first, the signal would be lost. (Thanks to Christian + Lynbech.) + 1998-11-17 Mikael Djurfeldt * eval.c (SCM_CEVAL): Added missing case for cclo. (Thanks to diff --git a/libguile/coop.c b/libguile/coop.c index d69f32133..832df6e21 100644 --- a/libguile/coop.c +++ b/libguile/coop.c @@ -40,7 +40,7 @@ * If you do not wish that, delete this exception notice. */ -/* $Id: coop.c,v 1.14 1998-10-13 23:17:09 jimb Exp $ */ +/* $Id: coop.c,v 1.15 1998-11-19 08:15:22 mdj Exp $ */ /* Cooperative thread library, based on QuickThreads */ @@ -333,6 +333,8 @@ coop_mutex_unlock (m) old = coop_global_curr; coop_global_curr = newthread; + /* The new thread came into m->waiting through a lock operation. + It now owns this mutex. */ m->owner = coop_global_curr; QT_BLOCK (coop_yieldhelp, old, &coop_global_runq, newthread->sp); } @@ -370,31 +372,6 @@ coop_condition_variable_init (c) return 0; } -#ifdef __STDC__ -static int -coop_condition_variable_wait (coop_c *c) -#else -static int -coop_condition_variable_wait (c) - coop_c *c; -#endif -{ - coop_t *old, *newthread; - -#ifdef GUILE_ISELECT - newthread = coop_wait_for_runnable_thread(); - if (newthread == coop_global_curr) - coop_abort (); -#else - newthread = coop_next_runnable_thread(); -#endif - old = coop_global_curr; - coop_global_curr = newthread; - QT_BLOCK (coop_yieldhelp, old, &(c->waiting), newthread->sp); - return 0; -} - - #ifdef __STDC__ int coop_condition_variable_wait_mutex (coop_c *c, coop_m *m) @@ -405,8 +382,30 @@ coop_condition_variable_wait_mutex (c, m) coop_m *m; #endif { - coop_mutex_unlock (m); - coop_condition_variable_wait (c); + coop_t *old, *newthread; + + /* coop_mutex_unlock (m); */ + newthread = coop_qget (&(m->waiting)); + if (newthread != NULL) + { + m->owner = newthread; + } + else + { + m->owner = NULL; +#ifdef GUILE_ISELECT + newthread = coop_wait_for_runnable_thread(); + if (newthread == coop_global_curr) + coop_abort (); +#else + newthread = coop_next_runnable_thread(); +#endif + } + coop_global_curr->top = &old; + old = coop_global_curr; + coop_global_curr = newthread; + QT_BLOCK (coop_yieldhelp, old, &(c->waiting), newthread->sp); + coop_mutex_lock (m); return 0; }