Native Threads in the RTS

Simon Marlow simonmar@microsoft.com
Tue, 26 Nov 2002 16:49:53 -0000


> *****************
> Native Threads Proposal, version 2
>=20
> Some "foreign" libraries (for example OpenGL) rely on a mechanism =20
> called thread-local storage. The meaning of an OpenGL call therefore =20
> usually depends on which OS thread it is called from.=20
> Therefore, some =20
> kind of direct mapping from Haskell threads to OS threads is=20
> necessary =20
> in order to use the affected foreign libraries.
> Executing every haskell thread in its own OS thread is not=20
> feasible for =20
> performance reasons. However, perfomance of native OS threads is not =20
> too bad as long as there aren't too many, so I propose that some =20
> threads get their own OS threads, and some don't:
>=20
> Every Haskell Thread can be either a "green" thread or a "native" =20
> thread.
> For each "native" thread, there is exactly one OS thread=20
> created by the =20
> RTS.

Is there an invariant that there is only one Haskell thread for each
native thread?

> For a green thread, it is unspecified which OS thread it is =20
> executed in.
> The main program and all haskell threads forked using forkIO=20
> are green =20
> threads. Threads forked using forkNativeThread :: IO () -> IO () are =20
> native threads. (Note: The type of the current haskell thread does =20
> _not_ matter when forking new threads)
>=20
> Execution of a green thread might move from one OS thread to=20
> another at =20
> any time. A "green" thread is never executed in an OS thread that is =20
> reserved for a "native" thread.
> A "native" haskell thread and all foreign imported functions that it =20
> calls are executed in its associated OS thread. A foreign exported =20
> callback that is called from C code executing in that OS thread is =20
> executed in the native haskell thread.
> A foreign exported callback that is called from C code=20
> executing in an =20
> OS thread that is not associated with a "native" haskell thread is =20
> executed in a new green haskell thread.
>=20
> Only one OS thread can execute Haskell code at any given time.
>=20
> If a "native" haskell thread enters a foreign imported=20
> function that is =20
> marked as "safe" or "threadsafe", all other Haskell threads keep =20
> running. If the imported function is marked as "unsafe", no other =20
> threads are executed until the call finishes.

I'd change this paragraph as follows:

  If a "native" haskell thread enters a foreign imported=20
  function that is =20
  marked as "threadsafe", all other Haskell threads keep =20
  running. If the imported function is marked as "safe" or "unsafe",
  no other threads are executed until the call finishes.

in other words, foreign imports for native threads behave just like they
do for green threads.  As Simon P.J. pointed out, we don't do any
OS-thread synchronisation on a "safe" foreign import.

> Other things I'm not sure about:
> What should we do get if a foreign function spawns a new OS=20
> thread and =20
> executes a haskell callback in that OS thread? Should a new native =20
> haskell thread that executes in the OS thread be created? Should the =20
> new OS thread be blocked and the callback executed in a green=20
> thread? =20
> What does the current threaded RTS do? (I assume the=20
> non-threaded RTS will just crash?)

The Haskell callback will execute in a green thread, according to the
proposal above, and I think that's the right thing to do.

It's possible to get into a situation in which several Haskell threads
in the system are associated with the same OS thread:

  - Haskell native thread calls a foreign import, which
  - invokes a Haskell callback, which
  - calls a foreign import, which
  - invokes another Haskell callback

at this point the two Haskell threads created by the callbacks are both
attached to the same native thread.  One of them is blocked waiting for
its foreign import to return, however.  I'm not sure if this is
important.
=20
Cheers,
	Simon