X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2Fsm%2FMBlock.c;h=b9d71f68c9ca64054a9c1d6e585431b1ef09625b;hb=d63ba79a6dde7a5616d3b532589ff09d3820f794;hp=28aa7b0a43be154224b30b89c6e913f278967932;hpb=43a120b706a5eece6624ca4907af89fc9a480c5e;p=ghc-hetmet.git diff --git a/rts/sm/MBlock.c b/rts/sm/MBlock.c index 28aa7b0..b9d71f6 100644 --- a/rts/sm/MBlock.c +++ b/rts/sm/MBlock.c @@ -9,21 +9,18 @@ * ---------------------------------------------------------------------------*/ #include "PosixSource.h" - #include "Rts.h" + #include "RtsUtils.h" -#include "MBlock.h" #include "BlockAlloc.h" #include "Trace.h" #include "OSMem.h" -lnat mblocks_allocated = 0; +#include -void -initMBlocks(void) -{ - osMemInit(); -} +lnat peak_mblocks_allocated = 0; +lnat mblocks_allocated = 0; +lnat mpc_misses = 0; /* ----------------------------------------------------------------------------- The MBlock Map: provides our implementation of HEAP_ALLOCED() @@ -31,12 +28,21 @@ initMBlocks(void) #if SIZEOF_VOID_P == 4 StgWord8 mblock_map[MBLOCK_MAP_SIZE]; // initially all zeros + +static void +setHeapAlloced(void *p, StgWord8 i) +{ + mblock_map[MBLOCK_MAP_ENTRY(p)] = i; +} + #elif SIZEOF_VOID_P == 8 -static MBlockMap dummy_mblock_map; -MBlockMap *mblock_cache = &dummy_mblock_map; -nat mblock_map_count = 0; + MBlockMap **mblock_maps = NULL; +nat mblock_map_count = 0; + +MbcCacheLine mblock_cache[MBC_ENTRIES]; + static MBlockMap * findMBlockMap(void *p) { @@ -52,48 +58,69 @@ findMBlockMap(void *p) return NULL; } -StgBool -slowIsHeapAlloced(void *p) +StgBool HEAP_ALLOCED_miss(StgWord mblock, void *p) { - MBlockMap *map = findMBlockMap(p); - if(map) + MBlockMap *map; + MBlockMapLine value; + nat entry_no; + + entry_no = mblock & (MBC_ENTRIES-1); + + map = findMBlockMap(p); + if (map) { - mblock_cache = map; - return map->mblocks[MBLOCK_MAP_ENTRY(p)]; + mpc_misses++; + value = map->lines[MBLOCK_MAP_LINE(p)]; + mblock_cache[entry_no] = (mblock<<1) | value; + return value; } else - return 0; + { + mblock_cache[entry_no] = (mblock<<1); + return 0; + } } -#endif static void -markHeapAlloced(void *p) +setHeapAlloced(void *p, StgWord8 i) { -#if SIZEOF_VOID_P == 4 - mblock_map[MBLOCK_MAP_ENTRY(p)] = 1; -#elif SIZEOF_VOID_P == 8 MBlockMap *map = findMBlockMap(p); if(map == NULL) { mblock_map_count++; - mblock_maps = realloc(mblock_maps, - sizeof(MBlockMap*) * mblock_map_count); - map = mblock_maps[mblock_map_count-1] = calloc(1,sizeof(MBlockMap)); + mblock_maps = stgReallocBytes(mblock_maps, + sizeof(MBlockMap*) * mblock_map_count, + "markHeapAlloced(1)"); + map = mblock_maps[mblock_map_count-1] = + stgMallocBytes(sizeof(MBlockMap),"markHeapAlloced(2)"); + memset(map,0,sizeof(MBlockMap)); map->addrHigh32 = (StgWord32) (((StgWord)p) >> 32); } - map->mblocks[MBLOCK_MAP_ENTRY(p)] = 1; - mblock_cache = map; -#endif + + map->lines[MBLOCK_MAP_LINE(p)] = i; + + { + StgWord mblock; + nat entry_no; + + mblock = (StgWord)p >> MBLOCK_SHIFT; + entry_no = mblock & (MBC_ENTRIES-1); + mblock_cache[entry_no] = (mblock << 1) + i; + } } +#endif -/* ---------------------------------------------------------------------------- - Debugging code for traversing the allocated MBlocks - - This is used for searching for lost blocks when a memory leak is - detected; see Blocks.c:findUnmarkedBlock(). - ------------------------------------------------------------------------ */ +static void +markHeapAlloced(void *p) +{ + setHeapAlloced(p, 1); +} -#ifdef DEBUG +static void +markHeapUnalloced(void *p) +{ + setHeapAlloced(p, 0); +} #if SIZEOF_VOID_P == 4 @@ -125,55 +152,65 @@ void * getNextMBlock(void *mblock) #elif SIZEOF_VOID_P == 8 -STATIC_INLINE -void * mapEntryToMBlock(MBlockMap *map, nat i) -{ - return (void *)(((StgWord)map->addrHigh32) << 32) + - ((StgWord)i << MBLOCK_SHIFT); -} - -void * getFirstMBlock(void) -{ - MBlockMap *map; - nat i, j; - - for (j = 0; j < mblock_map_count; j++) { - map = mblock_maps[j]; - for (i = 0; i < MBLOCK_MAP_SIZE; i++) { - if (map->mblocks[i]) return mapEntryToMBlock(map,i); - } - } - return NULL; -} - -void * getNextMBlock(void *mblock) +void * getNextMBlock(void *p) { MBlockMap *map; - nat i, j; + nat off, j; + nat line_no; + MBlockMapLine line; for (j = 0; j < mblock_map_count; j++) { map = mblock_maps[j]; - if (map->addrHigh32 == (StgWord)mblock >> 32) break; + if (map->addrHigh32 == (StgWord)p >> 32) break; } if (j == mblock_map_count) return NULL; for (; j < mblock_map_count; j++) { map = mblock_maps[j]; - if (map->addrHigh32 == (StgWord)mblock >> 32) { - i = MBLOCK_MAP_ENTRY(mblock) + 1; + if (map->addrHigh32 == (StgWord)p >> 32) { + line_no = MBLOCK_MAP_LINE(p); + off = (((StgWord)p >> MBLOCK_SHIFT) & (MBC_LINE_SIZE-1)) + 1; + // + 1 because we want the *next* mblock } else { - i = 0; + line_no = 0; off = 0; } - for (; i < MBLOCK_MAP_SIZE; i++) { - if (map->mblocks[i]) return mapEntryToMBlock(map,i); + for (; line_no < MBLOCK_MAP_ENTRIES; line_no++) { + line = map->lines[line_no]; + for (; off < MBC_LINE_SIZE; off++) { + if (line & (1<addrHigh32 << 32) + + line_no * MBC_LINE_SIZE * MBLOCK_SIZE + + off * MBLOCK_SIZE); + } + } + off = 0; } } return NULL; } -#endif // SIZEOF_VOID_P +void * getFirstMBlock(void) +{ + MBlockMap *map = mblock_maps[0]; + nat line_no, off; + MbcCacheLine line; + + for (line_no = 0; line_no < MBLOCK_MAP_ENTRIES; line_no++) { + line = map->lines[line_no]; + if (line) { + for (off = 0; off < MBC_LINE_SIZE; off++) { + if (line & (1<addrHigh32 << 32) + + line_no * MBC_LINE_SIZE * MBLOCK_SIZE + + off * MBLOCK_SIZE); + } + } + } + } + return NULL; +} -#endif // DEBUG +#endif // SIZEOF_VOID_P /* ----------------------------------------------------------------------------- Allocate new mblock(s) @@ -200,16 +237,51 @@ 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; + peak_mblocks_allocated = stg_max(peak_mblocks_allocated, mblocks_allocated); return ret; } void +freeMBlocks(void *addr, nat n) +{ + nat i; + + debugTrace(DEBUG_gc, "freeing %d megablock(s) at %p",n,addr); + + mblocks_allocated -= n; + + for (i = 0; i < n; i++) { + markHeapUnalloced( (StgWord8*)addr + i * MBLOCK_SIZE ); + } + + osFreeMBlocks(addr, n); +} + +void freeAllMBlocks(void) { + nat n; + + debugTrace(DEBUG_gc, "freeing all megablocks"); + osFreeAllMBlocks(); + + for (n = 0; n < mblock_map_count; n++) { + stgFree(mblock_maps[n]); + } + stgFree(mblock_maps); +} + +void +initMBlocks(void) +{ + osMemInit(); +#if SIZEOF_VOID_P == 8 + memset(mblock_cache,0xff,sizeof(mblock_cache)); +#endif }