X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=docs%2Fusers_guide%2Fffi-chap.xml;h=97a237876ff69a4d0f865f7faea4b0dedfccc4ff;hb=6cec61d14a324285dbb8ce73d4c7215f1f8d6766;hp=f9f52aec85b363eb61ef40e20f3410c3848e1b51;hpb=2d83b718db7197e451d7a47edc7611fa455bbe8d;p=ghc-hetmet.git
diff --git a/docs/users_guide/ffi-chap.xml b/docs/users_guide/ffi-chap.xml
index f9f52ae..97a2378 100644
--- a/docs/users_guide/ffi-chap.xml
+++ b/docs/users_guide/ffi-chap.xml
@@ -6,10 +6,10 @@
Foreign function interface (FFI)
- GHC (mostly) conforms to the Haskell 98 Foreign Function Interface
- Addendum 1.0, whose definition is available from http://www.haskell.org/.
+ GHC (mostly) conforms to the Haskell Foreign Function Interface,
+ whose definition is part of the Haskell Report on http://www.haskell.org/.
- To enable FFI support in GHC, give the
+ FFI support is enabled by default, but can be enabled or disabled explicitly with the flag.GHC implements a number of GHC-specific extensions to the FFI
@@ -19,7 +19,7 @@ Foreign function interface (FFI)
The FFI libraries are documented in the accompanying library
documentation; see for example the
- Foreign module.
+ Foreign module.GHC extensions to the FFI Addendum
@@ -78,6 +78,86 @@ OK:
details see the GHC developer wiki.
+
+
+ Interruptible foreign calls
+
+ This concerns the interaction of foreign calls
+ with Control.Concurrent.throwTo.
+ Normally when the target of a throwTo 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 (SIGINT on Unix) is to raise
+ the UserInterrupt 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.
+
+
+
+ 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. A foreign call
+ can be annotated with interruptible instead
+ of safe or unsafe:
+
+
+foreign import ccall interruptible
+ "sleep" :: CUint -> IO CUint
+
+
+ interruptble behaves exactly as
+ safe, except that when
+ a throwTo 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:
+
+
+
+ Unix systems
+
+
+ The thread making the foreign call is sent
+ a SIGPIPE signal
+ using pthread_kill(). This is
+ usually enough to cause a blocking system call to
+ return with EINTR (GHC by default
+ installs an empty signal handler
+ for SIGPIPE, to override the
+ default behaviour which is to terminate the process
+ immediately).
+
+
+
+
+ Windows systems
+
+
+ [Vista and later only] The RTS calls the Win32
+ function CancelSynchronousIO,
+ which will cause a blocking I/O operation to return
+ with the
+ error ERROR_OPERATION_ABORTED.
+
+
+
+
+
+ If the system call is successfully interrupted, it will
+ return to Haskell whereupon the exception can be raised. Be
+ especially careful when
+ using interruptible 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 EINTR always,
+ but on Windows it is not typically necessary to
+ handle ERROR_OPERATION_ABORTED.
+
+
@@ -165,18 +245,11 @@ extern HsInt foo(HsInt a0);
#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));
@@ -203,26 +276,6 @@ int main(int argc, char *argv[])
(i.e. those arguments between
+RTS...-RTS).
- Next, we call
- hs_add_rooths_add_root
- , a GHC-specific interface which is required to
- initialise the Haskell modules in the program. The argument
- to hs_add_root 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
- Main, 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
- hs_add_root multiple times, one for each
- root. The name of the initialization function for module
- M is
- __stginit_M, 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:
-
@@ -300,9 +353,6 @@ int main(int argc, char *argv[])
// 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;
@@ -314,7 +364,7 @@ int main(int argc, char *argv[])
The initialisation routine, mylib_init, calls
- hs_init() and hs_add_root() as
+ hs_init() as
normal to initialise the Haskell runtime, and the corresponding
deinitialisation function mylib_end() calls
hs_exit() to shut down the runtime.
@@ -476,6 +526,15 @@ int main(int argc, char *argv[])
threads, but there may be an arbitrary number of foreign
calls in progress at any one time, regardless of
the +RTS -N value.
+
+ If a call is annotated as interruptible
+ 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 for more details.
@@ -498,7 +557,7 @@ int main(int argc, char *argv[])
threads, which are Haskell threads tied to a
particular OS thread. For information on bound threads, see
the documentation
- for the Control.Concurrent
+ for the Control.Concurrent
module.
@@ -510,8 +569,7 @@ int main(int argc, char *argv[])
invoke foreign exported functions from
multiple OS threads concurrently. The runtime system must
be initialised as usual by
- calling hs_init()
- and hs_add_root, and these calls must
+ calling hs_init(), and this call must
complete before invoking any foreign
exported functions.
@@ -557,13 +615,70 @@ int main(int argc, char *argv[])
shutdownHaskellAndExit() instead).
-
+
+
+ Floating point and the FFI
+
+
+ The standard C99 fenv.h 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.
+
+
+
+ In Haskell, floating-point operations have pure types, and the
+ evaluation order is unspecified. So strictly speaking, since
+ the fenv.h functions let you change the
+ results of, or observe the effects of floating point
+ operations, use of fenv.h renders the
+ behaviour of floating-point operations anywhere in the program
+ undefined.
+
+
+
+ Having said that, we can document exactly
+ what GHC does with respect to the floating point state, so
+ that if you really need to use fenv.h then
+ you can do so with full knowledge of the pitfalls:
+
+
+
+ GHC completely ignores the floating-point
+ environment, the runtime neither modifies nor reads it.
+
+
+
+
+ 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
+ (Control.Concurrent.forkOS), because
+ a bound thread has its own OS thread, and OS threads do
+ save and restore the floating-point state.
+
+
+
+
+ It is safe to modify the floating-point unit state
+ temporarily during a foreign call, because foreign calls
+ are never pre-empted by GHC.
+
+
+
+
+