Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Collins <rbtcollins@hotmail.com>2001-12-26 15:46:26 +0300
committerRobert Collins <rbtcollins@hotmail.com>2001-12-26 15:46:26 +0300
commitcbce49804fb7826fa532e0e4ddc2436fa3374a2b (patch)
tree2096127d6f9a722d57764b32982a2354714100fa /winsup/cygwin/thread.cc
parent7a0252e203269091e183a83a98aa1d5b63d46984 (diff)
2001-12-26 Robert Collins <rbtcollins@hotmail.com>
* thread.cc (pthread_cond::Signal): Use a separate flag for signal detection and broadcast semantics. (__pthread_cond_dowait): Ditto. * thread.h (pthread_cond): New flag for testing when a waiter has woken.
Diffstat (limited to 'winsup/cygwin/thread.cc')
-rw-r--r--winsup/cygwin/thread.cc23
1 files changed, 19 insertions, 4 deletions
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index 8ca4820e8..ced5f6f80 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -499,24 +499,37 @@ pthread_cond::Signal ()
system_printf ("Failed to unlock condition variable access mutex, this %p", this);
return;
}
+ /* Prime the detection flag */
+ ExitingWait = 1;
+ /* Signal any waiting thread */
PulseEvent (win32_obj_id);
/* No one can start waiting until we release the condition access mutex */
/* The released thread will decrement waiting when it gets a time slice...
without waiting for the access mutex
+ * InterLockedIncrement on 98 +, NT4 + returns the incremented value.
+ * On 95, nt 3.51 < it returns a sign correct number - 0=0, + for greater than 0, -
+ * for less than 0.
+ * Because of this we cannot spin on the waiting count, but rather we need a
+ * dedicated flag for a thread exiting the Wait function.
+ * Also not that Interlocked* sync CPU caches with memory.
*/
int spins = 10;
- while (InterlockedIncrement (&waiting) != (temp - 1) && spins)
+ /* When ExitingWait is nonzero after a decrement, the leaving thread has
+ * done it's thing
+ */
+ while (InterlockedDecrement (&ExitingWait) == 0 && spins)
{
- InterlockedDecrement (&waiting);
+ InterlockedIncrement (&ExitingWait);
/* give up the cpu to force a context switch. */
Sleep (0);
if (spins == 5)
- /* we've had 5 timeslices, and the woekn thread still hasn't done it's
+ /* we've had 5 timeslices, and the woken thread still hasn't done it's
* thing - maybe we raced it with the event? */
PulseEvent (win32_obj_id);
spins--;
}
- InterlockedDecrement (&waiting);
+ if (waiting + 1 != temp)
+ system_printf ("Released too many threads - %d now %d originally", waiting, temp);
if (pthread_mutex_unlock (&cond_access))
system_printf ("Failed to unlock condition variable access mutex, this %p", this);
}
@@ -1782,6 +1795,8 @@ __pthread_cond_dowait (pthread_cond_t *cond, pthread_mutex_t *mutex,
bool last = false;
if (InterlockedDecrement (&((*cond)->waiting)) == 0)
last = true;
+ /* Tell Signal that we have been released */
+ InterlockedDecrement (&((*cond)->ExitingWait));
(*themutex)->Lock ();
if (last == true)
(*cond)->mutex = NULL;