Change the way module initialisation is done (#3252, #4417)
[ghc-hetmet.git] / docs / users_guide / ffi-chap.xml
index 2e6ce2f..97a2378 100644 (file)
@@ -6,10 +6,10 @@
 Foreign function interface (FFI)
  </title>
 
-  <para>GHC (mostly) conforms to the Haskell 98 Foreign Function Interface
-  Addendum 1.0, whose definition is available from <ulink url="http://www.haskell.org/"><literal>http://www.haskell.org/</literal></ulink>.</para>
+  <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>To enable FFI support in GHC, give the <option>-XForeignFunctionInterface</option><indexterm><primary><option>-XForeignFunctionInterface</option></primary>
+  <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
@@ -245,18 +245,11 @@ extern HsInt foo(HsInt a0);</programlisting>
 #include "foo_stub.h"
 #endif
 
-#ifdef __GLASGOW_HASKELL__
-extern void __stginit_Foo ( void );
-#endif
-
 int main(int argc, char *argv[])
 {
   int i;
 
   hs_init(&amp;argc, &amp;argv);
-#ifdef __GLASGOW_HASKELL__
-  hs_add_root(__stginit_Foo);
-#endif
 
   for (i = 0; i &lt; 5; i++) {
     printf("%d\n", foo(2500));
@@ -283,26 +276,6 @@ int main(int argc, char *argv[])
        (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>
@@ -380,9 +353,6 @@ int main(int argc, char *argv[])
    // Initialize Haskell runtime
    hs_init(&amp;argc, &amp;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;
@@ -394,7 +364,7 @@ int main(int argc, char *argv[])
 </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>
@@ -599,8 +569,7 @@ int main(int argc, char *argv[])
           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>
@@ -646,7 +615,65 @@ int main(int argc, char *argv[])
           <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>