diff options
Diffstat (limited to 'docs/users_guide/ffi-chap.xml')
-rw-r--r-- | docs/users_guide/ffi-chap.xml | 818 |
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 <stdio.h> -#include "HsFFI.h" - -#ifdef __GLASGOW_HASKELL__ -#include "Foo_stub.h" -#endif - -int main(int argc, char *argv[]) -{ - int i; - - hs_init(&argc, &argv); - - for (i = 0; i < 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 <stdio.h> -#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(&argc, &argv, conf); - } -#else - hs_init(&argc, &argv); -#endif - - for (i = 0; i < 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 <stdlib.h> -#include "HsFFI.h" - -HsBool mylib_init(void){ - int argc = 2; - char *argv[] = { "+RTS", "-A32m", NULL }; - char **pargv = argv; - - // Initialize Haskell runtime - hs_init(&argc, &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>#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>-#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: *** - --> |