#include "gmp.h" // Needs MP_INT definition
-/*
- * This is the table that holds shadow-locations for all the STG
- * registers. The shadow locations are used when:
- *
- * 1) the particular register isn't mapped to a real machine
- * register, probably because there's a shortage of real registers.
- * 2) caller-saves registers are saved across a CCall
+/*
+ * Spark pools: used to store pending sparks
+ * (THREADED_RTS & PARALLEL_HASKELL only)
+ * This is a circular buffer. Invariants:
+ * - base <= hd < lim
+ * - base <= tl < lim
+ * - if hd==tl, then the pool is empty.
+ * - if hd == tl+1, then the pool is full.
+ * Adding to the pool is done by assigning to *tl++ (wrapping round as
+ * necessary). When adding to a full pool, we have the option of
+ * throwing away either the oldest (hd++) or the most recent (tl--) entry.
*/
-
typedef struct StgSparkPool_ {
StgClosure **base;
StgClosure **lim;
StgClosure **tl;
} StgSparkPool;
+#define ASSERT_SPARK_POOL_INVARIANTS(p) \
+ ASSERT((p)->base <= (p)->hd); \
+ ASSERT((p)->hd < (p)->lim); \
+ ASSERT((p)->base <= (p)->tl); \
+ ASSERT((p)->tl < (p)->lim);
+
typedef struct {
StgFunPtr stgGCEnter1;
StgFunPtr stgGCFun;
StgTSOPtr t;
} StgUnion;
+/*
+ * This is the table that holds shadow-locations for all the STG
+ * registers. The shadow locations are used when:
+ *
+ * 1) the particular register isn't mapped to a real machine
+ * register, probably because there's a shortage of real registers.
+ * 2) caller-saves registers are saved across a CCall
+ */
typedef struct StgRegTable_ {
StgUnion rR1;
StgUnion rR2;
struct bdescr_ *rCurrentNursery; /* Hp/HpLim point into this block */
struct bdescr_ *rCurrentAlloc; /* for allocation using allocate() */
StgWord rHpAlloc; /* number of *bytes* being allocated in heap */
- // rmp_tmp1..rmp_result2 are only used in SMP builds to avoid per-thread temps
- // in bss, but currently always incldue here so we just run mkDerivedConstants once
+ // 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
StgInt rmp_tmp_w;
MP_INT rmp_tmp1;
MP_INT rmp_tmp2;
MP_INT rmp_result1;
MP_INT rmp_result2;
StgWord rRet; // holds the return code of the thread
-#if defined(SMP) || defined(PAR)
+#if defined(THREADED_RTS) || defined(PAR)
StgSparkPool rSparks; /* per-task spark pool */
#endif
} StgRegTable;
StgRegTable r;
};
-/* No such thing as a MainCapability under SMP - each thread must have
+/* No such thing as a MainCapability under THREADED_RTS - each thread must have
* its own Capability.
*/
-#if IN_STG_CODE && !defined(SMP)
+#if IN_STG_CODE && !defined(THREADED_RTS)
extern W_ MainCapability[];
#endif
+/*
+ * Assigning to BaseReg (the ASSIGN_BaseReg macro): this happens on
+ * return from a "safe" foreign call, when the thread might be running
+ * on a new Capability. Obviously if BaseReg is not a register, then
+ * we are restricted to a single Capability (this invariant is enforced
+ * in Capability.c:initCapabilities), and assigning to BaseReg can be omitted.
+ */
+
#if defined(REG_Base) && !defined(NO_GLOBAL_REG_DECLS)
GLOBAL_REG_DECL(StgRegTable *,BaseReg,REG_Base)
+#define ASSIGN_BaseReg(e) (BaseReg = (e))
#else
-#ifdef SMP
-#error BaseReg must be in a register for SMP
+#ifdef THREADED_RTS
+#error BaseReg must be in a register for THREADED_RTS
#endif
#define BaseReg (&((struct PartCapability_ *)MainCapability)->r)
+#define ASSIGN_BaseReg(e) (e)
#endif
#if defined(REG_Sp) && !defined(NO_GLOBAL_REG_DECLS)
#endif
#ifdef CALLER_SAVES_Base
-#ifdef SMP
-#error "Can't have caller-saved BaseReg with SMP"
+#ifdef THREADED_RTS
+#error "Can't have caller-saved BaseReg with THREADED_RTS"
#endif
#define CALLER_SAVE_Base /* nothing */
#define CALLER_RESTORE_Base BaseReg = &MainRegTable;