X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FStorage.c;h=4933854049a353ff5abd43b8fc7b0230f380d730;hb=2322bc9a89a9d8a6132a6818ccff6f665d7ed7f1;hp=dadcf1dfb9a91db1d7fb2614fafda6acf757bdc0;hpb=5a36a56294ccebb23e92efc8fded69fb4677e276;p=ghc-hetmet.git diff --git a/ghc/rts/Storage.c b/ghc/rts/Storage.c index dadcf1d..4933854 100644 --- a/ghc/rts/Storage.c +++ b/ghc/rts/Storage.c @@ -27,7 +27,7 @@ #include /* - * All these globals require sm_mutex to access in SMP mode. + * All these globals require sm_mutex to access in THREADED_RTS mode. */ StgClosure *caf_list = NULL; StgClosure *revertible_caf_list = NULL; @@ -49,16 +49,21 @@ step *g0s0 = NULL; /* generation 0, step 0, for convenience */ ullong total_allocated = 0; /* total memory allocated during run */ nat n_nurseries = 0; /* == RtsFlags.ParFlags.nNodes, convenience */ -step *nurseries = NULL; /* array of nurseries, >1 only if SMP */ +step *nurseries = NULL; /* array of nurseries, >1 only if THREADED_RTS */ +#ifdef THREADED_RTS /* * Storage manager mutex: protects all the above state from * simultaneous access by two STG threads. */ -#ifdef SMP -Mutex sm_mutex = INIT_MUTEX_VAR; +Mutex sm_mutex; +/* + * This mutex is used by atomicModifyMutVar# only + */ +Mutex atomic_modify_mutvar_mutex; #endif + /* * Forward references */ @@ -125,10 +130,13 @@ initStorage( void ) initBlockAllocator(); -#if defined(SMP) +#if defined(THREADED_RTS) initMutex(&sm_mutex); + initMutex(&atomic_modify_mutvar_mutex); #endif + ACQUIRE_SM_LOCK; + /* allocate generation info array */ generations = (generation *)stgMallocBytes(RtsFlags.GcFlags.generations * sizeof(struct generation_), @@ -171,8 +179,8 @@ initStorage( void ) g0->steps = stgMallocBytes (sizeof(struct step_), "initStorage: steps"); } -#ifdef SMP - n_nurseries = RtsFlags.ParFlags.nNodes; +#ifdef THREADED_RTS + n_nurseries = n_capabilities; nurseries = stgMallocBytes (n_nurseries * sizeof(struct step_), "initStorage: nurseries"); #else @@ -187,7 +195,7 @@ initStorage( void ) } } -#ifdef SMP +#ifdef THREADED_RTS for (s = 0; s < n_nurseries; s++) { initStep(&nurseries[s], 0, s); } @@ -202,7 +210,7 @@ initStorage( void ) } oldest_gen->steps[0].to = &oldest_gen->steps[0]; -#ifdef SMP +#ifdef THREADED_RTS for (s = 0; s < n_nurseries; s++) { nurseries[s].to = generations[0].steps[0].to; } @@ -217,10 +225,10 @@ initStorage( void ) } } -#ifdef SMP +#ifdef THREADED_RTS if (RtsFlags.GcFlags.generations == 1) { - errorBelch("-G1 is incompatible with SMP"); - stg_exit(1); + errorBelch("-G1 is incompatible with -threaded"); + stg_exit(EXIT_FAILURE); } #endif @@ -250,6 +258,8 @@ initStorage( void ) mp_set_memory_functions(stgAllocForGMP, stgReallocForGMP, stgDeallocForGMP); IF_DEBUG(gc, statDescribeGens()); + + RELEASE_SM_LOCK; } void @@ -405,7 +415,7 @@ allocNursery (step *stp, bdescr *tail, nat blocks) static void assignNurseriesToCapabilities (void) { -#ifdef SMP +#ifdef THREADED_RTS nat i; for (i = 0; i < n_nurseries; i++) { @@ -413,7 +423,7 @@ assignNurseriesToCapabilities (void) capabilities[i].r.rCurrentNursery = nurseries[i].blocks; capabilities[i].r.rCurrentAlloc = NULL; } -#else /* SMP */ +#else /* THREADED_RTS */ MainCapability.r.rNursery = &nurseries[0]; MainCapability.r.rCurrentNursery = nurseries[0].blocks; MainCapability.r.rCurrentAlloc = NULL; @@ -625,7 +635,7 @@ tidyAllocateLists (void) -------------------------------------------------------------------------- */ StgPtr -allocateLocal( StgRegTable *reg, nat n ) +allocateLocal (Capability *cap, nat n) { bdescr *bd; StgPtr p; @@ -652,36 +662,36 @@ allocateLocal( StgRegTable *reg, nat n ) /* small allocation (rCurrentAlloc; + bd = cap->r.rCurrentAlloc; if (bd == NULL || bd->free + n > bd->start + BLOCK_SIZE_W) { // The CurrentAlloc block is full, we need to find another // one. First, we try taking the next block from the // nursery: - bd = reg->rCurrentNursery->link; + bd = cap->r.rCurrentNursery->link; if (bd == NULL || bd->free + n > bd->start + BLOCK_SIZE_W) { // The nursery is empty, or the next block is already // full: allocate a fresh block (we can't fail here). ACQUIRE_SM_LOCK; bd = allocBlock(); - reg->rNursery->n_blocks++; + cap->r.rNursery->n_blocks++; RELEASE_SM_LOCK; bd->gen_no = 0; - bd->step = g0s0; + bd->step = cap->r.rNursery; bd->flags = 0; } else { // we have a block in the nursery: take it and put // it at the *front* of the nursery list, and use it // to allocate() from. - reg->rCurrentNursery->link = bd->link; + cap->r.rCurrentNursery->link = bd->link; if (bd->link != NULL) { - bd->link->u.back = reg->rCurrentNursery; + bd->link->u.back = cap->r.rCurrentNursery; } } - dbl_link_onto(bd, ®->rNursery->blocks); - reg->rCurrentAlloc = bd; - IF_DEBUG(sanity, checkNurserySanity(reg->rNursery)); + dbl_link_onto(bd, &cap->r.rNursery->blocks); + cap->r.rCurrentAlloc = bd; + IF_DEBUG(sanity, checkNurserySanity(cap->r.rNursery)); } } p = bd->free; @@ -755,6 +765,25 @@ allocatePinned( nat n ) } /* ----------------------------------------------------------------------------- + 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) +{ + Capability *cap = regTableToCapability(reg); + bdescr *bd; + if (p->header.info == &stg_MUT_VAR_CLEAN_info) { + p->header.info = &stg_MUT_VAR_DIRTY_info; + bd = Bdescr((StgPtr)p); + if (bd->gen_no > 0) recordMutableCap(p,cap,bd->gen_no); + } +} + +/* ----------------------------------------------------------------------------- Allocation functions for GMP. These all use the allocate() interface - we can't have any garbage @@ -776,10 +805,10 @@ stgAllocForGMP (size_t size_in_bytes) total_size_in_words = sizeofW(StgArrWords) + data_size_in_words; /* allocate and fill it in. */ -#if defined(SMP) - arr = (StgArrWords *)allocateLocal(&(myCapability()->r), total_size_in_words); +#if defined(THREADED_RTS) + arr = (StgArrWords *)allocateLocal(myTask()->cap, total_size_in_words); #else - arr = (StgArrWords *)allocateLocal(&MainCapability.r, total_size_in_words); + arr = (StgArrWords *)allocateLocal(&MainCapability, total_size_in_words); #endif SET_ARR_HDR(arr, &stg_ARR_WORDS_info, CCCS, data_size_in_words); @@ -832,7 +861,7 @@ calcAllocated( void ) allocated += countNurseryBlocks() * BLOCK_SIZE_W; { -#ifdef SMP +#ifdef THREADED_RTS nat i; for (i = 0; i < n_nurseries; i++) { Capability *cap; @@ -976,6 +1005,11 @@ memInventory(void) /* count the blocks we current have */ for (g = 0; g < RtsFlags.GcFlags.generations; g++) { + for (i = 0; i < n_capabilities; i++) { + for (bd = capabilities[i].mut_lists[g]; bd != NULL; bd = bd->link) { + total_blocks += bd->blocks; + } + } for (bd = generations[g].mut_list; bd != NULL; bd = bd->link) { total_blocks += bd->blocks; } @@ -989,6 +1023,10 @@ memInventory(void) for (i = 0; i < n_nurseries; i++) { total_blocks += stepBlocks(&nurseries[i]); } +#ifdef THREADED_RTS + // We put pinned object blocks in g0s0, so better count blocks there too. + total_blocks += stepBlocks(g0s0); +#endif /* any blocks held by allocate() */ for (bd = small_alloc_list; bd; bd = bd->link) {