Native Threads in the RTS

Alastair Reid alastair@reid-consulting-uk.ltd.uk
26 Nov 2002 17:37:33 +0000


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

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

>> [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:

  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.

     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