summaryrefslogtreecommitdiff
path: root/docs/users_guide/ffi-chap.xml
diff options
context:
space:
mode:
Diffstat (limited to 'docs/users_guide/ffi-chap.xml')
-rw-r--r--docs/users_guide/ffi-chap.xml818
1 files changed, 0 insertions, 818 deletions
diff --git a/docs/users_guide/ffi-chap.xml b/docs/users_guide/ffi-chap.xml
deleted file mode 100644
index 8417ef506b..0000000000
--- a/docs/users_guide/ffi-chap.xml
+++ /dev/null
@@ -1,818 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!-- FFI docs as a chapter -->
-
-<chapter id="ffi">
- <title>
-Foreign function interface (FFI)
- </title>
-
- <para>GHC (mostly) conforms to the Haskell Foreign Function Interface,
- whose definition is part of the Haskell Report on <ulink url="http://www.haskell.org/"><literal>http://www.haskell.org/</literal></ulink>.</para>
-
- <para>FFI support is enabled by default, but can be enabled or disabled explicitly with the <option>-XForeignFunctionInterface</option><indexterm><primary><option>-XForeignFunctionInterface</option></primary>
- </indexterm> flag.</para>
-
- <para>GHC implements a number of GHC-specific extensions to the FFI
- Addendum. These extensions are described in <xref linkend="ffi-ghcexts" />, but please note that programs using
- these features are not portable. Hence, these features should be
- avoided where possible.</para>
-
- <para>The FFI libraries are documented in the accompanying library
- documentation; see for example the
- <ulink url="&libraryBaseLocation;/Control-Concurrent.html"><literal>Foreign</literal></ulink> module.</para>
-
- <sect1 id="ffi-ghcexts">
- <title>GHC extensions to the FFI Addendum</title>
-
- <para>The FFI features that are described in this section are specific to
- GHC. Your code will not be portable to other compilers if you use them.</para>
-
- <sect2>
- <title>Unboxed types</title>
-
- <para>The following unboxed types may be used as basic foreign types
- (see FFI Addendum, Section 3.2): <literal>Int#</literal>,
- <literal>Word#</literal>, <literal>Char#</literal>,
- <literal>Float#</literal>, <literal>Double#</literal>,
- <literal>Addr#</literal>, <literal>StablePtr# a</literal>,
- <literal>MutableByteArray#</literal>, <literal>ForeignObj#</literal>,
- and <literal>ByteArray#</literal>.</para>
- </sect2>
-
- <sect2 id="ffi-newtype-io">
- <title>Newtype wrapping of the IO monad</title>
- <para>The FFI spec requires the IO monad to appear in various places,
- but it can sometimes be convenient to wrap the IO monad in a
- <literal>newtype</literal>, thus:
-<programlisting>
- newtype MyIO a = MIO (IO a)
-</programlisting>
- (A reason for doing so might be to prevent the programmer from
- calling arbitrary IO procedures in some part of the program.)
-</para>
-<para>The Haskell FFI already specifies that arguments and results of
-foreign imports and exports will be automatically unwrapped if they are
-newtypes (Section 3.2 of the FFI addendum). GHC extends the FFI by automatically unwrapping any newtypes that
-wrap the IO monad itself.
-More precisely, wherever the FFI specification requires an IO type, GHC will
-accept any newtype-wrapping of an IO type. For example, these declarations are
-OK:
-<programlisting>
- foreign import foo :: Int -> MyIO Int
- foreign import "dynamic" baz :: (Int -> MyIO Int) -> CInt -> MyIO Int
-</programlisting>
-</para>
- </sect2>
-
- <sect2 id="ffi-prim">
- <title>Primitive imports</title>
- <para>
- GHC extends the FFI with an additional calling convention
- <literal>prim</literal>, e.g.:
-<programlisting>
- foreign import prim "foo" foo :: ByteArray# -> (# Int#, Int# #)
-</programlisting>
- This is used to import functions written in Cmm code that follow an
- internal GHC calling convention. The arguments and results must
- be unboxed types, except that an argument may be of type
- <literal>Any</literal> (by way of <literal>unsafeCoerce#</literal>)
- and the result type is allowed to be an unboxed tuple or the
- type <literal>Any</literal>.
- </para>
- <para>
- This feature is not intended for
- use outside of the core libraries that come with GHC. For more
- details see the <ulink linkend="http://ghc.haskell.org/trac/ghc/wiki/Commentary/PrimOps">
- GHC developer wiki</ulink>.
- </para>
- </sect2>
-
- <sect2 id="ffi-interruptible">
- <title>Interruptible foreign calls</title>
- <para>
- This concerns the interaction of foreign calls
- with <literal>Control.Concurrent.throwTo</literal>.
- Normally when the target of a <literal>throwTo</literal> is
- involved in a foreign call, the exception is not raised
- until the call returns, and in the meantime the caller is
- blocked. This can result in unresponsiveness, which is
- particularly undesirable in the case of user interrupt
- (e.g. Control-C). The default behaviour when a Control-C
- signal is received (<literal>SIGINT</literal> on Unix) is to raise
- the <literal>UserInterrupt</literal> exception in the main
- thread; if the main thread is blocked in a foreign call at
- the time, then the program will not respond to the user
- interrupt.
- </para>
-
- <para>
- The problem is that it is not possible in general to
- interrupt a foreign call safely. However, GHC does provide
- a way to interrupt blocking system calls which works for
- most system calls on both Unix and Windows. When the
- <literal>InterruptibleFFI</literal> extension is enabled,
- a foreign call
- can be annotated with <literal>interruptible</literal> instead
- of <literal>safe</literal> or <literal>unsafe</literal>:
-
-<programlisting>
-foreign import ccall interruptible
- "sleep" sleepBlock :: CUint -> IO CUint
-</programlisting>
-
- <literal>interruptible</literal> behaves exactly as
- <literal>safe</literal>, except that when
- a <literal>throwTo</literal> is directed at a thread in an
- interruptible foreign call, an OS-specific mechanism will be
- used to attempt to cause the foreign call to return:
-
- <variablelist>
- <varlistentry>
- <term>Unix systems</term>
- <listitem>
- <para>
- The thread making the foreign call is sent
- a <literal>SIGPIPE</literal> signal
- using <literal>pthread_kill()</literal>. This is
- usually enough to cause a blocking system call to
- return with <literal>EINTR</literal> (GHC by default
- installs an empty signal handler
- for <literal>SIGPIPE</literal>, to override the
- default behaviour which is to terminate the process
- immediately).
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Windows systems</term>
- <listitem>
- <para>
- [Vista and later only] The RTS calls the Win32
- function <literal>CancelSynchronousIO</literal>,
- which will cause a blocking I/O operation to return
- with the
- error <literal>ERROR_OPERATION_ABORTED</literal>.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- If the system call is successfully interrupted, it will
- return to Haskell whereupon the exception can be raised. Be
- especially careful when
- using <literal>interruptible</literal> that the caller of
- the foreign function is prepared to deal with the
- consequences of the call being interrupted; on Unix it is
- good practice to check for <literal>EINTR</literal> always,
- but on Windows it is not typically necessary to
- handle <literal>ERROR_OPERATION_ABORTED</literal>.
- </para>
- </sect2>
-
- <sect2 id="ffi-capi">
- <title>The CAPI calling convention</title>
- <para>
- The <literal>CApiFFI</literal> extension allows a calling
- convention of <literal>capi</literal> to be used in foreign
- declarations, e.g.
-
-<programlisting>
-foreign import capi "header.h f" f :: CInt -> IO CInt
-</programlisting>
-
- Rather than generating code to call <literal>f</literal>
- according to the platform's ABI, we instead call
- <literal>f</literal> using the C API defined in the header
- <literal>header.h</literal>. Thus <literal>f</literal> can be
- called even if it may be defined as a CPP
- <literal>#define</literal> rather than a proper function.
- </para>
-
- <para>
- When using <literal>capi</literal>, it is also possible to
- import values, rather than functions. For example,
-
-<programlisting>
-foreign import capi "pi.h value pi" c_pi :: CDouble
-</programlisting>
-
- will work regardless of whether <literal>pi</literal> is
- defined as
-<programlisting>
-const double pi = 3.14;
-</programlisting>
- or with
-<programlisting>
-#define pi 3.14
-</programlisting>
- </para>
-
- <para>
- In order to tell GHC the C type that a Haskell type
- corresponds to when it is used with the CAPI, a
- <literal>CTYPE</literal> pragma can be used on the type
- definition. The header which defines the type can optionally
- also be specified. The syntax looks like:
-
-<programlisting>
-data {-# CTYPE "unistd.h" "useconds_t" #-} T = ...
-newtype {-# CTYPE "useconds_t" #-} T = ...
-</programlisting>
- </para>
- </sect2>
-
- <sect2>
- <title><literal>hs_thread_done()</literal></title>
-
-<programlisting>
-void hs_thread_done(void);
-</programlisting>
-
- <para>
- GHC allocates a small amount of thread-local memory when a
- thread calls a Haskell function via a <literal>foreign
- export</literal>. This memory is not normally freed until
- <literal>hs_exit()</literal>; the memory is cached so that
- subsequent calls into Haskell are fast. However, if your
- application is long-running and repeatedly creates new
- threads that call into Haskell, you probably want to arrange
- that this memory is freed in those threads that have
- finished calling Haskell functions. To do this, call
- <literal>hs_thread_done()</literal> from the thread whose
- memory you want to free.
- </para>
-
- <para>
- Calling <literal>hs_thread_done()</literal> is entirely
- optional. You can call it as often or as little as you
- like. It is safe to call it from a thread that has never
- called any Haskell functions, or one that never will. If
- you forget to call it, the worst that can happen is that
- some memory remains allocated until
- <literal>hs_exit()</literal> is called. If you call it too
- often, the worst that can happen is that the next call to a
- Haskell function incurs some extra overhead.
- </para>
- </sect2>
- </sect1>
-
- <sect1 id="ffi-ghc">
- <title>Using the FFI with GHC</title>
-
- <para>The following sections also give some hints and tips on the
- use of the foreign function interface in GHC.</para>
-
- <sect2 id="foreign-export-ghc">
- <title>Using <literal>foreign export</literal> and <literal>foreign import ccall "wrapper"</literal> with GHC</title>
-
- <indexterm><primary><literal>foreign export
- </literal></primary><secondary>with GHC</secondary>
- </indexterm>
-
- <para>When GHC compiles a module (say <filename>M.hs</filename>)
- which uses <literal>foreign export</literal> or
- <literal>foreign import "wrapper"</literal>, it generates
- a <filename>M_stub.h</filename> for use by C programs.</para>
-
- <para>For a plain <literal>foreign export</literal>, the file
- <filename>M_stub.h</filename> contains a C prototype for the
- foreign exported function. For example, if we compile the
- following module:</para>
-
-<programlisting>
-module Foo where
-
-foreign export ccall foo :: Int -> IO Int
-
-foo :: Int -> IO Int
-foo n = return (length (f n))
-
-f :: Int -> [Int]
-f 0 = []
-f n = n:(f (n-1))</programlisting>
-
- <para>Then <filename>Foo_stub.h</filename> will contain
- something like this:</para>
-
-<programlisting>
-#include "HsFFI.h"
-extern HsInt foo(HsInt a0);</programlisting>
-
- <para>To invoke <literal>foo()</literal> from C, just <literal>#include
- "Foo_stub.h"</literal> and call <literal>foo()</literal>.</para>
-
- <para>The
- <filename>Foo_stub.h</filename> file can be redirected using the
- <option>-stubdir</option> option; see <xref linkend="options-output"
- />.</para>
-
- <sect3 id="using-own-main">
- <title>Using your own <literal>main()</literal></title>
-
- <para>Normally, GHC's runtime system provides a
- <literal>main()</literal>, which arranges to invoke
- <literal>Main.main</literal> in the Haskell program. However,
- you might want to link some Haskell code into a program which
- has a main function written in another language, say C. In
- order to do this, you have to initialize the Haskell runtime
- system explicitly.</para>
-
- <para>Let's take the example from above, and invoke it from a
- standalone C program. Here's the C code:</para>
-
-<programlisting>
-#include &lt;stdio.h&gt;
-#include "HsFFI.h"
-
-#ifdef __GLASGOW_HASKELL__
-#include "Foo_stub.h"
-#endif
-
-int main(int argc, char *argv[])
-{
- int i;
-
- hs_init(&amp;argc, &amp;argv);
-
- for (i = 0; i &lt; 5; i++) {
- printf("%d\n", foo(2500));
- }
-
- hs_exit();
- return 0;
-}</programlisting>
-
- <para>We've surrounded the GHC-specific bits with
- <literal>#ifdef __GLASGOW_HASKELL__</literal>; the rest of the
- code should be portable across Haskell implementations that
- support the FFI standard.</para>
-
- <para>The call to <literal>hs_init()</literal>
- initializes GHC's runtime system. Do NOT try to invoke any
- Haskell functions before calling
- <literal>hs_init()</literal>: bad things will
- undoubtedly happen.</para>
-
- <para>We pass references to <literal>argc</literal> and
- <literal>argv</literal> to <literal>hs_init()</literal>
- so that it can separate out any arguments for the RTS
- (i.e. those arguments between
- <literal>+RTS...-RTS</literal>).</para>
-
- <para>After we've finished invoking our Haskell functions, we
- can call <literal>hs_exit()</literal>, which terminates the
- RTS.</para>
-
- <para>There can be multiple calls to
- <literal>hs_init()</literal>, but each one should be matched
- by one (and only one) call to
- <literal>hs_exit()</literal><footnote><para>The outermost
- <literal>hs_exit()</literal> will actually de-initialise the
- system. NOTE that currently GHC's runtime cannot reliably
- re-initialise after this has happened,
- see <xref linkend="infelicities-ffi" />.</para>
- </footnote>.</para>
-
- <para>NOTE: when linking the final program, it is normally
- easiest to do the link using GHC, although this isn't
- essential. If you do use GHC, then don't forget the flag
- <option>-no-hs-main</option><indexterm><primary><option>-no-hs-main</option></primary>
- </indexterm>, otherwise GHC will try to link
- to the <literal>Main</literal> Haskell module.</para>
-
- <para>To use <literal>+RTS</literal> flags
- with <literal>hs_init()</literal>, we have to modify the
- example slightly. By default, GHC's RTS will only accept
- "safe"
- <literal>+RTS</literal> flags (see
- <xref linkend="options-linker" />), and
- the <option>-rtsopts</option><indexterm><primary><option>-rtsopts</option></primary></indexterm> link-time flag overrides this.
- However, <option>-rtsopts</option> has no effect
- when <option>-no-hs-main</option> is in use (and the same
- goes for <option>-with-rtsopts</option>). To set these
- options we have to call a GHC-specific API instead
- of <option>hs_init()</option>:</para>
-
-<programlisting>
-#include &lt;stdio.h&gt;
-#include "HsFFI.h"
-
-#ifdef __GLASGOW_HASKELL__
-#include "Foo_stub.h"
-#include "Rts.h"
-#endif
-
-int main(int argc, char *argv[])
-{
- int i;
-
-#if __GLASGOW_HASKELL__ >= 703
- {
- RtsConfig conf = defaultRtsConfig;
- conf.rts_opts_enabled = RtsOptsAll;
- hs_init_ghc(&amp;argc, &amp;argv, conf);
- }
-#else
- hs_init(&amp;argc, &amp;argv);
-#endif
-
- for (i = 0; i &lt; 5; i++) {
- printf("%d\n", foo(2500));
- }
-
- hs_exit();
- return 0;
-}</programlisting>
-
- <para>Note two changes: we included <literal>Rts.h</literal>,
- which defines the GHC-specific external RTS interface, and we
- called <literal>hs_init_ghc()</literal> instead
- of <literal>hs_init()</literal>, passing an argument of
- type <literal>RtsConfig</literal>.
- <literal>RtsConfig</literal> is a struct with various fields
- that affect the behaviour of the runtime system. Its
- definition is:</para>
-
-<programlisting>
-typedef struct {
- RtsOptsEnabledEnum rts_opts_enabled;
- const char *rts_opts;
-} RtsConfig;
-
-extern const RtsConfig defaultRtsConfig;
-
-typedef enum {
- RtsOptsNone, // +RTS causes an error
- RtsOptsSafeOnly, // safe RTS options allowed; others cause an error
- RtsOptsAll // all RTS options allowed
- } RtsOptsEnabledEnum;
-</programlisting>
-
- <para>There is a default
- value <literal>defaultRtsConfig</literal> that should be used
- to initialise variables of type <literal>RtsConfig</literal>.
- More fields will undoubtedly be added
- to <literal>RtsConfig</literal> in the future, so in order to
- keep your code forwards-compatible it is best to initialise
- with <literal>defaultRtsConfig</literal> and then modify the
- required fields, as in the code sample above.</para>
-
-
- </sect3>
-
- <sect3 id="ffi-library">
- <title>Making a Haskell library that can be called from foreign
- code</title>
-
- <para>The scenario here is much like in <xref linkend="using-own-main"
- />, except that the aim is not to link a complete program, but to
- make a library from Haskell code that can be deployed in the same
- way that you would deploy a library of C code.</para>
-
- <para>The main requirement here is that the runtime needs to be
- initialized before any Haskell code can be called, so your library
- should provide initialisation and deinitialisation entry points,
- implemented in C or C++. For example:</para>
-
-<programlisting>
-#include &lt;stdlib.h&gt;
-#include "HsFFI.h"
-
-HsBool mylib_init(void){
- int argc = 2;
- char *argv[] = { "+RTS", "-A32m", NULL };
- char **pargv = argv;
-
- // Initialize Haskell runtime
- hs_init(&amp;argc, &amp;pargv);
-
- // do any other initialization here and
- // return false if there was a problem
- return HS_BOOL_TRUE;
-}
-
-void mylib_end(void){
- hs_exit();
-}
-</programlisting>
-
- <para>The initialisation routine, <literal>mylib_init</literal>, calls
- <literal>hs_init()</literal> as
- normal to initialise the Haskell runtime, and the corresponding
- deinitialisation function <literal>mylib_end()</literal> calls
- <literal>hs_exit()</literal> to shut down the runtime.</para>
- </sect3>
-
- </sect2>
-
- <sect2 id="glasgow-foreign-headers">
- <title>Using header files</title>
-
- <indexterm><primary>C calls, function headers</primary></indexterm>
-
- <para>C functions are normally declared using prototypes in a C
- header file. Earlier versions of GHC (6.8.3 and
- earlier) <literal>&num;include</literal>d the header file in
- the C source file generated from the Haskell code, and the C
- compiler could therefore check that the C function being
- called via the FFI was being called at the right type.</para>
-
- <para>GHC no longer includes external header files when
- compiling via C, so this checking is not performed. The
- change was made for compatibility with the
- <ulink linkend="native-code-gen">native code generator</ulink>
- (<literal>-fasm</literal>) and to comply strictly with the FFI
- specification, which requires that FFI calls are not subject
- to macro expansion and other CPP conversions that may be
- applied when using C header files. This approach also
- simplifies the inlining of foreign calls across module and
- package boundaries: there's no need for the header file to be
- available when compiling an inlined version of a foreign call,
- so the compiler is free to inline foreign calls in any
- context.</para>
-
- <para>The <literal>-&num;include</literal> option is now
- deprecated, and the <literal>include-files</literal> field
- in a Cabal package specification is ignored.</para>
-
- </sect2>
-
- <sect2>
- <title>Memory Allocation</title>
-
- <para>The FFI libraries provide several ways to allocate memory
- for use with the FFI, and it isn't always clear which way is the
- best. This decision may be affected by how efficient a
- particular kind of allocation is on a given compiler/platform,
- so this section aims to shed some light on how the different
- kinds of allocation perform with GHC.</para>
-
- <variablelist>
- <varlistentry>
- <term><literal>alloca</literal> and friends</term>
- <listitem>
- <para>Useful for short-term allocation when the allocation
- is intended to scope over a given <literal>IO</literal>
- computation. This kind of allocation is commonly used
- when marshalling data to and from FFI functions.</para>
-
- <para>In GHC, <literal>alloca</literal> is implemented
- using <literal>MutableByteArray#</literal>, so allocation
- and deallocation are fast: much faster than C's
- <literal>malloc/free</literal>, but not quite as fast as
- stack allocation in C. Use <literal>alloca</literal>
- whenever you can.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>mallocForeignPtr</literal></term>
- <listitem>
- <para>Useful for longer-term allocation which requires
- garbage collection. If you intend to store the pointer to
- the memory in a foreign data structure, then
- <literal>mallocForeignPtr</literal> is
- <emphasis>not</emphasis> a good choice, however.</para>
-
- <para>In GHC, <literal>mallocForeignPtr</literal> is also
- implemented using <literal>MutableByteArray#</literal>.
- Although the memory is pointed to by a
- <literal>ForeignPtr</literal>, there are no actual
- finalizers involved (unless you add one with
- <literal>addForeignPtrFinalizer</literal>), and the
- deallocation is done using GC, so
- <literal>mallocForeignPtr</literal> is normally very
- cheap.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>malloc/free</literal></term>
- <listitem>
- <para>If all else fails, then you need to resort to
- <literal>Foreign.malloc</literal> and
- <literal>Foreign.free</literal>. These are just wrappers
- around the C functions of the same name, and their
- efficiency will depend ultimately on the implementations
- of these functions in your platform's C library. We
- usually find <literal>malloc</literal> and
- <literal>free</literal> to be significantly slower than
- the other forms of allocation above.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><literal>Foreign.Marshal.Pool</literal></term>
- <listitem>
- <para>Pools are currently implemented using
- <literal>malloc/free</literal>, so while they might be a
- more convenient way to structure your memory allocation
- than using one of the other forms of allocation, they
- won't be any more efficient. We do plan to provide an
- improved-performance implementation of Pools in the
- future, however.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </sect2>
-
- <sect2 id="ffi-threads">
- <title>Multi-threading and the FFI</title>
-
- <para>In order to use the FFI in a multi-threaded setting, you must
- use the <option>-threaded</option> option
- (see <xref linkend="options-linker" />).</para>
-
- <sect3>
- <title>Foreign imports and multi-threading</title>
-
- <para>When you call a <literal>foreign import</literal>ed
- function that is annotated as <literal>safe</literal> (the
- default), and the program was linked
- using <option>-threaded</option>, then the call will run
- concurrently with other running Haskell threads. If the
- program was linked without <option>-threaded</option>,
- then the other Haskell threads will be blocked until the
- call returns.</para>
-
- <para>This means that if you need to make a foreign call to
- a function that takes a long time or blocks indefinitely,
- then you should mark it <literal>safe</literal> and
- use <option>-threaded</option>. Some library functions
- make such calls internally; their documentation should
- indicate when this is the case.</para>
-
- <para>If you are making foreign calls from multiple Haskell
- threads and using <option>-threaded</option>, make sure that
- the foreign code you are calling is thread-safe. In
- particularly, some GUI libraries are not thread-safe and
- require that the caller only invokes GUI methods from a
- single thread. If this is the case, you may need to
- restrict your GUI operations to a single Haskell thread,
- and possibly also use a bound thread (see
- <xref linkend="haskell-threads-and-os-threads" />).</para>
-
- <para>Note that foreign calls made by different Haskell
- threads may execute in <emphasis>parallel</emphasis>, even
- when the <literal>+RTS -N</literal> flag is not being used
- (<xref linkend="parallel-options" />). The <literal>+RTS
- -N</literal> flag controls parallel execution of Haskell
- threads, but there may be an arbitrary number of foreign
- calls in progress at any one time, regardless of
- the <literal>+RTS -N</literal> value.</para>
-
- <para>If a call is annotated as <literal>interruptible</literal>
- and the program was multithreaded, the call may be
- interrupted in the event that the Haskell thread receives an
- exception. The mechanism by which the interrupt occurs
- is platform dependent, but is intended to cause blocking
- system calls to return immediately with an interrupted error
- code. The underlying operating system thread is not to be
- destroyed. See <xref linkend="ffi-interruptible"/> for more details.</para>
- </sect3>
-
- <sect3 id="haskell-threads-and-os-threads">
- <title>The relationship between Haskell threads and OS
- threads</title>
-
- <para>Normally there is no fixed relationship between Haskell
- threads and OS threads. This means that when you make a
- foreign call, that call may take place in an unspecified OS
- thread. Furthermore, there is no guarantee that multiple
- calls made by one Haskell thread will be made by the same OS
- thread.</para>
-
- <para>This usually isn't a problem, and it allows the GHC
- runtime system to make efficient use of OS thread resources.
- However, there are cases where it is useful to have more
- control over which OS thread is used, for example when
- calling foreign code that makes use of thread-local state.
- For cases like this, we provide <emphasis>bound
- threads</emphasis>, which are Haskell threads tied to a
- particular OS thread. For information on bound threads, see
- the documentation
- for the <ulink url="&libraryBaseLocation;/Control-Concurrent.html"><literal>Control.Concurrent</literal></ulink>
- module.</para>
- </sect3>
-
- <sect3>
- <title>Foreign exports and multi-threading</title>
-
- <para>When the program is linked
- with <option>-threaded</option>, then you may
- invoke <literal>foreign export</literal>ed functions from
- multiple OS threads concurrently. The runtime system must
- be initialised as usual by
- calling <literal>hs_init()</literal>, and this call must
- complete before invoking any <literal>foreign
- export</literal>ed functions.</para>
- </sect3>
-
- <sect3 id="hs-exit">
- <title>On the use of <literal>hs_exit()</literal></title>
-
- <para><literal>hs_exit()</literal> normally causes the termination of
- any running Haskell threads in the system, and when
- <literal>hs_exit()</literal> returns, there will be no more Haskell
- threads running. The runtime will then shut down the system in an
- orderly way, generating profiling
- output and statistics if necessary, and freeing all the memory it
- owns.</para>
-
- <para>It isn't always possible to terminate a Haskell thread forcibly:
- for example, the thread might be currently executing a foreign call,
- and we have no way to force the foreign call to complete. What's
- more, the runtime must
- assume that in the worst case the Haskell code and runtime are about
- to be removed from memory (e.g. if this is a <link linkend="win32-dlls">Windows DLL</link>,
- <literal>hs_exit()</literal> is normally called before unloading the
- DLL). So <literal>hs_exit()</literal> <emphasis>must</emphasis> wait
- until all outstanding foreign calls return before it can return
- itself.</para>
-
- <para>The upshot of this is that if you have Haskell threads that are
- blocked in foreign calls, then <literal>hs_exit()</literal> may hang
- (or possibly busy-wait) until the calls return. Therefore it's a
- good idea to make sure you don't have any such threads in the system
- when calling <literal>hs_exit()</literal>. This includes any threads
- doing I/O, because I/O may (or may not, depending on the
- type of I/O and the platform) be implemented using blocking foreign
- calls.</para>
-
- <para>The GHC runtime treats program exit as a special case, to avoid
- the need to wait for blocked threads when a standalone
- executable exits. Since the program and all its threads are about to
- terminate at the same time that the code is removed from memory, it
- isn't necessary to ensure that the threads have exited first.
- (Unofficially, if you want to use this fast and loose version of
- <literal>hs_exit()</literal>, then call
- <literal>shutdownHaskellAndExit()</literal> instead).</para>
- </sect3>
- </sect2>
-
- <sect2 id="ffi-floating-point">
- <title>Floating point and the FFI</title>
-
- <para>
- The standard C99 <literal>fenv.h</literal> header
- provides operations for inspecting and modifying the state of
- the floating point unit. In particular, the rounding mode
- used by floating point operations can be changed, and the
- exception flags can be tested.
- </para>
-
- <para>
- In Haskell, floating-point operations have pure types, and the
- evaluation order is unspecified. So strictly speaking, since
- the <literal>fenv.h</literal> functions let you change the
- results of, or observe the effects of floating point
- operations, use of <literal>fenv.h</literal> renders the
- behaviour of floating-point operations anywhere in the program
- undefined.
- </para>
-
- <para>
- Having said that, we <emphasis>can</emphasis> document exactly
- what GHC does with respect to the floating point state, so
- that if you really need to use <literal>fenv.h</literal> then
- you can do so with full knowledge of the pitfalls:
- <itemizedlist>
- <listitem>
- <para>
- GHC completely ignores the floating-point
- environment, the runtime neither modifies nor reads it.
- </para>
- </listitem>
- <listitem>
- <para>
- The floating-point environment is not saved over a
- normal thread context-switch. So if you modify the
- floating-point state in one thread, those changes may be
- visible in other threads. Furthermore, testing the
- exception state is not reliable, because a context
- switch may change it. If you need to modify or test the
- floating point state and use threads, then you must use
- bound threads
- (<literal>Control.Concurrent.forkOS</literal>), because
- a bound thread has its own OS thread, and OS threads do
- save and restore the floating-point state.
- </para>
- </listitem>
- <listitem>
- <para>
- It is safe to modify the floating-point unit state
- temporarily during a foreign call, because foreign calls
- are never pre-empted by GHC.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- </sect2>
- </sect1>
-</chapter>
-
-<!-- Emacs stuff:
- ;;; Local Variables: ***
- ;;; sgml-parent-document: ("users_guide.xml" "book" "chapter") ***
- ;;; End: ***
- -->