Foreign Threads
===============

There are two variant attempts to address issues associated with
thread-local state in foreign threads (i.e., those provided by the
operating system or standard libraries as opposed to those provided by
a Haskell runtime system).

Until such time as we are able to merge the proposals, we include both
proposals as self-contained entities.

At the end, we include an outstanding issue concerning the meaning of
'threadsafe'.

Proposal 1
==========

Goals
~~~~~

Since foreign libraries sometimes exploit thread local state, it is
necessary to provide some control over which thread is used to execute
foreign code.  In particular, it is important that it should be
possible for Haskell code to arrange that a sequence of calls to a
given library are performed by the same foreign (or 'native') thread
and that if an external library calls into Haskell, then any outgoing
calls from Haskell are performed by the same foreign thread.

This specification is intended to be implementable both by
multi-threaded Haskell implementations and by single-threaded
implementations and so it does not comment on which particular OS
thread is used to execute Haskell code.


Design
~~~~~~

Haskell threads may be bound with either zero or one foreign threads.
Binding occurs at thread creation time.  There are four ways to
create Haskell threads so there are four cases to consider:

1) forkForeignThread :: IO () -> IO ThreadId
   The fresh Haskell thread is bound to a fresh foreign thread.

2) forkIO :: IO () -> IO ThreadId
   The fresh Haskell thread is not bound to a foreign 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>

   or
     
     foreign import "bound wrapper" wrapFoo :: <type>

   and otherwise behave like normal foreign exports.

4) ToDo: For completeness, there ought to be a way to 'bind'
   finalizers to foreign threads but no concrete proposal currently
   exists.

Calls to bound foreign imports by Haskell threads which are bound to a
foreign thread are performed by that foreign 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 foreign thread at
the implementation's discretion.


Issues
~~~~~~

The notion of bound foreign imports could be eliminated 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 which
perform less context switching - this is especially important for
'unsafe' foreign calls.


An alternative to forkForeignThread is to allow direct control over
thread binding:

   bindThread :: ForeignThread -> IO ()
   The current Haskell thread is bound to a fresh foreign thread.
   (Any previous binding is forgotten.)

This leads to a much simpler design since it eliminates the need for
forkForeignThread and can be used for finalizers too.  The cost is
that every bound foreign call requires locking and a context switch
since multiple Haskell threads may be bound to the same foreign thread
and could try to make a foreign call 'at the same time'.  Binding
finalizers to foreign threads also seems to require locking and a
context switch for the same reason.


End of Proposal 1
=================


Proposal 2
==========

Goals
~~~~~

Since foreign libraries sometimes exploit thread local state, it is
necessary to provide some control over which thread is used to execute
foreign code.  In particular, it is important that it should be
possible for Haskell code to arrange that a sequence of calls to a
given library are performed by the same native thread and that if an
external library calls into Haskell, then any outgoing calls from
Haskell are performed by the same native thread.

This specification is intended to be implementable both by
multithreaded Haskell implementations and by single-threaded
implementations and so it does not comment on which particular OS
thread is used to execute Haskell code.

Definitions
~~~~~~~~~~~

A native thread is a thread as defined by the operating system.

A "Haskell thread" encapsulates the execution of a Haskell I/O action. A
Haskell thread is created by forkIO, and dies when the I/O action
completes. When a Haskell thread calls a foreign imported function, it
is considered to be 'blocked' while the foreign function is executing.
If the foreign imported function calls back to Haskell, any IO actions
it triggers are considered to be executed in new Haskell threads. This
is the way it is implemented in GHC. Other implementations may implement
it differently, but it is believed that the proposal can be implemented
without following the GHC way of doing things here. The only observable
difference should be the behaviour of myThreadID in conjunction with
foreign functions.

Design
~~~~~~

1) Haskell threads may be associated at thread creation time with either
zero or one native threads. Each Native thread is associated with zero
or more Haskell threads.

2) A Haskell thread is always executed by a native thread. This
specification places absolutely no restrictions on which native thread
is used to execute a particular Haskell thread. The Haskell thread need
not be associated with the native thread used to execute it, and one
Haskell thread may be executed by more than one native thread during its
lifetime [but not by several native threads at once].

3) If a native thread is associated with one or more Haskell threads,
then at most one of the bound Haskell threads must be runnable at any
time. All but at most one of the bound Haskell threads must be blocked
on a foreign function call.

4) The thread that main runs in, threads created using forkIO and
threads created for running finalizers or signal handlers are not
necessarily associated with a native thread. However, an implementation
might choose to do so.

5) There are now two kinds of foreign exported [and foreign import
wrapped] functions: bound and free. The FFI syntax should be extended
appropriately:

Bound foreign exports have the form:

foreign export bound foo :: <type>

And bound foreign wrappers should be declared as follows:

foreign import "bound wrapper" wrapFoo :: <type>

All other foreign exports and wrappers are considered as free (unbound).

6) 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 implementation may
freely decide which thread to run the foreign function in. The existing
distinction between unsafe, safe and threadsafe calls remains unchanged.

7) When a "bound" foreign exported function is invoked [by foreign
code], a new Haskell thread is created and associated with the native
thread. The new associated Haskell thread is then used to execute the
callback. The invariants stated in 3) automatically hold, because the
foreign code must either run in a native thread that is not bound, or it
must have been called by haskell code bound to that thread (which means
that the other bound haskell threads are blocked on the foreign call).

8) When a "free" foreign exported function is invoked, the
implementation may freely choose what kind of Haskell thread the
function is executed in. It is not specified whether this thread is
associated with a particular OS thread or not.

9) A new library routine, forkNativeThread :: IO () -> IO ThreadID,
should spawn a new Haskell Thread (like forkIO) and associate it with a
new native thread (forkIO is not guaranteed to do this). It may be
implemented using the FFI and an OS-specific thread creation routine. It
would just pass a "bound" callback as an entry point for a new OS
thread.

Issues
~~~~~~

Finalizers and signal handlers cannot be associated with a particular
native thread. If they have to trigger an action in a particular native
thread, a message has to be sent manually (via MVars and friends) to the
Haskell thread associated with the native thread in question.

The term "Haskell thread" is confusing. The current proposal is strongly
influenced by the GHC-way of seeing things. It doesn't really matter
whether a callback is executed in a new Haskell thread or in the Haskell
thread that called out of Haskell Land in the first place [if such a
thread exists].

Implementations
~~~~~~~~~~~~~~~

Here are some examples of how the specification might be implemented.
They should not be considered an actual part of the specification.

1)
Let's assume we have a haskell system that has used OS native threads
from the start. Every call to forkIO creates a new OS thread. The OS is
responsible for all scheduling. Now we want to add support for [my
version of] the proposal to this implementation.
This should be trivial to do: A foreign call should be just a call, and
a callback should just start executing Haskell code in the current OS
thread.
This implementation would treat all foreign exports as bound ("the
implementation may freely choose what kind of Haskell thread the
function is executed in"). All "safe" calls will probably be treated as
"threadsafe" (after all, it's no use blocking other threads). 
If it weren't for the performance problems, this would be the ideal
solution for me.

2)
Let's assume we have a haskell system that executes all Haskell code in
one thread and does its own scheduling between those threads. Now we
want to add support for [my version of] the proposal. We do not want to
move execution of Haskell code to different threads. We are not
concerned about performance.
In this case, we would keep track of the association between Haskell
threads and "foreign" OS threads (here, the term "foreign thread" seems
to fit very well). If the Haskell code calls a foreign imported
function, a message is sent to the associated foreign thread (a new
foreign thread is created if necessary). If a foreign exported function
is called, it just signals the "Haskell runtime thread".
The performance would be better than 1) as long as no foreign functions
are involved. When the ffi is used, performance gets worse.

3)
"The Middle Way", i.e. what I think should be implemented for GHC. The
following are just fragments of thoughts, don't expect it to be complete
yet:
* There is a global lock [that's the Capability in the GHC RTS]
which prevents several haskell threads from running truly concurrently.
* Each bound Haskell thread is executed by its associated native thread.
* Each bound native thread is executing at most one piece of code at a
time, i.e. there is no scheduling going on inside the bound native
thread.
* When a bound foreign export is invoked, the RTS creates a new Haskell
thread bound to the current OS thread.
The following things are unchanged:
* Unsafe calls are just plain old function calls
* All unbound Haskell threads are executed by a so-called "worker
thread". When an unbound Haskell thread calls a threadsafe imported
function, a new worker thread is created.
* when an unbound foreign export is invoked, the RTS creates a new
unbound Haskell thread.

End of Proposal 2
=================


Query about meaning of threadsafe
=================================

Wolfgang Thaller writes:
> I reread Section 3.3 of the FFI document (RC7), and now I think I
> cannot clarify my specification in this respect without first asking
> others to clarify the current specs - can someone explain the
> distinction between unsafe, safe and threadsafe in the current FFI
> to me? I think I know what it does in GHC, but what's the general
> definition?

My reading of the spec is that it means that execution of other
runnable Haskell threads and of the foreign function can be
interleaved.  That is, neither will be 'starved'.

Operationally, this requires that the Haskell runtime and the foreign
call operate in separate threads.

I think it is a mistake for the ffi spec to say that single-threaded
systems may safely ignore this spec.  Who would specify 'threadsafe'
if they were not worried about starvation?  How could an
implementation that allows starvation be considered correct?

I think Haskell compilers that cannot implement 'threadsafe' as it is
implemented in GHC should reject Haskell programs which use it.  I
think the ffi spec should be amended to say this (the spec currently
says that such compilers may treat 'threadsafe' as meaning 'safe').

I suspect that 'threadsafety' is actually orthogonal to the
'safe/unsafe' distinction.  I think it would be perfectly meaningful
to make calls which must execute in a separate thread (i.e., are
'threadsafe') but do not make callbacks into Haskell (i.e., could
otherwise be 'unsafe').  We currently ignore this case because the
overhead of a context switch is so much greater than the overhead of a
safe call.

End query about meaning of threadsafe
=====================================
