Remove this file, as it has been replaced by threads.tex a long time ago.
authorWolfgang Thaller <wolfgang.thaller@gmx.net>
Thu, 18 Sep 2003 22:01:19 +0000 (22:01 +0000)
committerWolfgang Thaller <wolfgang.thaller@gmx.net>
Thu, 18 Sep 2003 22:01:19 +0000 (22:01 +0000)
ffi/threads.txt [deleted file]

diff --git a/ffi/threads.txt b/ffi/threads.txt
deleted file mode 100644 (file)
index 82e86c5..0000000
+++ /dev/null
@@ -1,322 +0,0 @@
-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
-=====================================