diff options
author | Simon Marlow <simonmar@microsoft.com> | 2008-04-02 05:14:12 +0000 |
---|---|---|
committer | Simon Marlow <simonmar@microsoft.com> | 2008-04-02 05:14:12 +0000 |
commit | c245355e6f2c7b7c95e9af910c4d420e13af9413 (patch) | |
tree | e8309f467b8bea2501e9f7de7af86fbfc22e0a67 /includes | |
parent | ab5c770bed51f08d56a0d61086988053b21aa461 (diff) | |
download | haskell-c245355e6f2c7b7c95e9af910c4d420e13af9413.tar.gz |
Do not #include external header files when compiling via C
This has several advantages:
- -fvia-C is consistent with -fasm with respect to FFI declarations:
both bind to the ABI, not the API.
- foreign calls can now be inlined freely across module boundaries, since
a header file is not required when compiling the call.
- bootstrapping via C will be more reliable, because this difference
in behavour between the two backends has been removed.
There is one disadvantage:
- we get no checking by the C compiler that the FFI declaration
is correct.
So now, the c-includes field in a .cabal file is always ignored by
GHC, as are header files specified in an FFI declaration. This was
previously the case only for -fasm compilations, now it is also the
case for -fvia-C too.
Diffstat (limited to 'includes')
-rw-r--r-- | includes/README | 13 | ||||
-rw-r--r-- | includes/Regs.h | 23 | ||||
-rw-r--r-- | includes/Rts.h | 6 | ||||
-rw-r--r-- | includes/RtsExternal.h | 3 | ||||
-rw-r--r-- | includes/RtsTypeable.h | 2 | ||||
-rw-r--r-- | includes/SMP.h | 154 | ||||
-rw-r--r-- | includes/SMPClosureOps.h | 71 | ||||
-rw-r--r-- | includes/SpinLock.h | 110 | ||||
-rw-r--r-- | includes/Stg.h | 9 | ||||
-rw-r--r-- | includes/StgMiscClosures.h | 44 |
10 files changed, 256 insertions, 179 deletions
diff --git a/includes/README b/includes/README index a63d02705f..fef91fe0fd 100644 --- a/includes/README +++ b/includes/README @@ -64,33 +64,35 @@ Rts.h StgDLL.h /* stuff related to Windows DLLs */ MachRegs.h /* global register assignments for this arch */ Regs.h /* "registers" in the virtual machine */ - StgProf.h /* profiling gubbins */ StgMiscClosures.h /* decls for closures & info tables in the RTS */ - RtsExternal.h /* decls for RTS things required by .hc code */ - (RtsAPI.h) - (HsFFI.h) + SMP.h /* basic primitives for synchronisation */ RtsTypes.h /* types used in the RTS */ Constants.h /* build-time constants */ StgLdvProf.h StgFun.h + StgProf.h /* profiling gubbins */ Closures.h Liveness.h /* macros for constructing RET_DYN liveness masks */ ClosureMacros.h ClosureTypes.h InfoTables.h + SMPClosureOps.h /* lockClosure/unlockClosure etc. */ + SpinLock.h TSO.h Updates.h /* macros for performing updates */ GranSim.h Parallel.h - SMP.h Block.h Stable.h Hooks.h Signals.h DNInvoke.h Dotnet.h + RtsExternal.h /* decls for RTS things required by .hc code */ + (RtsAPI.h) + (HsFFI.h) Cmm.h /* included into .cmm source only */ DerivedConstants.h /* generated by mkDerivedConstants.c from other */ @@ -110,4 +112,3 @@ ieee-flpt.h /* ToDo: needed? */ RtsAPI.h /* The top-level interface to the RTS (rts_evalIO(), etc.) */ HsFFI.h /* The external FFI api */ - diff --git a/includes/Regs.h b/includes/Regs.h index 6524c8f669..0f974ec4ad 100644 --- a/includes/Regs.h +++ b/includes/Regs.h @@ -22,14 +22,6 @@ #ifndef REGS_H #define REGS_H -#if defined(HAVE_FRAMEWORK_GMP) -#include <GMP/gmp.h> -#elif defined(HAVE_LIB_GMP) -#include <gmp.h> -#else -#include "gmp.h" // Needs MP_INT definition -#endif - /* * Spark pools: used to store pending sparks * (THREADED_RTS & PARALLEL_HASKELL only) @@ -79,6 +71,11 @@ typedef union { StgTSOPtr t; } StgUnion; +// Urgh.. we don't know the size of an MP_INT here because we haven't +// #included gmp.h. We should really autoconf this, but GMP may not +// be available at ./configure time if we're building it (GMP) locally. +#define MP_INT_WORDS 3 + /* * This is the table that holds shadow-locations for all the STG * registers. The shadow locations are used when: @@ -117,11 +114,11 @@ typedef struct StgRegTable_ { // rmp_tmp1..rmp_result2 are only used in THREADED_RTS builds to // avoid per-thread temps in bss, but currently always incldue here // so we just run mkDerivedConstants once - StgWord rmp_tmp_w; - MP_INT rmp_tmp1; - MP_INT rmp_tmp2; - MP_INT rmp_result1; - MP_INT rmp_result2; + StgWord rmp_tmp_w[MP_INT_WORDS]; + StgWord rmp_tmp1[MP_INT_WORDS]; + StgWord rmp_tmp2[MP_INT_WORDS]; + StgWord rmp_result1[MP_INT_WORDS]; + StgWord rmp_result2[MP_INT_WORDS]; StgWord rRet; // holds the return code of the thread StgSparkPool rSparks; /* per-task spark pool */ } StgRegTable; diff --git a/includes/Rts.h b/includes/Rts.h index df8cb46900..cec93e68b0 100644 --- a/includes/Rts.h +++ b/includes/Rts.h @@ -18,6 +18,9 @@ extern "C" { #endif #include "Stg.h" +// ToDo: move RtsExternal stuff elsewhere +#include "RtsExternal.h" + // Turn off inlining when debugging - it obfuscates things #ifdef DEBUG # undef STATIC_INLINE @@ -165,7 +168,8 @@ TAG_CLOSURE(StgWord tag,StgClosure * p) /* Parallel information */ #include "Parallel.h" #include "OSThreads.h" -#include "SMP.h" +#include "SMPClosureOps.h" +#include "SpinLock.h" /* GNU mp library */ #if defined(HAVE_FRAMEWORK_GMP) diff --git a/includes/RtsExternal.h b/includes/RtsExternal.h index b95da387bd..24dace2b14 100644 --- a/includes/RtsExternal.h +++ b/includes/RtsExternal.h @@ -111,9 +111,6 @@ extern void setIOManagerPipe (int fd); extern void* allocateExec(unsigned int len); // Breakpoint stuff -extern int rts_stop_next_breakpoint; -extern int rts_stop_on_exception; -extern HsStablePtr rts_breakpoint_io_action; /* ----------------------------------------------------------------------------- Storage manager stuff exported diff --git a/includes/RtsTypeable.h b/includes/RtsTypeable.h index 28b59cdc13..343c514ace 100644 --- a/includes/RtsTypeable.h +++ b/includes/RtsTypeable.h @@ -9,8 +9,6 @@ #ifndef GHC_RTS_TYPEABLE_H
#define GHC_RTS_TYPEABLE_H
-#include "Stg.h"
-
void initTypeableStore(void);
void exitTypeableStore(void);
diff --git a/includes/SMP.h b/includes/SMP.h index a91e5d5619..0e6322d40b 100644 --- a/includes/SMP.h +++ b/includes/SMP.h @@ -1,8 +1,8 @@ /* ---------------------------------------------------------------------------- * - * (c) The GHC Team, 2005 + * (c) The GHC Team, 2005-2008 * - * Macros for THREADED_RTS support + * Macros for multi-CPU support * * -------------------------------------------------------------------------- */ @@ -175,132 +175,6 @@ write_barrier(void) { #endif } -/* ----------------------------------------------------------------------------- - * Locking/unlocking closures - * - * This is used primarily in the implementation of MVars. - * -------------------------------------------------------------------------- */ - -#define SPIN_COUNT 4000 - -#ifdef KEEP_LOCKCLOSURE -// We want a callable copy of lockClosure() so that we can refer to it -// from .cmm files compiled using the native codegen. -extern StgInfoTable *lockClosure(StgClosure *p); -INLINE_ME -#else -INLINE_HEADER -#endif -StgInfoTable * -lockClosure(StgClosure *p) -{ - StgWord info; - do { - nat i = 0; - do { - info = xchg((P_)(void *)&p->header.info, (W_)&stg_WHITEHOLE_info); - if (info != (W_)&stg_WHITEHOLE_info) return (StgInfoTable *)info; - } while (++i < SPIN_COUNT); - yieldThread(); - } while (1); -} - -INLINE_HEADER void -unlockClosure(StgClosure *p, const StgInfoTable *info) -{ - // This is a strictly ordered write, so we need a write_barrier(): - write_barrier(); - p->header.info = info; -} - -/* ----------------------------------------------------------------------------- - * Spin locks - * - * These are simple spin-only locks as opposed to Mutexes which - * probably spin for a while before blocking in the kernel. We use - * these when we are sure that all our threads are actively running on - * a CPU, eg. in the GC. - * - * TODO: measure whether we really need these, or whether Mutexes - * would do (and be a bit safer if a CPU becomes loaded). - * -------------------------------------------------------------------------- */ - -#if defined(DEBUG) -typedef struct StgSync_ -{ - StgWord32 lock; - StgWord64 spin; // DEBUG version counts how much it spins -} StgSync; -#else -typedef StgWord StgSync; -#endif - -typedef lnat StgSyncCount; - - -#if defined(DEBUG) - -// Debug versions of spin locks maintain a spin count - -// How to use: -// To use the debug veriosn of the spin locks, a debug version of the program -// can be run under a deugger with a break point on stat_exit. At exit time -// of the program one can examine the state the spin count counts of various -// spin locks to check for contention. - -// acquire spin lock -INLINE_HEADER void ACQUIRE_SPIN_LOCK(StgSync * p) -{ - StgWord32 r = 0; - do { - p->spin++; - r = cas((StgVolatilePtr)&(p->lock), 1, 0); - } while(r == 0); - p->spin--; -} - -// release spin lock -INLINE_HEADER void RELEASE_SPIN_LOCK(StgSync * p) -{ - write_barrier(); - p->lock = 1; -} - -// initialise spin lock -INLINE_HEADER void initSpinLock(StgSync * p) -{ - write_barrier(); - p->lock = 1; - p->spin = 0; -} - -#else - -// acquire spin lock -INLINE_HEADER void ACQUIRE_SPIN_LOCK(StgSync * p) -{ - StgWord32 r = 0; - do { - r = cas((StgVolatilePtr)p, 1, 0); - } while(r == 0); -} - -// release spin lock -INLINE_HEADER void RELEASE_SPIN_LOCK(StgSync * p) -{ - write_barrier(); - (*p) = 1; -} - -// init spin lock -INLINE_HEADER void initSpinLock(StgSync * p) -{ - write_barrier(); - (*p) = 1; -} - -#endif /* DEBUG */ - /* ---------------------------------------------------------------------- */ #else /* !THREADED_RTS */ @@ -314,30 +188,8 @@ xchg(StgPtr p, StgWord w) return old; } -INLINE_HEADER StgInfoTable * -lockClosure(StgClosure *p) -{ return (StgInfoTable *)p->header.info; } - -INLINE_HEADER void -unlockClosure(StgClosure *p STG_UNUSED, const StgInfoTable *info STG_UNUSED) -{ /* nothing */ } - -// Using macros here means we don't have to ensure the argument is in scope -#define ACQUIRE_SPIN_LOCK(p) /* nothing */ -#define RELEASE_SPIN_LOCK(p) /* nothing */ - -INLINE_HEADER void initSpinLock(void * p STG_UNUSED) -{ /* nothing */ } - #endif /* !THREADED_RTS */ -// Handy specialised versions of lockClosure()/unlockClosure() -INLINE_HEADER void lockTSO(StgTSO *tso) -{ lockClosure((StgClosure *)tso); } - -INLINE_HEADER void unlockTSO(StgTSO *tso) -{ unlockClosure((StgClosure*)tso, (const StgInfoTable *)&stg_TSO_info); } +#endif /* CMINUSMINUS */ #endif /* SMP_H */ - -#endif /* CMINUSMINUS */ diff --git a/includes/SMPClosureOps.h b/includes/SMPClosureOps.h new file mode 100644 index 0000000000..fe78168011 --- /dev/null +++ b/includes/SMPClosureOps.h @@ -0,0 +1,71 @@ +/* ---------------------------------------------------------------------------- + * + * (c) The GHC Team, 2005 + * + * Macros for THREADED_RTS support + * + * -------------------------------------------------------------------------- */ + +#ifndef SMPCLOSUREOPS_H +#define SMPCLOSUREOPS_H + +#if defined(THREADED_RTS) + +/* ----------------------------------------------------------------------------- + * Locking/unlocking closures + * + * This is used primarily in the implementation of MVars. + * -------------------------------------------------------------------------- */ + +#define SPIN_COUNT 4000 + +#ifdef KEEP_LOCKCLOSURE +// We want a callable copy of lockClosure() so that we can refer to it +// from .cmm files compiled using the native codegen. +extern StgInfoTable *lockClosure(StgClosure *p); +INLINE_ME +#else +INLINE_HEADER +#endif +StgInfoTable * +lockClosure(StgClosure *p) +{ + StgWord info; + do { + nat i = 0; + do { + info = xchg((P_)(void *)&p->header.info, (W_)&stg_WHITEHOLE_info); + if (info != (W_)&stg_WHITEHOLE_info) return (StgInfoTable *)info; + } while (++i < SPIN_COUNT); + yieldThread(); + } while (1); +} + +INLINE_HEADER void +unlockClosure(StgClosure *p, const StgInfoTable *info) +{ + // This is a strictly ordered write, so we need a write_barrier(): + write_barrier(); + p->header.info = info; +} + +#else /* !THREADED_RTS */ + +INLINE_HEADER StgInfoTable * +lockClosure(StgClosure *p) +{ return (StgInfoTable *)p->header.info; } + +INLINE_HEADER void +unlockClosure(StgClosure *p STG_UNUSED, const StgInfoTable *info STG_UNUSED) +{ /* nothing */ } + +#endif /* THREADED_RTS */ + +// Handy specialised versions of lockClosure()/unlockClosure() +INLINE_HEADER void lockTSO(StgTSO *tso) +{ lockClosure((StgClosure *)tso); } + +INLINE_HEADER void unlockTSO(StgTSO *tso) +{ unlockClosure((StgClosure*)tso, (const StgInfoTable *)&stg_TSO_info); } + +#endif /* SMPCLOSUREOPS_H */ diff --git a/includes/SpinLock.h b/includes/SpinLock.h new file mode 100644 index 0000000000..de08ca1aa5 --- /dev/null +++ b/includes/SpinLock.h @@ -0,0 +1,110 @@ +/* ---------------------------------------------------------------------------- + * + * (c) The GHC Team, 2006-2008 + * + * Spin locks + * + * These are simple spin-only locks as opposed to Mutexes which + * probably spin for a while before blocking in the kernel. We use + * these when we are sure that all our threads are actively running on + * a CPU, eg. in the GC. + * + * TODO: measure whether we really need these, or whether Mutexes + * would do (and be a bit safer if a CPU becomes loaded). + * + * -------------------------------------------------------------------------- */ + +#ifndef SPINLOCK_H +#define SPINLOCK_H + +#if defined(THREADED_RTS) + +#if defined(DEBUG) +typedef struct StgSync_ +{ + StgWord32 lock; + StgWord64 spin; // DEBUG version counts how much it spins +} StgSync; +#else +typedef StgWord StgSync; +#endif + +typedef lnat StgSyncCount; + + +#if defined(DEBUG) + +// Debug versions of spin locks maintain a spin count + +// How to use: +// To use the debug veriosn of the spin locks, a debug version of the program +// can be run under a deugger with a break point on stat_exit. At exit time +// of the program one can examine the state the spin count counts of various +// spin locks to check for contention. + +// acquire spin lock +INLINE_HEADER void ACQUIRE_SPIN_LOCK(StgSync * p) +{ + StgWord32 r = 0; + do { + p->spin++; + r = cas((StgVolatilePtr)&(p->lock), 1, 0); + } while(r == 0); + p->spin--; +} + +// release spin lock +INLINE_HEADER void RELEASE_SPIN_LOCK(StgSync * p) +{ + write_barrier(); + p->lock = 1; +} + +// initialise spin lock +INLINE_HEADER void initSpinLock(StgSync * p) +{ + write_barrier(); + p->lock = 1; + p->spin = 0; +} + +#else + +// acquire spin lock +INLINE_HEADER void ACQUIRE_SPIN_LOCK(StgSync * p) +{ + StgWord32 r = 0; + do { + r = cas((StgVolatilePtr)p, 1, 0); + } while(r == 0); +} + +// release spin lock +INLINE_HEADER void RELEASE_SPIN_LOCK(StgSync * p) +{ + write_barrier(); + (*p) = 1; +} + +// init spin lock +INLINE_HEADER void initSpinLock(StgSync * p) +{ + write_barrier(); + (*p) = 1; +} + +#endif /* DEBUG */ + +#else /* !THREADED_RTS */ + +// Using macros here means we don't have to ensure the argument is in scope +#define ACQUIRE_SPIN_LOCK(p) /* nothing */ +#define RELEASE_SPIN_LOCK(p) /* nothing */ + +INLINE_HEADER void initSpinLock(void * p STG_UNUSED) +{ /* nothing */ } + +#endif /* THREADED_RTS */ + +#endif /* SPINLOCK_H */ + diff --git a/includes/Stg.h b/includes/Stg.h index 1facd5f405..6ddf17a0a0 100644 --- a/includes/Stg.h +++ b/includes/Stg.h @@ -41,6 +41,11 @@ #include "ghcconfig.h" #include "RtsConfig.h" +/* The code generator calls the math functions directly in .hc code. + NB. after configuration stuff above, because this sets #defines + that depend on config info, such as __USE_FILE_OFFSET64 */ +#include <math.h> + /* ----------------------------------------------------------------------------- Useful definitions -------------------------------------------------------------------------- */ @@ -148,7 +153,6 @@ typedef StgWord StgWordArray[]; #include "StgDLL.h" #include "MachRegs.h" #include "Regs.h" -#include "StgProf.h" /* ToDo: separate out RTS-only stuff from here */ #if IN_STG_CODE /* @@ -158,8 +162,7 @@ typedef StgWord StgWordArray[]; #include "StgMiscClosures.h" #endif -/* RTS external interface */ -#include "RtsExternal.h" +#include "SMP.h" // write_barrier() inline is required /* ----------------------------------------------------------------------------- Moving Floats and Doubles diff --git a/includes/StgMiscClosures.h b/includes/StgMiscClosures.h index a99ff72a22..c82ec05bd4 100644 --- a/includes/StgMiscClosures.h +++ b/includes/StgMiscClosures.h @@ -493,6 +493,12 @@ RTS_FUN(stg_threadFinished); RTS_FUN(stg_init_finish); RTS_FUN(stg_init); +RTS_FUN(StgReturn); + +extern int rts_stop_next_breakpoint; +extern int rts_stop_on_exception; +extern void *rts_breakpoint_io_action; + /* ----------------------------------------------------------------------------- PrimOps -------------------------------------------------------------------------- */ @@ -598,4 +604,42 @@ RTS_FUN(getApStackValzh_fast); RTS_FUN(noDuplicatezh_fast); +/* Other misc stuff */ + +#if IN_STG_CODE && !IN_STGCRUN + +// Schedule.c +extern int RTS_VAR(context_switch); +extern StgWord RTS_VAR(blocked_queue_hd), RTS_VAR(blocked_queue_tl); +extern StgWord RTS_VAR(sleeping_queue); +extern StgWord RTS_VAR(blackhole_queue); +extern StgWord RTS_VAR(sched_mutex); + +// Apply.cmm +// canned bitmap for each arg type +extern StgWord stg_arg_bitmaps[]; + +// Storage.c +extern unsigned int RTS_VAR(alloc_blocks); +extern unsigned int RTS_VAR(alloc_blocks_lim); +extern StgWord RTS_VAR(weak_ptr_list); +extern StgWord RTS_VAR(atomic_modify_mutvar_mutex); + +// RtsFlags +extern StgWord RTS_VAR(RtsFlags); // bogus type + +// Stable.c +extern StgWord RTS_VAR(stable_ptr_table); + +// Profiling.c +extern unsigned int RTS_VAR(era); +extern StgWord RTS_VAR(CCCS); /* current CCS */ +extern unsigned int RTS_VAR(entering_PAP); +extern StgWord RTS_VAR(CC_LIST); /* registered CC list */ +extern StgWord RTS_VAR(CCS_LIST); /* registered CCS list */ +extern unsigned int RTS_VAR(CC_ID); /* global ids */ +extern unsigned int RTS_VAR(CCS_ID); + +#endif + #endif /* STGMISCCLOSURES_H */ |