Native Threads in the RTS

Dean Herington heringto@cs.unc.edu
Tue, 26 Nov 2002 13:12:16 -0500 (EST)


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