diff options
author | Duncan Coutts <duncan@well-typed.com> | 2020-12-29 17:39:19 +0000 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2022-11-22 02:06:17 -0500 |
commit | ced9acdbe757331d8d0046df30a06e61b05dd204 (patch) | |
tree | 52f6796b25bf23c5eeaa0b88e4b794b09d30386a /rts/Schedule.c | |
parent | 5cf709c541a46a17ef2e36d589ba13d949d058e1 (diff) | |
download | haskell-ced9acdbe757331d8d0046df30a06e61b05dd204.tar.gz |
Move {blocked,sleeping}_queue from scheduler global vars to CapIOManager
The blocked_queue_{hd,tl} and the sleeping_queue are currently
cooperatively managed between the scheduler and (some but not all of)
the non-threaded I/O manager implementations.
They lived as global vars with the scheduler, but are poked by I/O
primops and the I/O manager backends.
This patch is a step on the path towards making the management of I/O or
timer blocking belong to the I/O managers and not the scheduler.
Specifically, this patch moves the {blocked,sleeping}_queue from being
global vars in the scheduler to being members of the CapIOManager struct
within each Capability. They are not yet exclusively used by the I/O
managers: they are still poked from a couple other places, notably in
the scheduler before calling awaitEvent.
Diffstat (limited to 'rts/Schedule.c')
-rw-r--r-- | rts/Schedule.c | 35 |
1 files changed, 9 insertions, 26 deletions
diff --git a/rts/Schedule.c b/rts/Schedule.c index c1ef05930b..95eba3f958 100644 --- a/rts/Schedule.c +++ b/rts/Schedule.c @@ -70,13 +70,6 @@ * Global variables * -------------------------------------------------------------------------- */ -#if !defined(THREADED_RTS) -// Blocked/sleeping threads -StgTSO *blocked_queue_hd = NULL; -StgTSO *blocked_queue_tl = NULL; -StgTSO *sleeping_queue = NULL; // perhaps replace with a hash table? -#endif - // Bytes allocated since the last time a HeapOverflow exception was thrown by // the RTS uint64_t allocated_bytes_at_heapoverflow = 0; @@ -910,7 +903,13 @@ scheduleCheckBlockedThreads(Capability *cap USED_IF_NOT_THREADS) // run queue is empty, and there are no other tasks running, we // can wait indefinitely for something to happen. // - if ( !emptyQueue(blocked_queue_hd) || !emptyQueue(sleeping_queue) ) + // TODO: this empty-queue test is highly dubious because it only makes + // sense for some I/O managers. The sleeping_queue is _only_ used by the + // select() I/O manager. The WinIO I/O manager does not use either the + // sleeping_queue or the blocked_queue, so both queues will _always_ be + // empty and so awaitEvent will _never_ be called here for WinIO. This may + // explain why there is a second call to awaitEvent below for mingw32. + if ( !EMPTY_BLOCKED_QUEUE(cap) || !EMPTY_SLEEPING_QUEUE(cap) ) { awaitEvent (emptyRunQueue(cap)); } @@ -2365,11 +2364,6 @@ deleteAllThreads () // somewhere, and the main scheduler loop has to deal with it. // Also, the run queue is the only thing keeping these threads from // being GC'd, and we don't want the "main thread has been GC'd" panic. - -#if !defined(THREADED_RTS) - ASSERT(blocked_queue_hd == END_TSO_QUEUE); - ASSERT(sleeping_queue == END_TSO_QUEUE); -#endif } /* ----------------------------------------------------------------------------- @@ -2703,12 +2697,6 @@ startWorkerTasks (uint32_t from USED_IF_THREADS, uint32_t to USED_IF_THREADS) void initScheduler(void) { -#if !defined(THREADED_RTS) - blocked_queue_hd = END_TSO_QUEUE; - blocked_queue_tl = END_TSO_QUEUE; - sleeping_queue = END_TSO_QUEUE; -#endif - sched_state = SCHED_RUNNING; SEQ_CST_STORE(&recent_activity, ACTIVITY_YES); @@ -2793,14 +2781,9 @@ freeScheduler( void ) #endif } -void markScheduler (evac_fn evac USED_IF_NOT_THREADS, - void *user USED_IF_NOT_THREADS) +void markScheduler (evac_fn evac STG_UNUSED, + void *user STG_UNUSED) { -#if !defined(THREADED_RTS) - evac(user, (StgClosure **)(void *)&blocked_queue_hd); - evac(user, (StgClosure **)(void *)&blocked_queue_tl); - evac(user, (StgClosure **)(void *)&sleeping_queue); -#endif } /* ----------------------------------------------------------------------------- |