wolfgang.thaller at gmx.net
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
> 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
(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
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
More information about the FFI