From 50ebfb020a18f2fa05129ee2e2c5a7752b10b141 Mon Sep 17 00:00:00 2001 From: simonmar Date: Thu, 18 Dec 2003 13:27:27 +0000 Subject: [PATCH] [project @ 2003-12-18 13:27:27 by simonmar] Fix some threaded RTS bugs: - in awaitRequests(), it was possible to return immediately even though wait was set to rtsTrue. This lead to a busy wait loop, so I've disabled that case (see code for details). - using PulseEvent in abandonRequestWait() wasn't the right thing, because it exposed a race condition. Again, see the comment in the code for details. --- ghc/rts/win32/AsyncIO.c | 32 +++++++++++++++++++++++++++----- ghc/rts/win32/AsyncIO.h | 1 + 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/ghc/rts/win32/AsyncIO.c b/ghc/rts/win32/AsyncIO.c index fabe85b..257a2be 100644 --- a/ghc/rts/win32/AsyncIO.c +++ b/ghc/rts/win32/AsyncIO.c @@ -9,6 +9,7 @@ #include #include #include "Schedule.h" +#include "Capability.h" #include "win32/AsyncIO.h" #include "win32/IOManager.h" @@ -182,8 +183,13 @@ start: #endif EnterCriticalSection(&queue_lock); /* Nothing immediately available & we won't wait */ - if ((!wait && completed_hw == 0) || - (issued_reqs == 0 && completed_hw == 0)) { + if ((!wait && completed_hw == 0) +#if 0 + // If we just return when wait==rtsFalse, we'll go into a busy + // wait loop, so I disabled this condition --SDM 18/12/2003 + (issued_reqs == 0 && completed_hw == 0) +#endif + ) { LeaveCriticalSection(&queue_lock); return 0; } @@ -203,7 +209,7 @@ start: return 0; } } else { - return 0; /* cannot happen */ + return 0; } goto start; } else { @@ -277,11 +283,27 @@ start: * to complete (via awaitRequests().) */ void -abandonRequestWait() +abandonRequestWait( void ) { /* the event is auto-reset, but in case there's no thread * already waiting on the event, we want to return it to * a non-signalled state. + * + * Careful! There is no synchronisation between + * abandonRequestWait and awaitRequest, which means that + * abandonRequestWait might be called just before a thread + * goes into a wait, and we miss the abandon signal. So we + * must SetEvent() here rather than PulseEvent() to ensure + * that the event isn't lost. We can re-optimise by resetting + * the event somewhere safe if we know the event has been + * properly serviced (see resetAbandon() below). --SDM 18/12/2003 */ - PulseEvent(abandon_req_wait); + SetEvent(abandon_req_wait); +} + +void +resetAbandonRequestWait( void ) +{ + ResetEvent(abandon_req_wait); } + diff --git a/ghc/rts/win32/AsyncIO.h b/ghc/rts/win32/AsyncIO.h index 00581c5..2077ea0 100644 --- a/ghc/rts/win32/AsyncIO.h +++ b/ghc/rts/win32/AsyncIO.h @@ -20,5 +20,6 @@ extern void shutdownAsyncIO(void); extern int awaitRequests(rtsBool wait); extern void abandonRequestWait(void); +extern void resetAbandonRequestWait(void); #endif /* __ASYNCHIO_H__ */ -- 1.7.10.4