Re: Native Threads in the RTS
I've been watching the discussion about native threads, and getting thoroughly confused. Understandable ;-) . But before investing effort in fiddling with it, I thought it'd be good to see whether anyone finds it helpful. Yes, it does seem to be a good idea. Feel free to modify it. E.g. add inline comments, alternative rules, and whatever. OK, I'll get to work :-) Cheers, Wolfgang ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: Native Threads in the RTS
2. It seems perfectly reasonable to want to have the Haskell called-back code throw an exception that is caught by the Haskell code that called out to foreign code. Reusing the Haskell thread is necessary (though not sufficient) to achieve such behavior. This is a particularly tricky problem, and I prefer to leave it up to the programmer to handle such things. Propagating the exception to the original (Haskell) caller automatically is unlikely to be the right thing to do, because the foreign code will almost certainly want to do some clean up. If the foreign language supports exceptions then it is conceivable that we could turn a Haskell exception into a foreign exception (and vice-versa), but for plain C I think we should leave well alone. Cheers, Simon ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
Dean Herrington wrote: [...] Rather, I find it nonintuitive that calling from Haskell to foreign code and back into Haskell should create a new Haskell thread, when these two Haskell threads really are just different portions of a single thread of computation (deliberately vague term). I agree to that. Creating a new thread for calling back into Haskell _only_ makes sense if you look at it from inside the GHC RTS. Before I had a look at the relevant parts of the RTS, I would never have thought of that. I don't know if there's any advantage/disadvantage to changing GHC's internals. The only _observable_ difference is the thread's ThreadIds, and this should at least be clearly documented (or, even better, it should be explicitly undocumented, so that no one will be suprised if the behaviour is changed in the future). Off the top of my head I can think of two situations in which having separate threads is bothersome. 3. Throwing exceptions to a thread If I manually translate haskell exceptions to foreign exceptions and back, there is no reason why I shouldn't want to raise an exception in a thread I have a threadId for, even if that thread called a foreign function which in turn called back to haskell. I think that the behaviour can always be emulated using MVars however, so I think there's no immediate action required. --- I've tried to rephrase my proposal for native threads, this time treating GHC's behaviour in this situation as an implementation detail. I think the meaning of the proposal becomes clearer because of this. The proposal doesn't comment on ThreadIds, so the non-intuitive (IMHO) behaviour in GHC is independent of the bound threads proposal. I think I've understood both my own specification and the current RTS well enough to start trying to implement a prototype soon. The intended meaning of the specification hasn't changed for the third revision in a row. Does anyone have concrete suggestions for the syntax change to foreign export and foreign import wrapper? Cheers, Wolfgang = Bound Threads Proposal, version 5 Goals ~ Since foreign libraries sometimes exploit thread local state, it is necessary to provide some control over which thread is used to execute foreign code. In particular, it is important that it should be possible for Haskell code to arrange that a sequence of calls to a given library are performed by the same native thread and that if an external library calls into Haskell, then any outgoing calls from Haskell are performed by the same native thread. This specification is intended to be implementable both by multithreaded Haskell implementations and by single-threaded implementations and so it does not comment on which particular OS thread is used to execute Haskell code. Definitions ~~~ A native thread is a thread as defined by the operating system. A Haskell thread encapsulates the execution of a Haskell I/O action. A Haskell thread is created by forkIO, and dies when the I/O action completes. When a Haskell thread calls a foreign imported function, it is not considered to be blocked (in the GHC runtime system, the calling thread is blocked; This is considered an implementation detail for the purposes of this specification, but be aware that myThreadId might return several different values for one Haskell thread as defined here). If the foreign function calls back to Haskell, the callback is said to run in the same Haskell thread. Design ~~ Haskell threads may be associated at thread creation time with either zero or one native threads. Each Native thread is associated with at most one Haskell thread. A native thread that is associated with a Haskell thread is called a bound Haskell thread. A Haskell thread that is associated with a native thread is called a bound native thread. A Haskell thread is always executed by a native thread. This specification places absolutely no restrictions on which native thread is used to execute a particular Haskell thread. The Haskell thread need not be associated with the native thread used to execute it, and one Haskell thread may be executed by more than one native thread during its lifetime [but not by several native threads at once]. A bound native thread may not be used for executing any Haskell thread except the one it is bound to. It is implementation dependent whether the main thread, threads created using forkIO and threads created for running finalizers or signal handlers are bound or not. When a foreign imported function is invoked [by Haskell code], the foreign code is executed in the native thread associated with the current Haskell thread, if an association exists. If the current Haskell thread is not associated to a native thread, the implementation may decide which native thread to run the foreign function in. The native thread that is used may not be bound to another Haskell thread. The existing distinction
RE: Native Threads in the RTS
| 2. Calling from foreign code into Haskell to a bound foreign import will | require some special handling to ensure that a subsequent call out to | foreign code will use the same native thread. Why couldn't this special | handling select the same Haskell thread instead of creating a new one? This is just an efficiency issue, right? If creating a Haskell thread from scratch is very cheap, then it's easier to do that each time rather than to try to find the carcass of a completed Haskell thread. If you do the latter, you need to get into carcass management. But maybe there is more to it than efficiency in your mind? Simon ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
I've postponed writing up a new proposal again... But I'm going to sum up some requirements that I would like to see fulfilled - to make it clearer to others why I'm proposing such strange things... *) It should be possible for Haskell code to arrange that a sequence of calls to a given library are performed by the same native thread and that if an external library calls into Haskell, then any outgoing calls from Haskell are performed by the same native thread. *) The specification should be implementable in a way that allows a lot of foreign calls to be made with no additional overhead with respect to GHC's current unsafe foreign calls. *) The good performance of the existing lightweight green threads in GHC should not be sacrificed. Performance should still OK when using the new features with only a few threads (i.e. not more than commonly used from multithreaded C programs). *) The specification shouldn't explicitly require lightweight green threads to exist. The specification should be implementable in a simple and obvious way in haskell systems that always use a 1:1 correspondence between Haskell threads and OS threads. *) The specification shouldn't specify which particular OS thread should be used to execute Haskell code. It should be possible to implement it with e.g. a Haskell interpreter running in one OS thread that just uses other OS threads for foreign calls. *) There should be no unexpected blocking. Especially, threadsafe calls should never cause other threads to block. I'm currently stuck thinking about one particular problem that I discovered in my current version of the spec. What happens when an unbound Haskell thread calls a threadsafe foreign function which in turn calls a bound foreign exported function? Well, I think my current proposal says relatively clearly what's supposed to happen, but I discovered it's not as easy to fit that in the current implementation of GHC as I thought... in fact it might be quite difficult. I'll have to do more thinking before I can be sure, though. That's it for today, Regards, Wolfgang ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
On 29 Nov 2002, Alastair Reid wrote: 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. Each of a,b,c,d are executed by different Haskell threads (because a new Haskell thread is spawned for each call into Haskell) so we have multiple Haskell threads associated with a single foreign thread. It doesn't feel right to me that a,b,c,d are executed by different Haskell threads. Why shouldn't they all be the *same* Haskell thread? 1. Reasonable exception handling across the Haskell/foreign boundary is not currently supported, but if we imagine moving in that direction, it would seem we'd want a single thread for the given example. 2. Calling from foreign code into Haskell to a bound foreign import will require some special handling to ensure that a subsequent call out to foreign code will use the same native thread. Why couldn't this special handling select the same Haskell thread instead of creating a new one? Dean ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
[Note: I'm consistently using 'foreign thread' instead of 'native thread'. The Haskell-spec necessarily treats Haskell as the centre of the universe. So what a Linux kernel hacker might think of as a 'native thread' is really quite foreign to Haskell. Feel free to ignore this little experiment with the language.] *) 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. Each of a,b,c,d are executed by different Haskell threads (because a new Haskell thread is spawned for each call into Haskell) so we have multiple Haskell threads associated with a single foreign thread. Now, when D is called, which of these threads is 'executing' and which are 'blocked'? I think the quoted text assumes that a,b,c,d are blocked during the call to D. The GHC implementation might well perform a context switch on making the calls into C so we could, perhaps, say that a Haskell thread is 'blocked' while making an ffi call. But, for normal function calls (i.e., all in Haskell or all in C, no ffi stuff), we don't say that the caller is 'blocked' until the callee returns. I think it's better to reserve the word is 'blocked' for its normal usage and avoid possibly over-specifying what implementations must do to implement the spec. Possible rewording: Definitions: Let $f$ be a foreign thread. $uses(f)$ is the number of foreign calls by Haskell threads bound to $f$. $bindees(f)$ is the number of Haskell threads bound to $f$. Invariant: $0 = bindees(f) - uses(f) = 1$ Proof: (Should be possible by) structural induction over relevant IO operations (forkIO, forkNativeIO, etc.) 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: bindees(f) - uses(f) == 0 or, maybe even, bindees(f) == 0 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. -- Alastair ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
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 ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
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 ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: Native Threads in the RTS
This is all getting highly confusing, as it seems we're working with different ideas of what's on the table. Alastair: you seem to be working on your own proposal - could you write it down either as a complete proposal or diffs to Wolfgangs? I did. You sent comments on it and I sent back a cleaned up version. Here it is again. My apologies - I didn't notice you'd already proposed 'foreign import bound' so I thought you were working with a definition that we hadn't seen. Never mind. Cheers, Simon ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
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 ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: Native Threads in the RTS
Improving. Want to put it in CVS? Simon M can suggest where. Simon | Definitions | ~~~ | A native thread (aka OS thread) is a thread as defined by the operating | system. | A Haskell thread is [*** FIXME - How shall I put this? ***] the thing | you see from Haskell land. A Haskell thread encapsulates the execution of a Haskell I/O action. A Haskell thread is created by forkIO, and dies when the I/O action completes. A Haskell thread is always executed by a native thread. The Haskell RTS creates one or more worker native threads to execute Haskell threads. | Haskell threads may be associated at thread creation time with either | zero or one native threads. Each Native thread is associated with zero | or more native threads. zero or more *Haskell* threads. Can you give an example of when a native thread is associated with more than one Haskell thread? To avoid A Haskell thread associated with a native thread I'd prefer to define the term a bound Haskell thread. I would also like to describe a bound native thread as one that has associated Haskell thread(s). | If a native thread is associated with one or more Haskell threads, | exactly one of the following must be true: | *) Exactly one Haskell thread associated with the native thread is | executing. | *) The native thread is executing foreign code. | *) The native thread and all Haskell threads associated with it are | blocked. You don't say (but you do mean) A bound Haskell thread can be executed only by its 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. | 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. | When a free foreign exported function is invoked, the implementation | may freely choose what kind of Haskell thread the function is executed | in. It is not specified whether this thread is associated with a | particular OS thread or not. Again, it must not be a bound native thread. | When a foreign imported function is invoked [by Haskell code], the | foreign code is executed in the native thread associated with the | current Haskell thread, if an association exists. If the current | Haskell thread is not associated to a native thread, the implementation | may freely decide which thread to run the foreign function in. | The existing distinction between unsafe, safe and threadsafe calls | remains unchanged. 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. ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: Native Threads in the RTS
Simon P.J. writes: Can you give an example of when a native thread is associated with more than one Haskell thread? I gave an example in my previous message. It's when a bound Haskell thread makes a foreign call which re-enters Haskell via a bound foreign export. 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 When Bagpuss goes to sleep, all his friends go to sleep too. :-) (apologies to those who never watched British childrens TV in the 70s). Actually, for any given native thread, only one of its bound Haskell threads can be runnable, the others must all be blocked waiting on the result of a foreign call. So you don't really have to worry about a native thread being bound to multiple Haskell threads; this would be quite tricky to implement in the scheduler anyway. Cheers, Simon ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
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 ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
Typo: Being fresh to Haskell, I suggest that the naming continues to be native and free. I did mean native and green Have a nice day, once again. Johan Steunenberg ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: Native Threads in the RTS
When a bound foreign exported function is invoked [by foreign code], the implementation checks whether a Haskell thread is associated with the current OS thread. If there is one, this Haskell thread is used to execute the callback. If there is none, a new Haskell thread is created and associated with the native thread. This is the only situation where a Haskell thread is associated with a native thread. The new associated Haskell thread is then used to execute the callback. When the callback finishes, the Haskell thread is terminated, the association is dissolved, but the OS thread continues to run. This is the bit I have trouble with too. If the OS thread trying to call a foreign export has an associated Haskell thread, then it must be because the Haskell thread called out to C in the first place. This Haskell thread will be waiting for the call to return, and has all the state associated with its current execution context, so we can't just use that thread to run the foreign export. I don't see the problem with forking a new Haskell thread for each foreign export, and associating it with the current native thread if the foreign export is marked bound. It does mean we can get multiple Haskell threads bound to the same native thread, but only one can be runnable at any one time (this is an important invariant from the point of view of the implementation, I believe). Cheers, Simon ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
Are you sure you intend to change the type of forkIO? Currently it's forkIO :: IO () - IO ThreadId Sorry, no, I did not. -- Alastair ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
Simon Marlow wrote: I don't see the problem with forking a new Haskell thread for each foreign export, and associating it with the current native thread if the foreign export is marked bound. It does mean we can get multiple Haskell threads bound to the same native thread, but only one can be runnable at any one time (this is an important invariant from the point of view of the implementation, I believe). Of course, you're right. Simon Peyton-Jones wrote: I offer myself as such a guinea pig. I'm afraid I don't understand it yet. It's hard to describe precisely. Comments below. Yes, I do need a guinea pig ;-) . I really have trouble expressing my ideas accurately, and I keep changing them. Better start with some definitions, for 'Haskell thread' and'native thread' I think I know what you mean, but better to be sure. Well, yes. I didn't manage to come up with a decent definition for it yet. I intend native thread to be the thing you get using pthread_create on unix, and Haskell thread to be the same thing as it currently is in the GHC RTS. Can anyone think of a way of defining that in a way that is accurate, general and understandable? | If there is one, this Haskell thread is used to execute the callback. OK, so this is where I get completely confused. A Haskell thread is not (currently) an execution platform. Oops... The best way to confuse other people is to be confused yourself ;-) --- I had a slight misconception about the RTS there --- I think I've corrected that. === Threads Proposal, version 4 Goals ~ Since foreign libraries sometimes exploit thread local state, it is necessary to provide some control over which thread is used to execute foreign code. In particular, it is important that it should be possible for Haskell code to arrange that a sequence of calls to a given library are performed by the same native thread and that if an external library calls into Haskell, then any outgoing calls from Haskell are performed by the same native thread. This specification is intended to be implementable both by multithreaded Haskell implementations and by single-threaded implementations and so it does not comment on which particular OS thread is used to execute Haskell code. Definitions ~~~ A native thread (aka OS thread) is a thread as defined by the operating system. A Haskell thread is [*** FIXME - How shall I put this? ***] the thing you see from Haskell land. Design ~~ Haskell threads may be associated at thread creation time with either zero or one native threads. Each Native thread is associated with zero or more native threads. If a native thread is associated with one or more Haskell threads, exactly one of the following must be true: *) Exactly one Haskell thread associated with the native thread is executing. *) The native thread is executing foreign code. *) 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. There are now two kinds of foreign exported [and foreign import wrapped] functions: bound and free. The FFI syntax should be extended appropriately [which of the two should be the default, if any?]. When a bound foreign exported function is invoked [by foreign code], a new Haskell thread is created and associated with the native thread. The new associated Haskell thread is then used to execute the callback. When a free foreign exported function is invoked, the implementation may freely choose what kind of Haskell thread the function is executed in. It is not specified whether this thread is associated with a particular OS thread or not. When a foreign imported function is invoked [by Haskell code], the foreign code is executed in the native thread associated with the current Haskell thread, if an association exists. If the current Haskell thread is not associated to a native thread, the implementation may freely decide which thread to run the foreign function in. The existing distinction between unsafe, safe and threadsafe calls remains unchanged. A new library routine, forkNativeThread :: IO () - IO ThreadID, should spawn a new Haskell Thread (like forkIO) and associate it with a new native thread (forkIO is not guaranteed to do this). It may be implemented using the FFI and an OS-specific thread creation routine. It would just pass a bound callback as an entry point for a new OS thread. Issues ~~ Finalizers and signal handlers cannot be associated with a particular native thread. If they have to trigger an action in a particular native thread, a message has to be sent manually (via MVars and friends) to the Haskell thread associated with the native thread in question. This introduces a change in the syntax for
Re: Native Threads in the RTS
On 26 Nov 2002, Alastair Reid wrote: ps Better names than 'native' and 'green' surely exist. Something which conveys the idea that the thread will be remembered for later use seems appropriate but no good words spring to mind. Perhaps bound and free? ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: Native Threads in the RTS
Alastair Reid wrote: Design ~~ Haskell threads may be associated at thread creation time with either zero or one native threads. There are only two ways to create Haskell threads so there are two cases to consider: Umm, Alastair, I think you've got things a bit mixed up here. Did you mean two ways to create a native thread? There are currently three ways to create a Haskell thread (forkIO, foreign export, finalizers) and Wolfgang has proposed a fourth (forkNativeThread). Or perhaps you're proposing we do away with forkIO and only have forkNativeThread? That was discounted a while back because we want to continue to have light-weight threads independent of OS threads. 1) forkNativeThread :: IO () - IO () The fresh Haskell thread is associated with a fresh native thread. (ToDo: do we really need to use a fresh native thread or would a pool of threads be ok? The issue could be avoided by separating creation of the native thread from the 'associate' operation.) 2) Calls to a threadsafe foreign export allocate a fresh Haskell thread which is then associated with the Haskell thread. I don't know what you mean by a threadsafe foreign export. Did you mean threadsafe foreign import perhaps? And I'm not sure how a fresh Haskell thread is associated with a Haskell thread ;-) Calls to threadsafe foreign imports by threads which have an associated native thread are performed by that native thread. Calls to any other foreign imports (i.e., 'safe' or 'unsafe' calls) may be made in other threads or, if it exists, in the associated native thread at the implementation's discretion. [ToDo: can Haskell threads with no associated thread make foreign calls using a thread associated with some other thread? er... overloading the word thread was maybe not such a good idea. I think you're asking whether a green thread can grab a native thread to make a foreign call. The current answer is no... but can you think of a reason we might want this feature? Cheers, Simon ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
On Tue, 2002-11-26 at 08:32, Dean Herington wrote: On 26 Nov 2002, Alastair Reid wrote: ps Better names than 'native' and 'green' surely exist. Something which conveys the idea that the thread will be remembered for later use seems appropriate but no good words spring to mind. Perhaps bound and free? Won't that be confused with bound and free as used in lambda calculus? Or am I missing the point and you mean that they are analogous to bound and free in lambda calculus? (If the latter, I need to reread my lambda calculus books. :)) ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users -- Seth Kurtzberg M. I. S. Corp 480-661-1849 Pager 888-605-9296, or [EMAIL PROTECTED] ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
On 26 Nov 2002, Alastair Reid wrote: Umm, Alastair, I think you've got things a bit mixed up here. Did you mean two ways to create a native thread? No. There are currently three ways to create a Haskell thread (forkIO, foreign export, finalizers) and Wolfgang has proposed a fourth (forkNativeThread). Invocation of a signal handler also creates a Haskell thread, doesn't it? I was (implicitly) viewing forkIO and forkNativeThread as two variants of the same operation. Both fork a Haskell thread, one of them also creates a native thread. (It may also choose to use the native thread as the Haskell thread but that's not externally observable.) I was putting off finalizers until the end. 1) forkNativeThread :: IO () - IO () The fresh Haskell thread is associated with a fresh native thread. (ToDo: do we really need to use a fresh native thread or would a pool of threads be ok? The issue could be avoided by separating creation of the native thread from the 'associate' operation.) 2) Calls to a threadsafe foreign export allocate a fresh Haskell thread which is then associated with the Haskell thread. I don't know what you mean by a threadsafe foreign export. Did you mean threadsafe foreign import perhaps? And I'm not sure how a fresh Haskell thread is associated with a Haskell thread ;-) Using the bound/free terminology suggested by Seth, what I meant was bound foreign import. Actually, I proposed the terms, and Seth criticized the proposal. Perhaps bound and unbound might be a bit better and partially avoid the possible confusion with lambda calculus variables. [ToDo: can Haskell threads with no associated thread make foreign calls using a thread associated with some other thread? er... overloading the word thread was maybe not such a good idea. I think you're asking whether a green thread can grab a native thread to make a foreign call. The current answer is no... but can you think of a reason we might want this feature? My question was of the form: 'is a correct implementation allowed to use a native thread even if the programmer didn't ask for it?' not 'can we make this happen?' Sorry for all the confusion, here's the key part of the proposal again - hopefully without the ambiguity. Haskell threads may be bound with either zero or one native threads. Binding occurs at thread creation time. There are four ways to create Haskell threads so there are four cases to consider: How about: A Haskell thread may be bound to a native thread. Such binding occurs when the Haskell thread is created and persists for the lifetime of the Haskell thread. A Haskell thread that is not bound to a native thread is called unbound. There are four ways ... 1) forkNativeThread :: IO () - IO () The fresh Haskell thread is bound to a fresh native thread. 2) forkIO :: IO () - IO () The fresh Haskell thread is not bound to a native thread. 3) Calls to a bound foreign export allocate a fresh Haskell thread which is then bound to the calling thread thread. ... which is bound to the calling native thread ? Bound foreign exports have the form foreign export bound foo :: type and otherwise behave like normal foreign exports. 4) ToDo: For completeness, there ought to be a way to 'bind' finalizers to native threads but no concrete proposal currently exists. [ToDo: The following could be simplified 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.] Calls to bound foreign imports by threads which are bound to a native thread are performed by that native thread. Bound foreign imports have the form foreign import bound foo :: type and otherwise behave like normal foreign imports. Calls to any free (i.e., not bound) foreign imports may be made in the bound thread (if it exists) or by some other native thread at the implementation's discretion. -- Alastair ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
At 2002-11-26 09:37, Alastair Reid wrote: 1) forkNativeThread :: IO () - IO () The fresh Haskell thread is bound to a fresh native thread. 2) forkIO :: IO () - IO () The fresh Haskell thread is not bound to a native thread. Are you sure you intend to change the type of forkIO? Currently it's forkIO :: IO () - IO ThreadId -- Ashley Yakeley, Seattle WA ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
Nice design, Alastair. I've stolen lots of ideas and some text for the complete rewrite of the proposal. The concept of associating haskell threads to native threads proved to be a good way of explaining my original idea in a different way --- and then I found out that forkNativeThread needn't be a primitive, but can be implemented on top of the FFI. After that I found out what the bound/free exports buisiness was all about and why we might need it. As for the questions regarding my previous proposal, I think they are answered in the new one. If they aren't, let me know. [It's no use explaining what I meant to say if I already want to say something different ;-) ] Cheers, Wolfgang === Threads Proposal, version 3 Goals ~ Since foreign libraries sometimes exploit thread local state, it is necessary to provide some control over which thread is used to execute foreign code. In particular, it is important that it should be possible for Haskell code to arrange that a sequence of calls to a given library are performed by the same native thread and that if an external library calls into Haskell, then any outgoing calls from Haskell are performed by the same native thread. This specification is intended to be implementable both by multithreaded Haskell implementations and by single-threaded implementations and so it does not comment on which particular OS thread is used to execute Haskell code. Design ~~ Haskell threads may be associated at thread creation time with either zero or one native threads. Each Native thread is associated with zero or one Haskell threads (no native thread may be associated with two Haskell threads at a time). An associated pair of a Haskell thread and a native thread can only execute either foreign code or haskell code at any one time. The thread that main runs in, threads created using forkIO and threads created for running finalizers or signal handlers are not associated with a native thread [Actually, we might make this an implementation detail: These Haskell threads are not guaranteed to be associated with a native thread. If it makes sense for some implementation, all threads might be associated with native threads]. There are now two kinds of foreign exported [and foreign import wrapped] functions: bound and free [I'm not happy with these names, for the same reasons as given by Seth before]. When a bound foreign exported function is invoked [by foreign code], the implementation checks whether a Haskell thread is associated with the current OS thread. If there is one, this Haskell thread is used to execute the callback. If there is none, a new Haskell thread is created and associated with the native thread. This is the only situation where a Haskell thread is associated with a native thread. The new associated Haskell thread is then used to execute the callback. When the callback finishes, the Haskell thread is terminated, the association is dissolved, but the OS thread continues to run. When a free foreign exported function is invoked, the implementation may freely choose what Haskell thread the function is executed in. It is not specified whether this thread is associated with a particular OS thread or not. When a foreign imported function is invoked [by Haskell code], the foreign code is executed in the native thread associated with the current Haskell thread, if an association exists. If the current Haskell thread is not associated to a native thread, the implementation may freely decide which thread to run the foreign function in. This must be done for all foreign imports, including unsafe. An unsafe call must not call back to Haskell or otherwise cause a garbage collection. Other Haskell threads may be blocked while the unsafe call executes. A safe call allows callbacks to Haskell. Other Haskell threads may be blocked while the unsafe call executes. A threadsafe call additionally guarantees other Haskell threads not to block. forkNativeThread :: IO () - IO ThreadID may be implemented using the FFI and an OS-specific thread creation routine. Issues ~~ Finalizers and signal handlers cannot be associated with a particular native thread. If they have to trigger an action in a particular native thread, a message has to be sent manually (via MVars and friends) to the Haskell thread associated with the native thread in question. This might be tedious, but if we want to avoid the nastiness of multiple Haskell threads associated with one OS thread (lots of unpredictable blocking), it looks like our only choice. ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
Hello, I read your proposal. It's great but I have a few remarks : * I think that, if it is not too much complicated, it could be great to put many threads in the OpenGL OS thread. The goal of concurrent Haskell was to allow concurrency for expressivity. It would be a pity to lose this in part of programs for technical reason. Having this possibility would also be a pro this language : Haskell would be the only language to have safe multithreaded OpenGL programming. *Another problem can raise : if one render in two different OpenGL windows, he may want to use different threads for these rendering. However, this is impossible for the moment because it would implies that user threads know when a switch has occurred to a thread rendering in another context and swap OpenGL context. This implies a notion of either : allowing to execute arbitrary code on switch ; either introducing a notion of family of threads. When a switch occurs to a member of a family different of the last member of the family executed , some user defined code should be executed (in that case the code perform a context switch). family and members of family would be defined by user. It seems that family and OS threads are independent : it could either be multiple OS threads for a family or multiple families for an OS threads. I think a thread could be member of multiple families (even if I can't see pertinent example so far). I also think that multiple threads can be the same member of a family (multiple threads drawing in the same window). * A simple way of introducing these new notions (family, members, OS threads) would be to define them as first class value. This would ease the problem of callback : an OpenGL callback would simply be a call to an operator telling the OpenGL thread to execute really the callback. threadsafe could be a short hand for wrapping a callback in a call to the thread currently executing (at time of the call to threadsafe function) and give it to extern function. * To protect OpenGL operations, it would perhaps be useful to introduce a mechanism forbidding to switch between members of a family between a critical section. (I don't know what do a context switch between a glBegin and glEnd). I don't know if my proposal is pertinent but it addresses some problems that would arise. It's quite complicated but i think that there is no overcost for people who don't need using it. Best regards, Nicolas Oury ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
Nicolas Oury a écrit: * I think that, if it is not too much complicated, it could be great to put many threads in the OpenGL OS thread. The goal of concurrent Haskell was to allow concurrency for expressivity. It would be a pity to lose this in part of programs for technical reason. Having this possibility would also be a pro this language : Haskell would be the only language to have safe multithreaded OpenGL programming. You can safely render into two different OpenGL contexts from two different OS threads. I don't think that rendering into the same context from two green threads would work - the OpenGL interface is far too thread-based for this to be useful. *Another problem can raise : if one render in two different OpenGL windows, he may want to use different threads for these rendering. However, this is impossible for the moment because it would implies that user threads know when a switch has occurred to a thread rendering in another context and swap OpenGL context. This implies a notion of either : allowing to execute arbitrary code on switch ; [...] If we want to render into two different OpenGL windows in parallel, we can use two OS threads. OpenGL keeps a reference to its current OpenGL context on a per-OS-thread basis (some old OpenGL implementations might not support this, but I think we can ignore them). [...] some user defined code should be executed (in that case the code perform a context switch) [...] Haskell Code won't work here [after all, we're between two haskell threads...]. C code would be no problem. I actually proposed something like this as a stopgap measure for making OpenGL work with the threaded RTS in summer, but I was convinced by others on this list that this is a hackish solution that relies on internals of the RTS far too much. It seems that family and OS threads are independent : it could either be multiple OS threads for a family or multiple families for an OS threads. I think a thread could be member of multiple families (even if I can't see pertinent example so far). I also think that multiple threads can be the same member of a family (multiple threads drawing in the same window). What would it mean if a thread was a member of more than one thread families? Would it mean that it might execute in several different OS threads? Also, how would these thread groups interact with the existing threaded RTS? Would the existing features still be available without additional effort? Would they be implemented on top of these thread families? I'm not quite convinced that the thread families approach would be worth the additional complexity. What would it be used for? * To protect OpenGL operations, it would perhaps be useful to introduce a mechanism forbidding to switch between members of a family between a critical section. (I don't know what do a context switch between a glBegin and glEnd). We already have MVars, they can be used for things like that. Can anybody else think of reasons why we should need a more complicated design where threads are put into different families or groups, where each thread group executes in exactly one OS thread? This has been proposed at least twice now, but I fail to see the advantages (it looks more flexible, but what's it _for_?). Some disadvantages of a thread groups approach are: *) More complexity. *) Foreign calls will block other threads in the same group. *) It would be even less meaningful for a haskell implementation that always uses OS threads --- the native/green threads proposal could be implemented as a no-op (forkNativeThread = forkIO) without breaking programs that use it. Somebody else please fill in the advantages. Cheers, Wolfgang ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
Great, thanks. I hope you'll keep it up to date so that by the time the discussion converges it can serve as a specification and rationale. We can put it in CVS too... Simon will think of where! Until then, I'll play the role of a human CVS server. Ultimately it'd be worth integrating with http://www.cse.unsw.edu.au/~chak/haskell/ghc/comm/rts-libs/multi- thread. html Of course. Some parts should be part of the user documentation, while others should probably be considered implentation details. | A foreign exported | callback that is called from C code executing in that OS thread is | executed in the native haskell thread. This is the bit I don't understand. Is the only scenario you have in mind here native Haskell thread calls C which calls Haskell and you want all that in the same native thread? Yes, exactly. What about this? native Haskell thread calls C which installs a pointer to a foreign-exported Haskell function in some C data structure Later... some other Haskell thread calls C which waits for an event which calls the callback So the callback was installed by a native thread, but won't be executed by it. Is that ok? Definitely. It's the same way it works in C. What thread some code executes in depends on what thread the code is called from. Anyway I think it would be worth explaining what is guaranteed a bit more clearly. I'm not sure how... to me it looks like I already specified this exactly ;-). Anyway, I've added some examples to the proposal to clarify what I mean. | If a green haskell thread enters a foreign imported function marked | as safe, all other green threads are blocked. Native haskell threads | continue to run in their own OS threads. No, I don't think so. The reason that 'safe' is cheaper than 'threadsafe' is that the current worker OS thread does not need to release the Big Lock it holds on the Haskell heap, thereby allowing other green threads to run. Instead, it holds the lock, executes the call, and returns. At least I think this is the idea, but it's all jolly slippery. I thought that was unsafe? The safe version still does quite a lot (after all, a callbacks are allowed, so is GC). In addition, threadsafe may start a new OS thread in order to keep executing green threads. On the other hand, we might simply leave it unspecified: If people want to know what happens to other threads, they should use threadsafe or unsafe. The exact behaviour of safe seems to be an implementation detail. | Other things I'm not sure about: Presumably if a native thread spawns a thread using forkIO, it gets just a green thread? If it used forkNativeThread it gets a distinct native thread. Better say this. The main program and all haskell threads forked using forkIO are green threads. Threads forked using forkNativeThread :: IO () - IO () are native threads. I thought that was clear enough... I've added a note. Cheers, Wolfgang * Native Threads Proposal, version 2 Some foreign libraries (for example OpenGL) rely on a mechanism called thread-local storage. The meaning of an OpenGL call therefore usually depends on which OS thread it is called from. Therefore, some kind of direct mapping from Haskell threads to OS threads is necessary in order to use the affected foreign libraries. Executing every haskell thread in its own OS thread is not feasible for performance reasons. However, perfomance of native OS threads is not too bad as long as there aren't too many, so I propose that some threads get their own OS threads, and some don't: Every Haskell Thread can be either a green thread or a native thread. For each native thread, there is exactly one OS thread created by the RTS. For a green thread, it is unspecified which OS thread it is executed in. The main program and all haskell threads forked using forkIO are green threads. Threads forked using forkNativeThread :: IO () - IO () are native threads. (Note: The type of the current haskell thread does _not_ matter when forking new threads) Execution of a green thread might move from one OS thread to another at any time. A green thread is never executed in an OS thread that is reserved for a native thread. A native haskell thread and all foreign imported functions that it calls are executed in its associated OS thread. A foreign exported callback that is called from C code executing in that OS thread is executed in the native haskell thread. A foreign exported callback that is called from C code executing in an OS thread that is not associated with a native haskell thread is executed in a new green haskell thread. Only one OS thread can execute Haskell code at any given time. If a native haskell thread enters a foreign imported function that is marked as safe or threadsafe, all other Haskell threads keep running. If the imported function is marked as unsafe, no other threads are executed until the call
Re: Native Threads in the RTS
Hello, Le mardi 19 novembre 2002, à 01:28 , Wolfgang Thaller a écrit : Nicolas Oury wrote: I don't know if what I say is pertinent, but there was another problem that was discussed in the thread about threaded RTS. One may want to use a finalizer in a particular thread. For example, a finalizer that put make a rotating cube on screen must be ran in the same thread as the Opengl/GLUT things... Good point. That feature won't be covered by my first proposal (As I said, I'll write up a proper document about that ASAP, that is, as soon as I find an entire hour of free time). It sounds useful at first, but I'm not that sure about it: after all, we can't rely on when the finalizer will be executed: the thread might no longer be around, and the GLUT window might be long closed. We should definitely think about it a little more, though. These problems always appears with finalizer. An example (maybe a bit strange but) : one can want to close a window when the program can't reach it anymore. It may sound more realistic if it is closing an unreachable database with a databasse library made for one thread only... I don't know if it is planned but I think it could be great to be able to have, in the new OS thread for OpenGL, an expressivity only concurrence system. I mean that to be able to fork user threads that are executed in the new OS thread. These new threads would be blocked on other threads in that kernel thread blocked, but can all access to this library, and will make programming easier. This sounds a lot like the thread group idea that somebody had when we last discussed this. I think it gives us added flexibility at the cost of more difficult implementation and the danger of accidentally blocking OS threads [it might be just yet another source of bugs]. It is not bad that threads working in the OpenGL world are blocked when OpenGL can't receive orders. The user would see new OS thread as a thread for a kind of group : group of people using OpenGL, are blocked wwhen OpenGl blocks. Think again of other example : imagine the glorious haskell web server using a database library allowing only one thread access. One can't write all the request in only one thread, the programmer will have to add a monothreaded layer that serve requests from other threads that are preparing pages with database datas. I don't know if that library (database monothread) exits but a good exercise would be to all try to find example library relevant to this problem. I can start adding a small example : SDL, which allows to manage every low level parts of 2D games and all that isn't OpenGl in an OpenGl game. I have a small and dirty binder to SDL, and in SDL one have to use the same thread for pumping events (asking what have be done), than the one which was use to open video window !!! A program would here be far better organize if multithreaded is allowed in one thread... With that kind of problem, having a way to program multithreaded and run monothread is a power. As there already is user level threads, it would be a pity to lose that. I'll first write up something in order to explain/accurately define the simple solution I proposed. After that, we can still design a more complex solution that addresses these two issues. Great, Best regards, Nicolas Oury Cheers, Wolfgang Thaller ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: Native Threads in the RTS
| I propose adding something like | | forkNativeThread :: IO () - IO () I haven't talked to Simon about this, but it sounds possible. Three thoughts. First, before doing anything like this I'd like to ask you or someone else, or a group, to write a clear exposition of what the problem is and what the solution is, to add to the GHC user manual. (If there are implementation related questions, they can go into the Commentary.) As you say, this is a topic that we have visited regularly, and it's a slippery one, so I'd like to capture it. Second, there's the question of what it really means. In particular, what if that thread forks further (Haskell, green) threads? Are they too bound to the native thread? A library you call might in principle fork threads to get its job done... Third | If a callback is entered and the current OS thread corresponds to a | native haskell thread, the callback should be executed in the current | OS thread. | Other haskell threads continue to run in the worker thread or in their | own dedicated OS thread. I'm not sure what this means. What is the current OS thread? Perhaps an example? Simon ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: Native Threads in the RTS
I'm still unconvinced that the current optional RTS support for mixed green/native threads is the right way to go. It looks to me like a workaround for poor OS support for really lightweight threads. It is a workaround for the lack of truly lightweight threads at the OS level. But I don't expect that situation to change, even with the recent improvements on the Linux front. The new RedHat Linux threads folk claim to be able to create 10^5 threads in a couple of seconds, whereas we can create 10^6 threads in about that time (on an old 500MHz machine, too). Cheers, Simon ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
Wolfgang Thaller wrote: [...] I propose adding something like forkNativeThread :: IO () - IO () which forks a new Haskell thread that has its own OS thread to execute in. Note that the fact that only one Haskell thread may execute at a time remains unchanged. [...] I haven't thought very deeply about your proposal yet, but I don't understand the remark above: What about e.g. a multi-processor Solaris machine (where pthreads work as intended, not the rather poor stuff currently shipped with Linux)? In such an environment there are often multiple processors executing different threads (or LWPs, or whatever you call it) of the same process simultaneously. Perhaps I misunderstood something here... :-} Nevertheless, you make a good point: Better support for real multi-threading is definitely an area where I'd like to see some improvement for the next non-patchlevel release of GHC. I'm still unconvinced that the current optional RTS support for mixed green/native threads is the right way to go. It looks to me like a workaround for poor OS support for really lightweight threads. Cheers, S. ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
On Sun, 17 Nov 2002 12:23:06 +0100 Sven Panne [EMAIL PROTECTED] wrote: Nevertheless, you make a good point: Better support for real multi-threading is definitely an area where I'd like to see some improvement for the next non-patchlevel release of GHC. I'm still unconvinced that the current optional RTS support for mixed green/native threads is the right way to go. It looks to me like a workaround for poor OS support for really lightweight threads. Which of course has been improving greatly recently - on Linux at least. The 2.6 kernel will apparently have threading on par with Solaris. In fact, the next Linux pthreads library looks as though it will be based on a 1:1 model rather than a M:N model because it is simpler and (with the recent threading improvements) performs better. So that means that all of ghc's major platforms (Solaris, Linux, Win32) will have good OS thread support in the near future. Duncan ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
On Sun, 17 Nov 2002 12:23:06 +0100 Sven Panne wrote: Nevertheless, you make a good point: Better support for real multi-threading is definitely an area where I'd like to see some improvement for the next non-patchlevel release of GHC. I'm still unconvinced that the current optional RTS support for mixed green/native threads is the right way to go. It looks to me like a workaround for poor OS support for really lightweight threads. On Sun, Nov 17, 2002 at 11:33:44AM +, Duncan Coutts wrote: Which of course has been improving greatly recently - on Linux at least. The 2.6 kernel will apparently have threading on par with Solaris. In fact, the next Linux pthreads library looks as though it will be based on a 1:1 model rather than a M:N model because it is simpler and (with the recent threading improvements) performs better. So that means that all of ghc's major platforms (Solaris, Linux, Win32) will have good OS thread support in the near future. 1:1 threading is inferior by virtue of resource scalability on 32-bit machines. This is not the final word. Bill ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Native Threads in the RTS
I wrote: [...] Note that the fact that only one Haskell thread may execute at a time remains unchanged. [...] Sven Panne wrote: I haven't thought very deeply about your proposal yet, but I don't understand the remark above: What about e.g. a multi-processor Solaris machine (where pthreads work as intended, [...] We can't currently allow several Haskell threads to really run simultaneosly [e.g. on two separate processors, or preemtively scheduled on a single processor], because they always mutate the same global heap. Currently, GHC switches its green threads only at times when the heap is in a defined state [not truly preemptively]. There seems to be some SMP support in the RTS, I don't know if it ever worked. If anyone wants to fix/finish it, that would be great, but it's not what I'm proposing here. My proposal is only a minimum solution intended to resolve the inherent incompatibility between the threaded RTS and libraries like OpenGL, which require thread-local-state. Cheers, Wolfgang ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Native Threads in the RTS
Hello All, A while ago there was a discussion on the shortcomings of the threaded RTS (in short, it doesn't work with foreign APIs that use thread-local state, and that breaks HOpenGL). Back then, it was decided to just keep the threaded RTS off by default and to do something about it some time after 5.04. I believe it's time to think about it again, so I'll take the liberty of proposing an extension to the RTS that might solve the problem. I propose adding something like forkNativeThread :: IO () - IO () which forks a new Haskell thread that has its own OS thread to execute in. Note that the fact that only one Haskell thread may execute at a time remains unchanged. Whenever the scheduler determines that a native haskell thread is next, it sends the OS worker thread to sleep and wakes up the OS thread corresponding to the native haskell thread. When the native haskell thread yields again, so does the corresponding OS thread. Foreign calls from normal (non-native) haskell threads should be handled in exactly the same way as they are currently. If a callback is entered and the current OS thread corresponds to a native haskell thread, the callback should be executed in the current OS thread. Other haskell threads continue to run in the worker thread or in their own dedicated OS thread. Programs that don't use forkNativeThread won't be affected by the change. Thread switching to and from native threads will be slower, but not painfully slow. Wrapping an entire HOpenGL program in forkNativeThread should solve the OpenGL/GLUT thread-local-state problem, for example, and who knows what else it is good for. Any comments? Opinions? Wolfgang ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users