
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

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.

On Sun, 17 Nov 2002 12:23:06 +0100
Sven Panne
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

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 +0000, 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

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

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... Best regards, Nicolas Oury Le vendredi 15 novembre 2002, à 06:02 , Wolfgang Thaller a écrit :
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 Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

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. Best regards, Nicolas Oury Le vendredi 15 novembre 2002, à 06:02 , Wolfgang Thaller a écrit :
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 Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

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.
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]. 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. Cheers, Wolfgang Thaller

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 Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
participants (5)
-
Duncan Coutts
-
Nicolas Oury
-
Sven Panne
-
William Lee Irwin III
-
Wolfgang Thaller