#include "Schedule.h"
#include <windows.h>
#include "win32/AsyncIO.h"
+#if defined(THREADED_RTS)
+#include "Capability.h"
+#endif
+
+// Used to avoid calling abandonRequestWait() if we don't need to.
+// Protected by sched_mutex.
+static nat workerWaitingForRequests = 0;
void
awaitEvent(rtsBool wait)
{
- RELEASE_LOCK(&sched_mutex);
+ int ret;
+
+#ifdef THREADED_RTS
+ // Small optimisation: we don't want the waiting thread to wake
+ // up straight away just because a previous returning worker has
+ // called abandonRequestWait(). If the event is no longer needed,
+ // reset it. We must do this inside the sched_mutex.
+ if (!needToYieldToReturningWorker()) {
+ resetAbandonRequestWait();
+ }
+#endif
+
do {
- /* Try to de-queue completed IO requests */
- if (!awaitRequests(wait)) {
- return;
- }
- ACQUIRE_LOCK(&sched_mutex);
- /* we were interrupted, return to the scheduler immediately.
+ /* Try to de-queue completed IO requests
*/
- if (interrupted) {
+ workerWaitingForRequests = 1;
+ RELEASE_LOCK(&sched_mutex);
+ ret = awaitRequests(wait);
+ ACQUIRE_LOCK(&sched_mutex);
+ workerWaitingForRequests = 0;
+ if (!ret) {
return; /* still hold the lock */
}
- /* If new runnable threads have arrived, stop waiting for
- * I/O and run them.
- */
- if (run_queue_hd != END_TSO_QUEUE) {
- return; /* still hold the lock */
- }
+ // Return to the scheduler if:
+ //
+ // - we were interrupted
+ // - new threads have arrived
+ // - another worker wants to take over (THREADED_RTS)
-#ifdef RTS_SUPPORTS_THREADS
- /* If another worker thread wants to take over,
- * return to the scheduler
- */
- if (needToYieldToReturningWorker()) {
- return; /* still hold the lock */
- }
+ } while (wait
+ && !interrupted
+ && run_queue_hd == END_TSO_QUEUE
+#ifdef THREADED_RTS
+ && !needToYieldToReturningWorker()
#endif
- RELEASE_LOCK(&sched_mutex);
- } while (wait && !interrupted && run_queue_hd == END_TSO_QUEUE);
+ );
}
-#ifdef RTS_SUPPORTS_THREADS
+#ifdef THREADED_RTS
void
wakeBlockedWorkerThread()
{
- abandonRequestWait();
+ if (workerWaitingForRequests) {
+ abandonRequestWait();
+ }
}
#endif
-