[project @ 2003-12-18 13:29:23 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(RTS_SUPPORTS_THREADS)
20 #include "Capability.h"
21 #endif
22
23 void
24 awaitEvent(rtsBool wait)
25 {
26   int ret;
27
28 #ifdef RTS_SUPPORTS_THREADS
29   // Small optimisation: we don't want the waiting thread to wake
30   // up straight away just because a previous returning worker has
31   // called abandonRequestWait().  If the event is no longer needed,
32   // reset it.  We must do this inside the sched_mutex.
33   if (!needToYieldToReturningWorker()) {
34       resetAbandonRequestWait();
35   }
36 #endif
37
38   do {
39     /* Try to de-queue completed IO requests
40      */
41     RELEASE_LOCK(&sched_mutex);
42     ret = awaitRequests(wait);
43     ACQUIRE_LOCK(&sched_mutex);
44     if (!ret) { 
45       return; /* still hold the lock */
46     }
47
48     // Return to the scheduler if:
49     //
50     //  - we were interrupted
51     //  - new threads have arrived
52     //  - another worker wants to take over (RTS_SUPPORTS_THREADS)
53
54   } while (wait
55            && !interrupted
56            && run_queue_hd == END_TSO_QUEUE
57 #ifdef RTS_SUPPORTS_THREADS
58            && !needToYieldToReturningWorker()
59 #endif
60       );
61 }
62
63 #ifdef RTS_SUPPORTS_THREADS
64 void
65 wakeBlockedWorkerThread()
66 {
67   abandonRequestWait();
68 }
69 #endif
70