Native Threads in the RTS

Simon Peyton-Jones
Wed, 27 Nov 2002 09:14:29 -0000

| Nice design, Alastair. I've stolen lots of ideas and some text for the
| complete rewrite of the proposal.

I think it is a great idea to rewrite the proposal.  A tiny minority
will follow the details of the discussion, and it's essential to record
the outcome in a way comprehensible by someone who reads only the

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. =20

I wonder if some simple formal semantics would be useful.


| 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).

Better start with some definitions, for
	'Haskell thread'
and	'native thread'

I think I know what you mean, but better to be sure. =20

| An associated pair of a Haskell thread and a native thread can only
| execute either foreign code or haskell code at any one time.

Unclear.  Can we have a name for a Haskell thread that is 'associated
with' a native thread?  (Or is that misleading?) Is that what you mean
by a 'bound Haskell thread'?  If so then I think the above sentence

	A bound Haskell thread can be executed only by its associated
native thread.

| There are now two kinds of foreign exported [and foreign import
| wrapped] functions: bound and free [I'm not happy with these names,
| the same reasons as given by Seth before].

Do you mean that the syntax for 'foreign export' etc is modified to let
you say bound/free?

| 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.

OK, so this is where I get completely confused.  A Haskell thread is not
(currently) an execution platform.  It is spawned to execute a single IO
action, and then dies, completely and forever.  Perhaps you are saying
	a bound Haskell thread does not vanish when it completes its IO
	instead it waits around in case its associated OS thread wants
it to do something

If that is what you mean, better say so, because it's quite new.
Suppose the Haskell thread calls *out* to foreign code.   Then the
Haskell thread is not available for to compute anything because it's
suspended in the middle of a call.

What happens if a bound Haskell thread blocks?  Does its associated OS
thread block too?  Please say so.

| 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.=20

Do you mean "This is the only way in which an association between a
native thread and a Haskell thread can be created"?

| 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.

So, returning to "the implementation checks whether a Haskell thread is
associated with
the current OS thread", how could this ever happen?  The Haskell thread
dies when the foreign call terminates.

| 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
| may freely decide which thread to run the foreign function in.
| This must be done for all foreign imports, including  "unsafe".

What is "this"?

| 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.

...not to block, even if the foreign call blocks in foreign code.

| forkNativeThread :: IO () -> IO ThreadID may be implemented using the
| FFI and an OS-specific thread creation routine.

Better say what you expect forkNativeThread to do, and what its
implementation looks like.