
On Mar 3, 2006, at 5:29 AM, Thomas Shackell wrote:
That is very good to hear. It seems to me that the two biggest issues are: -- supporting multiple execution stacks -- blocking I/O and FFI calls How did you decide to handle these problems (mostly for my curiousity)?
You're quite right, those were two of the biggest issues :-)
The first thing to note is that concurrency is implemented in Yhc by the interpretter running some instructions for one process, then some more instructions for the next process and so on.
This is rather than using one OS thread per Haskell process because all processes can access the global heap, so if using OS threads it would be necessary to either lock every heap access (incredibly slow) or use some of the truely nasty tricks that concurrent GHC uses.
The first problem, as you note, is that originally we only had one stack but now every process needs its own stack. After considering possible options I decided the easiest way was: - process stacks become normal nodes in the heap, and are garbage collected like other heap nodes. This preserves the property that we can't run out of heap but not stack (and vice versa).
[snip] How do you detect when a process runs out of stack? Do you calculate the max stack usage from the bytecode and check before you push a new stack frame?
Now going back, the approach of running some instructions from one thread then some more from another is fine providing every instruction runs quickly. They all do, with one exception, PRIMITIVE. This is because PRIMITIVE is used for IO actions/FFI calls.
The solution? Well the basic idea is "just spawn an OS thread to do the IO action while the main thread continues running Haskell".
[snip] How do you deal with OS threads portably? I assume you use pthreads for *nix. Does windows know pthreads or did you create some thin wrapper over OS specific threading?
Hope that answers your questions :-)
Yes, thank you! Rob Dockins Speak softly and drive a Sherman tank. Laugh hard; it's a long way to the bank. -- TMBG