Bound Threads

Wolfgang Thaller wolfgang.thaller at
Sun Mar 16 17:39:11 EST 2003

Hi Daan & everyone else,

> Now, I can be easily convinced that "threadsafe" is the way to go, 
> whenever there
> is a compelling example where forkOS/forkIO fails.

I'm not arguing that there is a situation where forkOS/forkIO fail to 
provide sufficient functionality. In fact, I'm afraid they may provide 
too much functionality, leading to an overly complex solution.
Also, I'm afraid that "safe" foreign imports, with their strange 
blocking behaviour, will be a permanent source of bugs.

As I've already said, I consider lightweight threads and the ability to 
run multiple lightweight threads in one OS thread to be an 
implementation detail of many current Haskell implementations. 
Implementation details of the runtime system should not be exposed to 
the user (although they may be available as primitives that may change 
from compiler version to compiler version).

Providing forkOS/forkIO would _require_ future implementations to 
provide this functionality, even if there is no longer any technical 
reason for it.

> Now, what I don't like about my proposal and your proposal is that the 
> user has to be aware of OS threads when making foreign calls by 
> wrapping it in "threadSafe" or
> adding "threadsafe" sometimes -- but maybe that is unavoidable.

With threadsafe and bound, we could just treat "threadsafe" and "bound" 
as defaults. Then, the user does not have to be aware of the OS 
thread/lightweight issue, unless (s)he wants to optimize for 
performance. Only then would the user need to add "unsafe" or "unbound" 
(or remove "bound") in some places.
(GHC 5.05 already has "threadsafe" as default; as "safe" doesn't seem 
to provide any advantages, it is currently not implemented in the 
threaded RTS).

> On the other hand, it seems awkward/impossible to make sure that 
> certain functions
> are always called from a specific OS thread with the "threadsafe" 
> approach while
> the forkOS/forkIO primitives are always available to the programmer 
> for explicit
> management of threads.

How would you make sure that a certain function is always called from a 
specific OS thread (other than the current one) in C? I don't see why 
the runtime system should provide special support for this, it looks 
like trying to beat C at interacting with C libraries...

> Thanks for the explanation. Just on the side, it seems that this 
> approach always involves
> an OS context switch for bound callbacks. This doesn't happen with the 
> forkOS/forkIO approach.
> It may be rather expensive, take a mouse motion event handler for 
> example.

(I assume you meant to say "unbound callbacks". Bound callbacks don't 
require a thread-switch).
Unbound callbacks require a thread-switch in the approach I just 
described*. However (after having thought about it for a few minutes), 
I'm convinced that this extra thread-switch can easily be optimized 
away in the RTS. The resulting implementation would still be simpler 
than what is required to support the forkIO/forkOS primitives.

( * ... plus two extra OS thread switches that have nothing to do with 
this issue. They'd be necessary with either approach until someone 
makes certain improvements to the storage manager)

>> Maybe we need a more exact specification of how forkOS/forkIO should  
>> behave, especially with respect to foreign calls blocking other  
>> threads. Could you elaborate on how you would expect "normal" (safe)  
>> > foreign calls to behave in different situations?
> 1) "forkOS" starts a new haskell thread in a new OS thread
> 2) "forkIO" starts a new haskell thread in the current OS thread
> 3) maybe we should also add "forkUnbound" that forks a haskell thread 
> that can automatically
>   be moved between OS threads.
> 4) a foreign call blocks all haskell threads that are attached to the 
> current OS thread
>   until a) the call returns, or b) the call enters Haskell again.

Does that make sense for implementations that don't use the "current" 
OS thread for executing the Haskell code (just for foreign calls)? Such 
implementations would have to do extra locking that's not really 

> 5) on top of this, we can implement *) a library function "fork" that 
> forks a new haskell thread
>      that maybe runs in separate OS thread, depending on the 
> architecture.

Wouldn't that mean it would be impossible to predict which other 
haskell threads, if any, would be blocked by a particular call to a 
foreign import?



More information about the FFI mailing list