diff options
Diffstat (limited to 'rts/sm')
-rw-r--r-- | rts/sm/BlockAlloc.c | 44 | ||||
-rw-r--r-- | rts/sm/Compact.c | 12 | ||||
-rw-r--r-- | rts/sm/Compact.h | 6 | ||||
-rw-r--r-- | rts/sm/Evac.c | 6 | ||||
-rw-r--r-- | rts/sm/Evac.h | 6 | ||||
-rw-r--r-- | rts/sm/GC.c | 24 | ||||
-rw-r--r-- | rts/sm/GC.h | 16 | ||||
-rw-r--r-- | rts/sm/GCAux.c | 5 | ||||
-rw-r--r-- | rts/sm/GCThread.h | 7 | ||||
-rw-r--r-- | rts/sm/GCUtils.c | 5 | ||||
-rw-r--r-- | rts/sm/GCUtils.h | 7 | ||||
-rw-r--r-- | rts/sm/MBlock.c | 5 | ||||
-rw-r--r-- | rts/sm/MBlock.h | 208 | ||||
-rw-r--r-- | rts/sm/MarkWeak.c | 4 | ||||
-rw-r--r-- | rts/sm/MarkWeak.h | 5 | ||||
-rw-r--r-- | rts/sm/OSMem.h | 5 | ||||
-rw-r--r-- | rts/sm/README | 11 | ||||
-rw-r--r-- | rts/sm/Scav.c | 5 | ||||
-rw-r--r-- | rts/sm/Scav.h | 6 | ||||
-rw-r--r-- | rts/sm/Storage.c | 11 | ||||
-rw-r--r-- | rts/sm/Storage.h | 169 | ||||
-rw-r--r-- | rts/sm/Sweep.c | 4 | ||||
-rw-r--r-- | rts/sm/Sweep.h | 7 |
23 files changed, 287 insertions, 291 deletions
diff --git a/rts/sm/BlockAlloc.c b/rts/sm/BlockAlloc.c index 280ebfc7db..bf7a55e7a9 100644 --- a/rts/sm/BlockAlloc.c +++ b/rts/sm/BlockAlloc.c @@ -17,11 +17,10 @@ #include "PosixSource.h" #include "Rts.h" -#include "RtsFlags.h" + +#include "Storage.h" #include "RtsUtils.h" #include "BlockAlloc.h" -#include "MBlock.h" -#include "Storage.h" #include <string.h> @@ -284,7 +283,7 @@ alloc_mega_group (nat mblocks) { // we take our chunk off the end here. nat best_mblocks = BLOCKS_TO_MBLOCKS(best->blocks); - bd = FIRST_BDESCR(MBLOCK_ROUND_DOWN(best) + + bd = FIRST_BDESCR((StgWord8*)MBLOCK_ROUND_DOWN(best) + (best_mblocks-mblocks)*MBLOCK_SIZE); best->blocks = MBLOCK_GROUP_BLOCKS(best_mblocks - mblocks); @@ -415,7 +414,8 @@ coalesce_mblocks (bdescr *p) q = p->link; if (q != NULL && MBLOCK_ROUND_DOWN(q) == - MBLOCK_ROUND_DOWN(p) + BLOCKS_TO_MBLOCKS(p->blocks) * MBLOCK_SIZE) { + (StgWord8*)MBLOCK_ROUND_DOWN(p) + + BLOCKS_TO_MBLOCKS(p->blocks) * MBLOCK_SIZE) { // can coalesce p->blocks = MBLOCK_GROUP_BLOCKS(BLOCKS_TO_MBLOCKS(p->blocks) + BLOCKS_TO_MBLOCKS(q->blocks)); @@ -610,20 +610,21 @@ splitBlockGroup (bdescr *bd, nat blocks) static void initMBlock(void *mblock) { - bdescr *bd; - void *block; - - /* the first few Bdescr's in a block are unused, so we don't want to - * put them all on the free list. - */ - block = FIRST_BLOCK(mblock); - bd = FIRST_BDESCR(mblock); - - /* Initialise the start field of each block descriptor - */ - for (; block <= LAST_BLOCK(mblock); bd += 1, block += BLOCK_SIZE) { - bd->start = block; - } + bdescr *bd; + StgWord8 *block; + + /* the first few Bdescr's in a block are unused, so we don't want to + * put them all on the free list. + */ + block = FIRST_BLOCK(mblock); + bd = FIRST_BDESCR(mblock); + + /* Initialise the start field of each block descriptor + */ + for (; block <= (StgWord8*)LAST_BLOCK(mblock); bd += 1, + block += BLOCK_SIZE) { + bd->start = (void*)block; + } } /* ----------------------------------------------------------------------------- @@ -708,7 +709,7 @@ checkFreeListSanity(void) if (bd->link != NULL) { ASSERT (MBLOCK_ROUND_DOWN(bd->link) != - MBLOCK_ROUND_DOWN(bd) + + (StgWord8*)MBLOCK_ROUND_DOWN(bd) + BLOCKS_TO_MBLOCKS(bd->blocks) * MBLOCK_SIZE); } } @@ -758,7 +759,8 @@ reportUnmarkedBlocks (void) debugBelch(" %p\n",bd); } if (bd->blocks >= BLOCKS_PER_MBLOCK) { - mblock += (BLOCKS_TO_MBLOCKS(bd->blocks) - 1) * MBLOCK_SIZE; + mblock = (StgWord8*)mblock + + (BLOCKS_TO_MBLOCKS(bd->blocks) - 1) * MBLOCK_SIZE; break; } else { bd += bd->blocks; diff --git a/rts/sm/Compact.c b/rts/sm/Compact.c index 9c13253c32..892364dfa5 100644 --- a/rts/sm/Compact.c +++ b/rts/sm/Compact.c @@ -13,16 +13,18 @@ #include "PosixSource.h" #include "Rts.h" + +#include "Storage.h" #include "RtsUtils.h" -#include "RtsFlags.h" -#include "OSThreads.h" #include "BlockAlloc.h" -#include "MBlock.h" #include "GC.h" #include "Compact.h" #include "Schedule.h" #include "Apply.h" #include "Trace.h" +#include "Weak.h" +#include "MarkWeak.h" +#include "Stable.h" // Turn off inlining when debugging - it obfuscates things #ifdef DEBUG @@ -166,7 +168,7 @@ loop: case 1: { StgWord r = *(StgPtr)(q-1); - ASSERT(LOOKS_LIKE_INFO_PTR(UNTAG_CLOSURE((StgClosure *)r))); + ASSERT(LOOKS_LIKE_INFO_PTR((StgWord)UNTAG_CLOSURE((StgClosure *)r))); return r; } case 2: @@ -929,7 +931,7 @@ update_bkwd_compact( step *stp ) iptr = get_threaded_info(p); unthread(p, (StgWord)free + GET_CLOSURE_TAG((StgClosure *)iptr)); - ASSERT(LOOKS_LIKE_INFO_PTR(((StgClosure *)p)->header.info)); + ASSERT(LOOKS_LIKE_INFO_PTR((StgWord)((StgClosure *)p)->header.info)); info = get_itbl((StgClosure *)p); size = closure_sizeW_((StgClosure *)p,info); diff --git a/rts/sm/Compact.h b/rts/sm/Compact.h index 40622c5682..7a237ac362 100644 --- a/rts/sm/Compact.h +++ b/rts/sm/Compact.h @@ -11,8 +11,8 @@ * * ---------------------------------------------------------------------------*/ -#ifndef GCCOMPACT_H -#define GCCOMPACT_H +#ifndef SM_COMPACT_H +#define SM_COMPACT_H INLINE_HEADER rtsBool mark_stack_empty(void) @@ -76,4 +76,4 @@ is_marked(StgPtr p, bdescr *bd) extern void compact (StgClosure *static_objects); -#endif /* GCCOMPACT_H */ +#endif /* SM_COMPACT_H */ diff --git a/rts/sm/Evac.c b/rts/sm/Evac.c index 5935f9069e..9e6d0f1783 100644 --- a/rts/sm/Evac.c +++ b/rts/sm/Evac.c @@ -11,16 +11,16 @@ * * ---------------------------------------------------------------------------*/ +#include "PosixSource.h" #include "Rts.h" -#include "Storage.h" -#include "MBlock.h" + #include "Evac.h" +#include "Storage.h" #include "GC.h" #include "GCThread.h" #include "GCUtils.h" #include "Compact.h" #include "Prelude.h" -#include "LdvProfile.h" #include "Trace.h" #if defined(PROF_SPIN) && defined(THREADED_RTS) && defined(PARALLEL_GC) diff --git a/rts/sm/Evac.h b/rts/sm/Evac.h index e6ef02cfcc..78d024f3e9 100644 --- a/rts/sm/Evac.h +++ b/rts/sm/Evac.h @@ -11,6 +11,9 @@ * * ---------------------------------------------------------------------------*/ +#ifndef SM_EVAC_H +#define SM_EVAC_H + // Use a register argument for evacuate, if available. // Earlier, the regparm attribute was used whenever __GNUC__ >= 2, but this // generated warnings on PPC. So the use is restricted further. @@ -31,3 +34,6 @@ REGPARM1 void evacuate (StgClosure **p); REGPARM1 void evacuate1 (StgClosure **p); extern lnat thunk_selector_depth; + +#endif /* SM_EVAC_H */ + diff --git a/rts/sm/GC.c b/rts/sm/GC.c index 88b11aae88..02fd6d9161 100644 --- a/rts/sm/GC.c +++ b/rts/sm/GC.c @@ -11,28 +11,23 @@ * * ---------------------------------------------------------------------------*/ -// #include "PosixSource.h" +#include "PosixSource.h" #include "Rts.h" -#include "RtsFlags.h" +#include "HsFFI.h" + +#include "Storage.h" #include "RtsUtils.h" #include "Apply.h" -#include "OSThreads.h" -#include "LdvProfile.h" #include "Updates.h" #include "Stats.h" #include "Schedule.h" #include "Sanity.h" #include "BlockAlloc.h" -#include "MBlock.h" #include "ProfHeap.h" -#include "SchedAPI.h" #include "Weak.h" #include "Prelude.h" -#include "ParTicky.h" // ToDo: move into Rts.h #include "RtsSignals.h" #include "STM.h" -#include "HsFFI.h" -#include "Linker.h" #if defined(RTS_GTK_FRONTPANEL) #include "FrontPanel.h" #endif @@ -40,6 +35,7 @@ #include "RetainerProfile.h" #include "RaiseAsync.h" #include "Papi.h" +#include "Stable.h" #include "GC.h" #include "GCThread.h" @@ -1112,10 +1108,11 @@ gcWorkerThread (Capability *cap) #endif +#if defined(THREADED_RTS) + void waitForGcThreads (Capability *cap USED_IF_THREADS) { -#if defined(THREADED_RTS) nat n_threads = RtsFlags.ParFlags.nNodes; nat me = cap->no; nat i, j; @@ -1141,9 +1138,10 @@ waitForGcThreads (Capability *cap USED_IF_THREADS) if (!retry) break; } } -#endif } +#endif // THREADED_RTS + static void start_gc_threads (void) { @@ -1185,10 +1183,10 @@ shutdown_gc_threads (nat n_threads USED_IF_THREADS, nat me USED_IF_THREADS) #endif } +#if defined(THREADED_RTS) void releaseGCThreads (Capability *cap USED_IF_THREADS) { -#if defined(THREADED_RTS) nat n_threads = RtsFlags.ParFlags.nNodes; nat me = cap->no; nat i; @@ -1201,8 +1199,8 @@ releaseGCThreads (Capability *cap USED_IF_THREADS) ACQUIRE_SPIN_LOCK(&gc_threads[i]->gc_spin); RELEASE_SPIN_LOCK(&gc_threads[i]->mut_spin); } -#endif } +#endif /* ---------------------------------------------------------------------------- Initialise a generation that is to be collected diff --git a/rts/sm/GC.h b/rts/sm/GC.h index fb4381dc0b..920b464bbb 100644 --- a/rts/sm/GC.h +++ b/rts/sm/GC.h @@ -11,8 +11,15 @@ * * ---------------------------------------------------------------------------*/ -#ifndef GC_H -#define GC_H +#ifndef SM_GC_H +#define SM_GC_H + +void GarbageCollect(rtsBool force_major_gc, nat gc_type, Capability *cap); + +typedef void (*evac_fn)(void *user, StgClosure **root); + +StgClosure * isAlive ( StgClosure *p ); +void markCAFs ( evac_fn evac, void *user ); extern nat N; extern rtsBool major_gc; @@ -45,9 +52,12 @@ extern StgWord64 whitehole_spin; void gcWorkerThread (Capability *cap); void initGcThreads (void); void freeGcThreads (void); + +#if defined(THREADED_RTS) void waitForGcThreads (Capability *cap); void releaseGCThreads (Capability *cap); +#endif #define WORK_UNIT_WORDS 128 -#endif /* GC_H */ +#endif /* SM_GC_H */ diff --git a/rts/sm/GCAux.c b/rts/sm/GCAux.c index c1ff54123d..404e9bbcbc 100644 --- a/rts/sm/GCAux.c +++ b/rts/sm/GCAux.c @@ -7,10 +7,11 @@ * * ---------------------------------------------------------------------------*/ +#include "PosixSource.h" #include "Rts.h" -#include "Storage.h" -#include "MBlock.h" + #include "GC.h" +#include "Storage.h" #include "Compact.h" #include "Task.h" #include "Capability.h" diff --git a/rts/sm/GCThread.h b/rts/sm/GCThread.h index f91092b7ea..9188a20a9a 100644 --- a/rts/sm/GCThread.h +++ b/rts/sm/GCThread.h @@ -11,10 +11,9 @@ * * ---------------------------------------------------------------------------*/ -#ifndef GCTHREAD_H -#define GCTHREAD_H +#ifndef SM_GCTHREAD_H +#define SM_GCTHREAD_H -#include "OSThreads.h" #include "WSDeque.h" /* ----------------------------------------------------------------------------- @@ -271,5 +270,5 @@ extern StgWord8 the_gc_thread[]; #endif -#endif // GCTHREAD_H +#endif // SM_GCTHREAD_H diff --git a/rts/sm/GCUtils.c b/rts/sm/GCUtils.c index 57cede7d43..6c6f10e01f 100644 --- a/rts/sm/GCUtils.c +++ b/rts/sm/GCUtils.c @@ -11,8 +11,9 @@ * * ---------------------------------------------------------------------------*/ +#include "PosixSource.h" #include "Rts.h" -#include "RtsFlags.h" + #include "Storage.h" #include "GC.h" #include "GCThread.h" @@ -101,6 +102,7 @@ grab_local_todo_block (step_workspace *ws) return NULL; } +#if defined(THREADED_RTS) bdescr * steal_todo_block (nat s) { @@ -117,6 +119,7 @@ steal_todo_block (nat s) } return NULL; } +#endif void push_scanned_block (bdescr *bd, step_workspace *ws) diff --git a/rts/sm/GCUtils.h b/rts/sm/GCUtils.h index e71f4374fb..d68ce7876f 100644 --- a/rts/sm/GCUtils.h +++ b/rts/sm/GCUtils.h @@ -11,7 +11,8 @@ * * --------------------------------------------------------------------------*/ -#include "SMP.h" +#ifndef SM_GCUTILS_H +#define SM_GCUTILS_H bdescr *allocBlock_sync(void); void freeChain_sync(bdescr *bd); @@ -21,7 +22,9 @@ StgPtr todo_block_full (nat size, step_workspace *ws); StgPtr alloc_todo_block (step_workspace *ws, nat size); bdescr *grab_local_todo_block (step_workspace *ws); +#if defined(THREADED_RTS) bdescr *steal_todo_block (nat s); +#endif // Returns true if a block is partially full. This predicate is used to try // to re-use partial blocks wherever possible, and to reduce wastage. @@ -55,3 +58,5 @@ recordMutableGen_GC (StgClosure *p, nat gen_no) } *bd->free++ = (StgWord)p; } + +#endif /* SM_GCUTILS_H */ diff --git a/rts/sm/MBlock.c b/rts/sm/MBlock.c index b3fa13b0bc..996b2c9ae9 100644 --- a/rts/sm/MBlock.c +++ b/rts/sm/MBlock.c @@ -9,10 +9,9 @@ * ---------------------------------------------------------------------------*/ #include "PosixSource.h" - #include "Rts.h" + #include "RtsUtils.h" -#include "MBlock.h" #include "BlockAlloc.h" #include "Trace.h" #include "OSMem.h" @@ -235,7 +234,7 @@ getMBlocks(nat n) // fill in the table for (i = 0; i < n; i++) { - markHeapAlloced( ret + i * MBLOCK_SIZE ); + markHeapAlloced( (StgWord8*)ret + i * MBLOCK_SIZE ); } mblocks_allocated += n; diff --git a/rts/sm/MBlock.h b/rts/sm/MBlock.h deleted file mode 100644 index f9dddc3138..0000000000 --- a/rts/sm/MBlock.h +++ /dev/null @@ -1,208 +0,0 @@ -/* ----------------------------------------------------------------------------- - * - * (c) The GHC Team, 1998-2008 - * - * MegaBlock Allocator interface. - * - * See wiki commentary at - * http://hackage.haskell.org/trac/ghc/wiki/Commentary/HeapAlloced - * - * ---------------------------------------------------------------------------*/ - -#ifndef MBLOCK_H -#define MBLOCK_H - -#include "GC.h" - -extern lnat RTS_VAR(mblocks_allocated); - -extern void initMBlocks(void); -extern void * getMBlock(void); -extern void * getMBlocks(nat n); -extern void freeAllMBlocks(void); - -#ifdef DEBUG -extern void *getFirstMBlock(void); -extern void *getNextMBlock(void *mblock); -#endif - -/* ----------------------------------------------------------------------------- - The HEAP_ALLOCED() test. - - HEAP_ALLOCED is called FOR EVERY SINGLE CLOSURE during GC. - It needs to be FAST. - - See wiki commentary at - http://hackage.haskell.org/trac/ghc/wiki/Commentary/HeapAlloced - - Implementation of HEAP_ALLOCED - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Since heap is allocated in chunks of megablocks (MBLOCK_SIZE), we - can just use a table to record which megablocks in the address - space belong to the heap. On a 32-bit machine, with 1Mb - megablocks, using 8 bits for each entry in the table, the table - requires 4k. Lookups during GC will be fast, because the table - will be quickly cached (indeed, performance measurements showed no - measurable difference between doing the table lookup and using a - constant comparison). - - On 64-bit machines, we cache one 12-bit block map that describes - 4096 megablocks or 4GB of memory. If HEAP_ALLOCED is called for - an address that is not in the cache, it calls slowIsHeapAlloced - (see MBlock.c) which will find the block map for the 4GB block in - question. - -------------------------------------------------------------------------- */ - -#if SIZEOF_VOID_P == 4 -extern StgWord8 mblock_map[]; - -/* On a 32-bit machine a 4KB table is always sufficient */ -# define MBLOCK_MAP_SIZE 4096 -# define MBLOCK_MAP_ENTRY(p) ((StgWord)(p) >> MBLOCK_SHIFT) -# define HEAP_ALLOCED(p) mblock_map[MBLOCK_MAP_ENTRY(p)] -# define HEAP_ALLOCED_GC(p) HEAP_ALLOCED(p) - -/* ----------------------------------------------------------------------------- - HEAP_ALLOCED for 64-bit machines. - - Here are some cache layout options: - - [1] - 16KB cache of 16-bit entries, 1MB lines (capacity 8GB) - mblock size = 20 bits - entries = 8192 13 bits - line size = 0 bits (1 bit of value) - tag size = 15 bits - = 48 bits - - [2] - 32KB cache of 16-bit entries, 4MB lines (capacity 32GB) - mblock size = 20 bits - entries = 16384 14 bits - line size = 2 bits (4 bits of value) - tag size = 12 bits - = 48 bits - - [3] - 16KB cache of 16-bit entries, 2MB lines (capacity 16GB) - mblock size = 20 bits - entries = 8192 13 bits - line size = 1 bits (2 bits of value) - tag size = 14 bits - = 48 bits - - [4] - 4KB cache of 32-bit entries, 16MB lines (capacity 16GB) - mblock size = 20 bits - entries = 1024 10 bits - line size = 4 bits (16 bits of value) - tag size = 14 bits - = 48 bits - - [5] - 4KB cache of 64-bit entries, 32MB lines (capacity 16GB) - mblock size = 20 bits - entries = 512 9 bits - line size = 5 bits (32 bits of value) - tag size = 14 bits - = 48 bits - - We actually use none of the above. After much experimentation it was - found that optimising the lookup is the most important factor, - followed by reducing the number of misses. To that end, we use a - variant of [1] in which each cache entry is ((mblock << 1) + value) - where value is 0 for non-heap and 1 for heap. The cache entries can - be 32 bits, since the mblock number is 48-20 = 28 bits, and we need - 1 bit for the value. The cache can be as big as we like, but - currently we use 8k entries, giving us 8GB capacity. - - ---------------------------------------------------------------------------- */ - -#elif SIZEOF_VOID_P == 8 - -#define MBC_LINE_BITS 0 -#define MBC_TAG_BITS 15 -typedef StgWord32 MbcCacheLine; // could use 16, but 32 was faster -typedef StgWord8 MBlockMapLine; - -#define MBLOCK_MAP_LINE(p) (((StgWord)p & 0xffffffff) >> (MBLOCK_SHIFT + MBC_LINE_BITS)) - -#define MBC_LINE_SIZE (1<<MBC_LINE_BITS) -#define MBC_SHIFT (48 - MBLOCK_SHIFT - MBC_LINE_BITS - MBC_TAG_BITS) -#define MBC_ENTRIES (1<<MBC_SHIFT) - -extern MbcCacheLine mblock_cache[]; - -#define MBC_LINE(p) ((StgWord)p >> (MBLOCK_SHIFT + MBC_LINE_BITS)) - -#define MBLOCK_MAP_ENTRIES (1 << (32 - MBLOCK_SHIFT - MBC_LINE_BITS)) - -typedef struct { - StgWord32 addrHigh32; - MBlockMapLine lines[MBLOCK_MAP_ENTRIES]; -} MBlockMap; - -extern lnat mpc_misses; - -StgBool HEAP_ALLOCED_miss(StgWord mblock, void *p); - -INLINE_HEADER -StgBool HEAP_ALLOCED(void *p) -{ - StgWord mblock; - nat entry_no; - MbcCacheLine entry, value; - - mblock = (StgWord)p >> MBLOCK_SHIFT; - entry_no = mblock & (MBC_ENTRIES-1); - entry = mblock_cache[entry_no]; - value = entry ^ (mblock << 1); - // this formulation coaxes gcc into prioritising the value==1 - // case, which we expect to be the most common. - // __builtin_expect() didn't have any useful effect (gcc-4.3.0). - if (value == 1) { - return 1; - } else if (value == 0) { - return 0; - } else { - // putting the rest out of line turned out to be a slight - // performance improvement: - return HEAP_ALLOCED_miss(mblock,p); - } -} - -// In the parallel GC, the cache itself is safe to *read*, and can be -// updated atomically, but we need to place a lock around operations -// that touch the MBlock map. -INLINE_HEADER -StgBool HEAP_ALLOCED_GC(void *p) -{ - StgWord mblock; - nat entry_no; - MbcCacheLine entry, value; - StgBool b; - - mblock = (StgWord)p >> MBLOCK_SHIFT; - entry_no = mblock & (MBC_ENTRIES-1); - entry = mblock_cache[entry_no]; - value = entry ^ (mblock << 1); - if (value == 1) { - return 1; - } else if (value == 0) { - return 0; - } else { - // putting the rest out of line turned out to be a slight - // performance improvement: - ACQUIRE_SPIN_LOCK(&gc_alloc_block_sync); - b = HEAP_ALLOCED_miss(mblock,p); - RELEASE_SPIN_LOCK(&gc_alloc_block_sync); - return b; - } -} - -#else -# error HEAP_ALLOCED not defined -#endif - -#endif /* MBLOCK_H */ diff --git a/rts/sm/MarkWeak.c b/rts/sm/MarkWeak.c index 78c84ed77a..4f0a7a451b 100644 --- a/rts/sm/MarkWeak.c +++ b/rts/sm/MarkWeak.c @@ -11,14 +11,16 @@ * * ---------------------------------------------------------------------------*/ +#include "PosixSource.h" #include "Rts.h" -#include "Storage.h" + #include "MarkWeak.h" #include "GC.h" #include "GCThread.h" #include "Evac.h" #include "Trace.h" #include "Schedule.h" +#include "Weak.h" /* ----------------------------------------------------------------------------- Weak Pointers diff --git a/rts/sm/MarkWeak.h b/rts/sm/MarkWeak.h index 7b3a806857..2647a22eec 100644 --- a/rts/sm/MarkWeak.h +++ b/rts/sm/MarkWeak.h @@ -11,6 +11,9 @@ * * ---------------------------------------------------------------------------*/ +#ifndef SM_MARKWEAK_H +#define SM_MARKWEAK_H + extern StgWeak *old_weak_ptr_list; extern StgTSO *resurrected_threads; extern StgTSO *exception_threads; @@ -19,3 +22,5 @@ void initWeakForGC ( void ); rtsBool traverseWeakPtrList ( void ); void markWeakPtrList ( void ); rtsBool traverseBlackholeQueue ( void ); + +#endif /* SM_MARKWEAK_H */ diff --git a/rts/sm/OSMem.h b/rts/sm/OSMem.h index dcf8eb73df..3dbca23d11 100644 --- a/rts/sm/OSMem.h +++ b/rts/sm/OSMem.h @@ -6,8 +6,13 @@ * * ---------------------------------------------------------------------------*/ +#ifndef SM_OSMEM_H +#define SM_OSMEM_H + void osMemInit(void); void *osGetMBlocks(nat n); void osFreeAllMBlocks(void); lnat getPageSize (void); void setExecutable (void *p, lnat len, rtsBool exec); + +#endif /* SM_OSMEM_H */ diff --git a/rts/sm/README b/rts/sm/README deleted file mode 100644 index 61cb7d2c06..0000000000 --- a/rts/sm/README +++ /dev/null @@ -1,11 +0,0 @@ -The Storage Manager -=================== - -This directory contains the storage manager and garbage collector. -The interfaces exported from here are: - - Storage.h (in ../includes) - Block.h (in ../includes) - GC.h - Arena.h - BlockAlloc.h diff --git a/rts/sm/Scav.c b/rts/sm/Scav.c index b850423244..9ebd4c5597 100644 --- a/rts/sm/Scav.c +++ b/rts/sm/Scav.c @@ -11,10 +11,10 @@ * * ---------------------------------------------------------------------------*/ +#include "PosixSource.h" #include "Rts.h" -#include "RtsFlags.h" + #include "Storage.h" -#include "MBlock.h" #include "GC.h" #include "GCThread.h" #include "GCUtils.h" @@ -23,7 +23,6 @@ #include "Scav.h" #include "Apply.h" #include "Trace.h" -#include "LdvProfile.h" #include "Sanity.h" #include "Capability.h" diff --git a/rts/sm/Scav.h b/rts/sm/Scav.h index df774cd63d..10b9ffde40 100644 --- a/rts/sm/Scav.h +++ b/rts/sm/Scav.h @@ -11,6 +11,9 @@ * * ---------------------------------------------------------------------------*/ +#ifndef SM_SCAV_H +#define SM_SCAV_H + void scavenge_loop (void); void scavenge_mutable_list (bdescr *bd, generation *gen); void scavenge_capability_mut_lists (Capability *cap); @@ -20,3 +23,6 @@ void scavenge_loop1 (void); void scavenge_mutable_list1 (bdescr *bd, generation *gen); void scavenge_capability_mut_Lists1 (Capability *cap); #endif + +#endif /* SM_SCAV_H */ + diff --git a/rts/sm/Storage.c b/rts/sm/Storage.c index d14e58856f..97615e9d1b 100644 --- a/rts/sm/Storage.c +++ b/rts/sm/Storage.c @@ -13,18 +13,15 @@ #include "PosixSource.h" #include "Rts.h" + +#include "Storage.h" #include "RtsUtils.h" -#include "RtsFlags.h" #include "Stats.h" -#include "Hooks.h" #include "BlockAlloc.h" -#include "MBlock.h" #include "Weak.h" #include "Sanity.h" #include "Arena.h" -#include "OSThreads.h" #include "Capability.h" -#include "Storage.h" #include "Schedule.h" #include "RetainerProfile.h" // for counting memory blocks (memInventory) #include "OSMem.h" @@ -32,7 +29,6 @@ #include "GC.h" #include "Evac.h" -#include <stdlib.h> #include <string.h> #include "ffi.h" @@ -71,6 +67,7 @@ step *nurseries = NULL; /* array of nurseries, >1 only if THREADED_RTS * Mutex sm_mutex; #endif +static void allocNurseries ( void ); static void initStep (step *stp, int g, int s) @@ -440,7 +437,7 @@ assignNurseriesToCapabilities (void) #endif } -void +static void allocNurseries( void ) { nat i; diff --git a/rts/sm/Storage.h b/rts/sm/Storage.h new file mode 100644 index 0000000000..c6aa45e162 --- /dev/null +++ b/rts/sm/Storage.h @@ -0,0 +1,169 @@ +/* ----------------------------------------------------------------------------- + * + * (c) The GHC Team, 1998-2009 + * + * External Storage Manger Interface + * + * ---------------------------------------------------------------------------*/ + +#ifndef SM_STORAGE_H +#define SM_STORAGE_H + +/* ----------------------------------------------------------------------------- + Initialisation / De-initialisation + -------------------------------------------------------------------------- */ + +void initStorage(void); +void exitStorage(void); +void freeStorage(void); + +/* ----------------------------------------------------------------------------- + Storage manager state + -------------------------------------------------------------------------- */ + +extern bdescr * pinned_object_block; + +extern nat alloc_blocks; +extern nat alloc_blocks_lim; + +INLINE_HEADER rtsBool +doYouWantToGC( void ) +{ + return (alloc_blocks >= alloc_blocks_lim); +} + +/* for splitting blocks groups in two */ +bdescr * splitLargeBlock (bdescr *bd, nat blocks); + +/* ----------------------------------------------------------------------------- + Generational garbage collection support + + recordMutable(StgPtr p) Informs the garbage collector that a + previously immutable object has + become (permanently) mutable. Used + by thawArray and similar. + + updateWithIndirection(p1,p2) Updates the object at p1 with an + indirection pointing to p2. This is + normally called for objects in an old + generation (>0) when they are updated. + + updateWithPermIndirection(p1,p2) As above but uses a permanent indir. + + -------------------------------------------------------------------------- */ + +/* + * Storage manager mutex + */ +#if defined(THREADED_RTS) +extern Mutex sm_mutex; +#endif + +#if defined(THREADED_RTS) +#define ACQUIRE_SM_LOCK ACQUIRE_LOCK(&sm_mutex); +#define RELEASE_SM_LOCK RELEASE_LOCK(&sm_mutex); +#define ASSERT_SM_LOCK() ASSERT_LOCK_HELD(&sm_mutex); +#else +#define ACQUIRE_SM_LOCK +#define RELEASE_SM_LOCK +#define ASSERT_SM_LOCK() +#endif + +INLINE_HEADER void +recordMutableGen(StgClosure *p, nat gen_no) +{ + bdescr *bd; + + bd = generations[gen_no].mut_list; + if (bd->free >= bd->start + BLOCK_SIZE_W) { + bdescr *new_bd; + new_bd = allocBlock(); + new_bd->link = bd; + bd = new_bd; + generations[gen_no].mut_list = bd; + } + *bd->free++ = (StgWord)p; + +} + +INLINE_HEADER void +recordMutableGenLock(StgClosure *p, nat gen_no) +{ + ACQUIRE_SM_LOCK; + recordMutableGen(p,gen_no); + RELEASE_SM_LOCK; +} + +INLINE_HEADER void +recordMutable(StgClosure *p) +{ + bdescr *bd; + ASSERT(closure_MUTABLE(p)); + bd = Bdescr((P_)p); + if (bd->gen_no > 0) recordMutableGen(p, bd->gen_no); +} + +INLINE_HEADER void +recordMutableLock(StgClosure *p) +{ + ACQUIRE_SM_LOCK; + recordMutable(p); + RELEASE_SM_LOCK; +} + +/* ----------------------------------------------------------------------------- + This is the write barrier for MUT_VARs, a.k.a. IORefs. A + MUT_VAR_CLEAN object is not on the mutable list; a MUT_VAR_DIRTY + is. When written to, a MUT_VAR_CLEAN turns into a MUT_VAR_DIRTY + and is put on the mutable list. + -------------------------------------------------------------------------- */ + +void dirty_MUT_VAR(StgRegTable *reg, StgClosure *p); + +/* ----------------------------------------------------------------------------- + Similarly, the write barrier for MVARs + -------------------------------------------------------------------------- */ + +void dirty_MVAR(StgRegTable *reg, StgClosure *p); + +/* ----------------------------------------------------------------------------- + Nursery manipulation + -------------------------------------------------------------------------- */ + +void resetNurseries ( void ); +void resizeNurseries ( nat blocks ); +void resizeNurseriesFixed ( nat blocks ); +lnat countNurseryBlocks ( void ); + +/* ----------------------------------------------------------------------------- + Stats 'n' DEBUG stuff + -------------------------------------------------------------------------- */ + +extern ullong total_allocated; + +lnat calcAllocated (void); +lnat calcLiveBlocks (void); +lnat calcLiveWords (void); +lnat countOccupied (bdescr *bd); +lnat calcNeeded (void); +HsInt64 getAllocations (void); + +#if defined(DEBUG) +void memInventory (rtsBool show); +void checkSanity (void); +nat countBlocks (bdescr *); +void checkNurserySanity (step *stp); +#endif + +/* ---------------------------------------------------------------------------- + Storage manager internal APIs and globals + ------------------------------------------------------------------------- */ + +#define END_OF_STATIC_LIST ((StgClosure*)1) + +void move_TSO (StgTSO *src, StgTSO *dest); + +extern StgClosure * caf_list; +extern StgClosure * revertible_caf_list; + +#endif /* SM_STORAGE_H */ diff --git a/rts/sm/Sweep.c b/rts/sm/Sweep.c index 444c3d5111..b6574024eb 100644 --- a/rts/sm/Sweep.c +++ b/rts/sm/Sweep.c @@ -11,9 +11,11 @@ * * ---------------------------------------------------------------------------*/ +#include "PosixSource.h" #include "Rts.h" + +#include "Storage.h" #include "Sweep.h" -#include "Block.h" #include "Trace.h" void diff --git a/rts/sm/Sweep.h b/rts/sm/Sweep.h index e7904a90a8..562a934faa 100644 --- a/rts/sm/Sweep.h +++ b/rts/sm/Sweep.h @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------------- * - * (c) The GHC Team 2008 + * (c) The GHC Team 2008 * * Simple mark/sweep, collecting whole blocks. * @@ -11,4 +11,9 @@ * * ---------------------------------------------------------------------------*/ +#ifndef SM_SWEEP_H +#define SM_SWEEP_H + void sweep(step *gen); + +#endif /* SM_SWEEP_H */ |