diff options
author | simonmar <unknown> | 2005-11-18 15:24:12 +0000 |
---|---|---|
committer | simonmar <unknown> | 2005-11-18 15:24:12 +0000 |
commit | c5cd2343c5a86c8cb5349823a9699b30a269f3e8 (patch) | |
tree | 02929661d685c1b6cc53844338f54507fdfa80ce /ghc/includes | |
parent | 6c17d627e08e03f2b107bb9ab5d9259c7739c0d6 (diff) | |
download | haskell-c5cd2343c5a86c8cb5349823a9699b30a269f3e8.tar.gz |
[project @ 2005-11-18 15:24:12 by simonmar]
Two improvements to the SMP runtime:
- support for 'par', aka sparks. Load balancing is very primitive
right now, but I have seen programs that go faster using par.
- support for backing off when a thread is found to be duplicating
a computation currently underway in another thread. This also
fixes some instability in SMP, because it turned out that when
an update frame points to an indirection, which can happen if
a thunk is under evaluation in multiple threads, then after GC
has shorted out the indirection the update will trash the value.
Now we suspend the duplicate computation to the heap before this
can happen.
Additionally:
- stack squeezing is separate from lazy blackholing, and now only
happens if there's a reasonable amount of squeezing to be done
in relation to the number of words of stack that have to be moved.
This means we won't try to shift 10Mb of stack just to save 2
words at the bottom (it probably never happened, but still).
- update frames are now marked when they have been visited by lazy
blackholing, as per the SMP paper.
- cleaned up raiseAsync() a bit.
Diffstat (limited to 'ghc/includes')
-rw-r--r-- | ghc/includes/Closures.h | 5 | ||||
-rw-r--r-- | ghc/includes/Regs.h | 32 | ||||
-rw-r--r-- | ghc/includes/RtsFlags.h | 1 | ||||
-rw-r--r-- | ghc/includes/StgMiscClosures.h | 2 | ||||
-rw-r--r-- | ghc/includes/Storage.h | 2 |
5 files changed, 33 insertions, 9 deletions
diff --git a/ghc/includes/Closures.h b/ghc/includes/Closures.h index f9bfeb4dc1..df3bca32f7 100644 --- a/ghc/includes/Closures.h +++ b/ghc/includes/Closures.h @@ -339,6 +339,11 @@ typedef struct { * - In StgTRecHeader, it might be worthwhile having separate chunks * of read-only and read-write locations. This would save a * new_value field in the read-only locations. + * + * - In StgAtomicallyFrame, we could combine the waiting bit into + * the header (maybe a different info tbl for a waiting transaction). + * This means we can specialise the code for the atomically frame + * (it immediately switches on frame->waiting anyway). */ typedef struct StgTVarWaitQueue_ { diff --git a/ghc/includes/Regs.h b/ghc/includes/Regs.h index f1b8597d60..def36c327d 100644 --- a/ghc/includes/Regs.h +++ b/ghc/includes/Regs.h @@ -24,15 +24,17 @@ #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 (SMP & 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; @@ -40,6 +42,12 @@ typedef struct StgSparkPool_ { 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; @@ -64,6 +72,14 @@ typedef union { 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; diff --git a/ghc/includes/RtsFlags.h b/ghc/includes/RtsFlags.h index a4c6d9ba58..4a37d48fd4 100644 --- a/ghc/includes/RtsFlags.h +++ b/ghc/includes/RtsFlags.h @@ -62,6 +62,7 @@ struct DEBUG_FLAGS { rtsBool linker; /* 'l' the object linker */ rtsBool apply; /* 'a' */ rtsBool stm; /* 'm' */ + rtsBool squeeze; /* 'z' stack squeezing & lazy blackholing */ }; struct COST_CENTRE_FLAGS { diff --git a/ghc/includes/StgMiscClosures.h b/ghc/includes/StgMiscClosures.h index 1d381e656e..a9938aa9f4 100644 --- a/ghc/includes/StgMiscClosures.h +++ b/ghc/includes/StgMiscClosures.h @@ -37,6 +37,7 @@ /* Stack frames */ RTS_RET_INFO(stg_upd_frame_info); +RTS_RET_INFO(stg_marked_upd_frame_info); RTS_RET_INFO(stg_noupd_frame_info); RTS_RET_INFO(stg_seq_frame_info); RTS_RET_INFO(stg_catch_frame_info); @@ -45,6 +46,7 @@ RTS_RET_INFO(stg_atomically_frame_info); RTS_RET_INFO(stg_catch_stm_frame_info); RTS_ENTRY(stg_upd_frame_ret); +RTS_ENTRY(stg_marked_upd_frame_ret); RTS_ENTRY(stg_seq_frame_ret); /* Entry code for constructors created by the bytecode interpreter */ diff --git a/ghc/includes/Storage.h b/ghc/includes/Storage.h index 1f6ef3f5e7..e37c50d054 100644 --- a/ghc/includes/Storage.h +++ b/ghc/includes/Storage.h @@ -392,7 +392,7 @@ extern lnat countNurseryBlocks ( void ); Functions from GC.c -------------------------------------------------------------------------- */ -extern void threadPaused ( StgTSO * ); +extern void threadPaused ( Capability *cap, StgTSO * ); extern StgClosure * isAlive ( StgClosure *p ); extern void markCAFs ( evac_fn evac ); |