[project @ 2004-01-06 12:40:00 by simonmar]
authorsimonmar <unknown>
Tue, 6 Jan 2004 12:40:01 +0000 (12:40 +0000)
committersimonmar <unknown>
Tue, 6 Jan 2004 12:40:01 +0000 (12:40 +0000)
Fix, and simplify, the getting/setting of errno in Foreign.C.Error.

It was previously wrong: although we called a C function to get the
location of errno (correct), we cached the result in a CAF which was
wrong because the location is OS thread dependent.  We must call the C
function every time we need the value of errno.

I also simplified things by making the getter/setter functions inlined
in the same way as the other C fragments in this library, and putting
them in HsBase.h.

MERGE TO STABLE

Foreign/C/Error.hs
cbits/errno.c [deleted file]
include/HsBase.h
include/ghc_errno.h [deleted file]

index db17f5f..9b7059d 100644 (file)
@@ -123,16 +123,6 @@ import System.IO.Unsafe            ( unsafePerformIO )
 -- "errno" type
 -- ------------
 
--- import of C function that gives address of errno
--- This function exists because errno is a variable on some systems, but on
--- Windows it is a macro for a function...
--- [yes, global variables and thread safety don't really go hand-in-hand. -- sof]
-#ifdef __NHC__
-foreign import ccall unsafe "errno.h &errno" _errno :: Ptr CInt
-#else
-foreign import ccall unsafe "HsBase.h ghcErrno" _errno :: Ptr CInt
-#endif
-
 -- Haskell representation for "errno" values
 --
 newtype Errno = Errno CInt
@@ -282,13 +272,29 @@ isValidErrno (Errno errno)  = errno /= -1
 -- yield the current thread's "errno" value
 --
 getErrno :: IO Errno
-getErrno  = do e <- peek _errno; return (Errno e)
+
+-- We must call a C function to get the value of errno in general.  On
+-- threaded systems, errno is hidden behind a C macro so that each OS
+-- thread gets its own copy.
+#ifdef __NHC__
+getErrno = do e <- peek _errno; return (Errno e)
+foreign import ccall unsafe "errno.h &errno" _errno :: IO (Ptr CInt)
+#else
+getErrno = do e <- get_errno; return (Errno e)
+foreign import ccall unsafe "HsBase.h __hscore_get_errno" get_errno :: IO CInt
+#endif
 
 -- set the current thread's "errno" value to 0
 --
 resetErrno :: IO ()
-resetErrno  = poke _errno 0
 
+-- Again, setting errno has to be done via a C function.
+#ifdef __NHC__
+resetErrno = poke _errno 0
+#else
+resetErrno = set_errno 0
+foreign import ccall unsafe "HsBase.h __hscore_set_errno" set_errno :: CInt -> IO ()
+#endif
 
 -- throw current "errno" value
 -- ---------------------------
diff --git a/cbits/errno.c b/cbits/errno.c
deleted file mode 100644 (file)
index 04eae07..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/* 
- * (c) The University of Glasgow, 2000-2001
- *
- * $Id: errno.c,v 1.5 2002/09/25 15:24:07 simonmar Exp $
- *
- * GHC Error Number Conversion
- */
-
-#include "HsBase.h"
-
-/* Raw errno */
-/* Covers up the fact that on Windows this is a function */
-
-int *ghcErrno(void) {
-  return &errno;
-}
index 71fd475..9db6133 100644 (file)
 #include "timeUtils.h"
 #endif
 
-/* in ghc_errno.c */
-int *ghcErrno(void);
-
 /* in system.c */
 HsInt systemCmd(HsAddr cmd);
 
@@ -206,6 +203,9 @@ StgWord64 stg_integerToWord64 (StgInt sa, StgByteArray /* Really: mp_limb_t* */
 # endif
 #endif
 
+INLINE int __hscore_get_errno(void) { return errno; }
+INLINE int __hscore_set_errno(int e) { errno = e; }
+
 #if !defined(_MSC_VER)
 INLINE int __hscore_s_isreg(m)  { return S_ISREG(m);  }
 INLINE int __hscore_s_isdir(m)  { return S_ISDIR(m);  }
diff --git a/include/ghc_errno.h b/include/ghc_errno.h
deleted file mode 100644 (file)
index 33b5dce..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* -----------------------------------------------------------------------------
- * $Id: ghc_errno.h,v 1.1 2001/06/28 14:15:04 simonmar Exp $
- *
- * (c) The GHC Team 2001
- *
- * Haskell-usable version of errno
- *
- * ---------------------------------------------------------------------------*/
-
-#ifndef GHCERRNO_H
-#define GHCERRNO_H
-
-int *ghcErrno(void);
-
-#endif