[GHC] #9285: IO manager startup procedure somewhat odd
GHC
ghc-devs at haskell.org
Tue Jul 8 17:19:01 UTC 2014
#9285: IO manager startup procedure somewhat odd
------------------------------------+-------------------------------------
Reporter: edsko | Owner:
Type: bug | Status: new
Priority: low | Milestone:
Component: Compiler | Version: 7.8.2
Keywords: | Operating System: Unknown/Multiple
Architecture: Unknown/Multiple | Type of failure: None/Unknown
Difficulty: Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: |
------------------------------------+-------------------------------------
Currently the RTS startup procedure for the threaded runtime with a single
capability looks something like this:
'''1. Capability gets initialized'''
{{{
hs_main
real_main
hs_init_ghc
initScheduler
initCapabilities
}}}
'''2. IO Manager is started'''
{{{
hs_main
real_main
hs_init_ghc
ioManagerStart
}}}
'''3. ensureIOManagerIsRunning'''
The IO manager of course is mostly written in Haskell, so `ioManagerStart`
does
{{{
cap = rts_lock();
rts_evalIO(&cap,&base_GHCziConcziIO_ensureIOManagerIsRunning_closure,NULL);
rts_unlock(cap);
}}}
'''4. Bound task is created and we start running Haskell code'''
Since this is the first call to `rts_lock`, it creates a bound task to
correspond to the current OS thread.
'''5. Haskell code does a safe FFI call: create worker task 1'''
The first safe FFI call that the IO manager makes (ignoring `labelThread`)
is to `c_setIOManagerControlFd`. At this point, the bound task gets
suspended and we create a worker task.
'''6. Worker task 1 starts executing `GHC.Event.Manager.loop`'''
The worker tasks gets suspended due to an explicit call to `yield` in
`GHC.Event.Manager.step`, at which point the bound task continues
execution. It continues and finishes (`ensureIOManagerRunning` completes).
The worker task takes over.
'''7. Worker task 1 does a safe FFI call to `I.poll`, create new worker
task 2'''
(This safe call is from `GHC.Event.Manager.step`)
'''8. Worker task 2 executes `GHC.Event.TimerManager.loop`, and does safe
FFI call to `I.poll`; create worker task 3'''
This worker task will remain spare for now.
'''9. Start executing the actual main function'''
The IO manager calls `rts_unlock`, which verifies if there are any spare
workers available; it finds that there are and doesn't start a new one.
Then when we start `main` itself of course we go through this `rts_lock,
rts_evalIO, rts_unlock` sequence ''again''. This is somewhat confusing,
and makes tracing the startup of the code more difficult to interpret. It
seems that this could be simpler: only a single `rts_lock` should be
necessary, in which we first call `ensureIOManagerIsRunning` and then
`main`, followed by a single `rts_unlock`. A similar simplification should
be possible in `forkProcess`.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/9285>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list