RE: Native Threads in the RTS

Or, we can adopt a much weaker semantics than Wolfgang intended and have:
$0 <= bindees(f) - uses(f)$
This would allow several currently running, active Haskell threads to all be bound to the same foreign thread. When any of these threads makes a foreign call, the other threads could all keep running and they would only block if they too tried to make foreign calls. From an implementation point of view, this requires:
1) That foreign threads are _not_ used to execute Haskell code.
2) That we maintain a lock on foreign threads so that only one Haskell thread tries to use it at a time.
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.
Another problem, from an implementation point of view, is that we would have to surround "unsafe" foreign calls with a lot of context-switching gumph, in case the calling Haskell thread is bound to a native thread. I really think we don't want to do this. The "thread groups" idea is similar, but only allows one of the Haskell threads in a group to be executing at any one time. This means you can run the Haskell thread using its native thread, and you don't have to context switch on every C call. However, I believe it would be tricky to implement this correctly in the scheduler (not impossible, just tricky and hard to test). Cheers, Simon

Simon Marlow:
Another problem, from an implementation point of view, is that we would have to surround "unsafe" foreign calls with a lot of context-switching gumph, in case the calling Haskell thread is bound to a native thread. I really think we don't want to do this.
Note that you only have to do this to foreign calls of the form: foreign import bound foo :: ... since any other calls are free to use whatever thread they feel like. 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.) -- Alastair

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 me. 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 registers. And I definitely do want to keep that efficiency for "bound" Haskell threads. 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 pattern
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. Cheers, Wolfgang
participants (3)
-
Alastair Reid
-
Simon Marlow
-
Wolfgang Thaller