Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Haskell
Wiki community
Recent changes
Random page
HaskellWiki
Search
Search
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
Lightweight concurrency
(section)
Page
Discussion
English
Read
Edit
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit
View history
General
What links here
Related changes
Special pages
Page information
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
==== Problem 1 - Indefinitely blocked threads ==== In the LWC implementation, since there is no notion of a runnable queue of threads for a capability, how do we raise <hask>BlockedIndefinitely</hask> exception? We need to distinguish between blocked on an unreachable concurrent data structure and an unreachable scheduler. The programmer makes this distinction explicit through the thread status argument as a part of [[Lightweight_concurrency#Substrate_primitives|context switch]] primitives. ===== Blocked on an unreachable concurrent data structure ===== If the MVar is unreachable, the scheduler might still be reachable, and some runnable thread is potentially waiting pull work off this scheduler. Thread blocked on an unreachable MVar will be blocked with thread status <hask>BlockedOnConcDS</hask>. In this case, we can prepare the blocked thread for raising the asynchronous exception as we do in the vanilla implementation. Subsequently, RTS need only to evaluate the blocked thread's unblock action, which will enqueue the blocked thread on its scheduler. But on which thread do we execute the unblock action? In the LWC implementation, each capability has only ever one thread in its run queue. The solution proposed here is similar to finalizer invocations. We create an array of IO () actions with the following structure: <haskell> [unblock_currentThread, unblock_t0, unblock_t1, ..., unblock_tn, switchToNext_currentThread] </haskell> where unblock_t0 to unblock_tn correspond to <hask>unblockThread</hask> upcalls of threads t0 to tn, which are being resurrected with <hask>BlockedIndefinitelyOnConcDS</hask> exception. unblock_currentThread and switchToNext_currentThread correspond to the <hask>unblockThread</hask> and <hask>switchToNext</hask> upcalls of the (only) thread currently on this capability. Next, we create a helper thread with the following closure applied to the array constructed previously. <haskell> rtsSchedulerBatchIO :: Array (IO ()) -> IO () </haskell> When given an array of IO () actions, <hask>rtsSchedulerBatchIO</hask> performs each IO action it one-by-one. The net effect of executing the new thread is to add the resurrected threads to their corresponding schedulers and waking up the original thread that was running on this capability. The newly created thread inherits the scheduler of the thread that was running on the scheduler. This is done by copying the upcall handlers. This is necessary since the newly created helper thread might also get blocked due to PTM actions, blackholes, etc,. ===== Blocked on a unreachable scheduler ===== This case is a bit tricky. If a thread is blocked on an unreachable scheduler, we need to find a scheduler for this thread to execute. But which scheduler? RTS does not know about any other user-level schedulers. We might fall back to the vanilla GHC's solution here, which is to prepare the blocked thread for asynchronous exception and add it to the current capability's queue of threads blocked on scheduler. At the end of GC, RTS first raises BlockedIndefinitelyOnScheduler exception on all the threads blocked on scheduler, and finally switches to the actual computation (current thread). This solution is not ideal since we do not eliminate schedulers completely from RTS.
Summary:
Please note that all contributions to HaskellWiki are considered to be released under simple permissive license (see
HaskellWiki:Copyrights
for details). If you don't want your writing to be edited mercilessly and redistributed at will, then don't submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource.
DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION!
Cancel
Editing help
(opens in new window)
Toggle limited content width