[project @ 2005-10-21 14:02:17 by simonmar]
[ghc-hetmet.git] / ghc / rts / win32 / AwaitEvent.c
1 /*
2  * Wait/check for external events. Periodically, the
3  * Scheduler checks for the completion of external operations,
4  * like the expiration of timers, completion of I/O requests
5  * issued by Haskell threads.
6  *
7  * If the Scheduler is otherwise out of work, it'll block
8  * herein waiting for external events to occur.
9  *
10  * This file mirrors the select()-based functionality 
11  * for POSIX / Unix platforms in rts/Select.c, but for
12  * Win32.
13  *
14  */
15 #include "Rts.h"
16 #include "Schedule.h"
17 #include <windows.h>
18 #include "win32/AsyncIO.h"
19 #if defined(THREADED_RTS)
20 #include "Capability.h"
21 #endif
22
23 // Used to avoid calling abandonRequestWait() if we don't need to.
24 // Protected by sched_mutex.
25 static nat workerWaitingForRequests = 0;
26
27 void
28 awaitEvent(rtsBool wait)
29 {
30   int ret;
31
32 #ifdef THREADED_RTS
33   // Small optimisation: we don't want the waiting thread to wake
34   // up straight away just because a previous returning worker has
35   // called abandonRequestWait().  If the event is no longer needed,
36   // reset it.  We must do this inside the sched_mutex.
37   if (!needToYieldToReturningWorker()) {
38       resetAbandonRequestWait();
39   }
40 #endif
41
42   do {
43     /* Try to de-queue completed IO requests
44      */
45     workerWaitingForRequests = 1;
46     RELEASE_LOCK(&sched_mutex);
47     ret = awaitRequests(wait);
48     ACQUIRE_LOCK(&sched_mutex);
49     workerWaitingForRequests = 0;
50     if (!ret) { 
51       return; /* still hold the lock */
52     }
53
54     // Return to the scheduler if:
55     //
56     //  - we were interrupted
57     //  - new threads have arrived
58     //  - another worker wants to take over (THREADED_RTS)
59
60   } while (wait
61            && !interrupted
62            && run_queue_hd == END_TSO_QUEUE
63 #ifdef THREADED_RTS
64            && !needToYieldToReturningWorker()
65 #endif
66       );
67 }
68
69 #ifdef THREADED_RTS
70 void
71 wakeBlockedWorkerThread()
72 {
73     if (workerWaitingForRequests) {
74         abandonRequestWait();
75     }
76 }
77 #endif