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
+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
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
of <literal>safe</literal> or <literal>unsafe</literal>:
<programlisting>
-foreign import ccall interruptible
+foreign import ccall interruptible
"sleep" :: CUint -> IO CUint
</programlisting>
- <literal>interruptble</literal> behaves exactly as
+ <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
</indexterm>
<para>When GHC compiles a module (say <filename>M.hs</filename>)
- which uses <literal>foreign export</literal> or
+ which uses <literal>foreign export</literal> or
<literal>foreign import "wrapper"</literal>, it generates two
additional files, <filename>M_stub.c</filename> and
<filename>M_stub.h</filename>. GHC will automatically compile
––make</literal>, as GHC will automatically link in the
correct bits).</para>
- <sect3 id="using-own-main">
+ <sect3 id="using-own-main">
<title>Using your own <literal>main()</literal></title>
<para>Normally, GHC's runtime system provides a
#include "foo_stub.h"
#endif
-#ifdef __GLASGOW_HASKELL__
-extern void __stginit_Foo ( void );
-#endif
-
int main(int argc, char *argv[])
{
int i;
hs_init(&argc, &argv);
-#ifdef __GLASGOW_HASKELL__
- hs_add_root(__stginit_Foo);
-#endif
for (i = 0; i < 5; i++) {
printf("%d\n", foo(2500));
(i.e. those arguments between
<literal>+RTS...-RTS</literal>).</para>
- <para>Next, we call
- <function>hs_add_root</function><indexterm><primary><function>hs_add_root</function></primary>
- </indexterm>, a GHC-specific interface which is required to
- initialise the Haskell modules in the program. The argument
- to <function>hs_add_root</function> should be the name of the
- initialization function for the "root" module in your program
- - in other words, the module which directly or indirectly
- imports all the other Haskell modules in the program. In a
- standalone Haskell program the root module is normally
- <literal>Main</literal>, but when you are using Haskell code
- from a library it may not be. If your program has multiple
- root modules, then you can call
- <function>hs_add_root</function> multiple times, one for each
- root. The name of the initialization function for module
- <replaceable>M</replaceable> is
- <literal>__stginit_<replaceable>M</replaceable></literal>, and
- it may be declared as an external function symbol as in the
- code above. Note that the symbol name should be transformed
- according to the Z-encoding:</para>
-
<informaltable>
<tgroup cols="2" align="left" colsep="1" rowsep="1">
<thead>
// Initialize Haskell runtime
hs_init(&argc, &argv);
- // Tell Haskell about all root modules
- hs_add_root(__stginit_Foo);
-
// do any other initialization here and
// return false if there was a problem
return HS_BOOL_TRUE;
</programlisting>
<para>The initialisation routine, <literal>mylib_init</literal>, calls
- <literal>hs_init()</literal> and <literal>hs_add_root()</literal> as
+ <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>
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>
</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
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
<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
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 <literal>hs_add_root</literal>, and these calls must
+ calling <literal>hs_init()</literal>, and this call must
complete before invoking any <literal>foreign
export</literal>ed functions.</para>
</sect3>
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>
+ <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>