Native Threads in the RTS
Fri, 29 Nov 2002 18:59:12 +0100
> So, we can say that foreign functions of the form:
> foreign import bound unsafe bar :: ...
> are illegal or we can allow them and provide warnings or we can allow
> them and trust the programmer to know that bar is much more expensive
> than they think. (I favour the first two.)
NOOO! Don't do that! Please don't!
> I see two potential problems with this (but would like to hear which,
> if either, dominates your thoughts):
> 1) If foreign threads cannot be used to execute Haskell code, foreign
> calls require (OS-level) context switches which are expensive.
> 2) Adding an implicit lock to foreign calls might surprise programmers.
I'm slightly concerned about 2), but 1) Is an absolute show-stopper for
It should stay possible to implement an unsafe call as just a call - no
special RTS management, no context switches, no nothing, just a few
machine code instructions to move the parameters to the stack and/or
And I definitely do want to keep that efficiency for "bound" Haskell
The reason why I startet this discussion is that I want to use OpenGL
in my Haskell Programs (which works fine with GHC's current
non-threaded RTS). OpenGL requires a lot of calls to functions that
don't take much time to execute and that don't call back to haskell
land. Using "safe" or even "threadsafe" for these calls would kill
performance utterly and completely.
>> *) 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.
> This isn't quite right - or, at least, needs clarified.
> Consider Haskell functions a,b,c,d and C functions A,B,C,D and a call
> a -> A -> b -> B -> c -> C -> d -> D
> That is, a calls A, calls b, calls B, calls ...
> Suppose we want A,B,C,D executed by the same foreign thread.
> I think the quoted text assumes that a,b,c,d are blocked during the
> call to D.
Yes. For the purpose of the above paragraph (and the neighboring
paragraphs in the spec), a Haskell thread is considered "blocked"
during a call to a foreign imported function. I admit that this
terminology is inspired by implementation details of GHC, but it makes
[some] sense: After all, if there is no Haskell code to execute [it's
foreign code only now], the Haskell thread can not be executed. A
Haskell thread can be either blocked or executing Haskell code.
> This needs careful interpretation if we want to be able to bind
> finalizers to foreign threads. In particular, if a finalizer is bound
> to a foreign thread, we don't increment 'bindees(f)' until the
> finalizer starts and we don't start the finalizer unless either:
I'm not currently planning to allow finalizers to be bound to
native(foreign) threads, as I have so far failed to see a solution that
I'm happy with.
> [...] From an implementation point of view, this requires:
> 1) That foreign threads are _not_ used to execute Haskell code.
One of my design goals is to allow the native threads to be used to
execute Haskell code. Implementations are not required to do so, but it
should be possible.
For that reason I also dislike the term "foreign thread". It sounds
great until I want to say "the implementation may use the foreign
thread to execute Haskell code".
And just as I went back to the computer after a long pause in order to
finish this message, a new proposal arrived. I'll take more time to
study it more completely. I just want to reiterate one thing:
> The notion of bound foreign imports could be eliminated by saying that
> all foreign calls are performed by the bound thread if one exists and
> eliminate the concept of 'bound foreign imports'. The only reason to
> allow any flexibility is to allow for faster implementations which
> perform less context switching - this is especially important for
> 'unsafe' foreign calls.
I definitely need zero-overhead bound unsafe calls. Everything else
would be basically unusable for me.
I'll be back later.