Native Threads in the RTS

Wolfgang Thaller wolfgang.thaller@gmx.net
Fri, 29 Nov 2002 00:20:02 +0100


I'll write up a new version of the proposal tomorrow. For now, here are 
some answers and [at the end] a question about the current FFI 
specification.

Simon Peyton Jones wrote:
> You don't say (but you do mean)
>
> 	A bound Haskell thread can be executed only by its associated
> native thread

No I don't mean that, and I've been avoiding to say that. This is how 
the GHC implementation will probably handle it, but I do not want to 
put that in the general specification. Alastair remarked a while ago:

> For that matter, I'd like it to be possible to implement this spec in
> Hugs.  Hugs is internally single-threaded but this spec is concerned
> with what happens when Haskell calls out to C and we could arrange to
> switch into the appropriate native thread when Hugs calls out to C.

After all, the only thing which needs to be guaranteed is that foreign 
functions called by the Haskell thread are executed in the associated 
native thread.

> You don't say (and I'm not sure if you mean)
>
> 	If a bound native thread blocks, all of its associated Haskell
> 	threads are blocked too
>
> 	If a bound Haskell thread blocks, its associate native thread
> and all its
> 	associated Haskell threads also block.

Does this sound clearer:

*) Exactly one Haskell thread associated with the native thread is 
executing. All other associated Haskell threads are blocked. No foreign 
code is being executed by the native thread.
*) The native thread is executing foreign code. No Haskell code is 
executing in any of the associated Haskell threads.
*) The native thread and all Haskell threads associated with it are 
blocked.

> | The thread that main runs in, threads created using forkIO and 
> threads
> | created for running finalizers or signal handlers are not necessarily
> | associated with a native thread. However, an implementation might
> | choose to do so.
>
> But the impl may *not* choose a bound native thread.  These must be 
> kept
> inviolate.
>
> [...]
> Again, it must not be a bound native thread.

Good point, I had overlooked that.

> If a bound Haskell thread
> 	calls a foreign import that is not labelled 'threadsafe'
> 	which calls a bound foreign export
> does that work?  What if the foreign export was not bound?
>
> Similarly, if the foreign import was labelled 'threadsafe', would it
> work?  It's not obvious to me.  Some kind of semantics would be good.

Good question. I reread Section 3.3 of the FFI document (RC7), and now 
I think I cannot clarify my specification in this respect without first 
asking others to clarify the current specs - can someone explain the 
distinction between unsafe, safe and threadsafe in the current FFI to 
me? I think I know what it does in GHC, but what's the general 
definition? I've read the description in the FFI document, but it's not 
clear to me. Is there any reason why "safe" is the default and not 
"threadsafe"? After all, "safe" is less safe (it might cause the whole 
program to block). To me, "safe" seems to be an odd middle ground 
between speed and safety. What is "safe" guaranteed/allowed to do? Is 
it _guaranteed_ to block other Haskell threads under certain 
conditions? Or is that only an artifact of current implementations? Why 
are implementations allowed to _silently_ fall back to "safe" when 
"threadsafe" is not supported? Isn't that dangerous?

If I'm not mistaken, "threadsafe" calls from bound Haskell threads 
would have exactly the same overhead as "safe" calls. Should we make 
sure that "safe" calls somehow block other threads? If so, why?


Thats all for now....

Wolfgang