1 /* -----------------------------------------------------------------------------
3 * (c) The GHC Team 1998-2008
5 * MegaBlock Allocator Interface. This file contains all the dirty
6 * architecture-dependent hackery required to get a chunk of aligned
7 * memory from the operating system.
9 * ---------------------------------------------------------------------------*/
11 #include "PosixSource.h"
16 #include "BlockAlloc.h"
20 lnat mblocks_allocated = 0;
28 /* -----------------------------------------------------------------------------
29 The MBlock Map: provides our implementation of HEAP_ALLOCED()
30 -------------------------------------------------------------------------- */
32 #if SIZEOF_VOID_P == 4
33 StgWord8 mblock_map[MBLOCK_MAP_SIZE]; // initially all zeros
34 #elif SIZEOF_VOID_P == 8
35 static MBlockMap dummy_mblock_map;
36 MBlockMap *mblock_cache = &dummy_mblock_map;
37 nat mblock_map_count = 0;
38 MBlockMap **mblock_maps = NULL;
41 findMBlockMap(void *p)
44 StgWord32 hi = (StgWord32) (((StgWord)p) >> 32);
45 for( i = 0; i < mblock_map_count; i++ )
47 if(mblock_maps[i]->addrHigh32 == hi)
49 return mblock_maps[i];
56 slowIsHeapAlloced(void *p)
58 MBlockMap *map = findMBlockMap(p);
62 return map->mblocks[MBLOCK_MAP_ENTRY(p)];
70 markHeapAlloced(void *p)
72 #if SIZEOF_VOID_P == 4
73 mblock_map[MBLOCK_MAP_ENTRY(p)] = 1;
74 #elif SIZEOF_VOID_P == 8
75 MBlockMap *map = findMBlockMap(p);
79 mblock_maps = realloc(mblock_maps,
80 sizeof(MBlockMap*) * mblock_map_count);
81 map = mblock_maps[mblock_map_count-1] = calloc(1,sizeof(MBlockMap));
82 map->addrHigh32 = (StgWord32) (((StgWord)p) >> 32);
84 map->mblocks[MBLOCK_MAP_ENTRY(p)] = 1;
89 /* ----------------------------------------------------------------------------
90 Debugging code for traversing the allocated MBlocks
92 This is used for searching for lost blocks when a memory leak is
93 detected; see Blocks.c:findUnmarkedBlock().
94 ------------------------------------------------------------------------ */
98 #if SIZEOF_VOID_P == 4
101 void * mapEntryToMBlock(nat i)
103 return (void *)((StgWord)i << MBLOCK_SHIFT);
106 void * getFirstMBlock(void)
110 for (i = 0; i < MBLOCK_MAP_SIZE; i++) {
111 if (mblock_map[i]) return mapEntryToMBlock(i);
116 void * getNextMBlock(void *mblock)
120 for (i = MBLOCK_MAP_ENTRY(mblock) + 1; i < MBLOCK_MAP_SIZE; i++) {
121 if (mblock_map[i]) return mapEntryToMBlock(i);
126 #elif SIZEOF_VOID_P == 8
129 void * mapEntryToMBlock(MBlockMap *map, nat i)
131 return (void *)(((StgWord)map->addrHigh32) << 32) +
132 ((StgWord)i << MBLOCK_SHIFT);
135 void * getFirstMBlock(void)
140 for (j = 0; j < mblock_map_count; j++) {
141 map = mblock_maps[j];
142 for (i = 0; i < MBLOCK_MAP_SIZE; i++) {
143 if (map->mblocks[i]) return mapEntryToMBlock(map,i);
149 void * getNextMBlock(void *mblock)
154 for (j = 0; j < mblock_map_count; j++) {
155 map = mblock_maps[j];
156 if (map->addrHigh32 == (StgWord)mblock >> 32) break;
158 if (j == mblock_map_count) return NULL;
160 for (; j < mblock_map_count; j++) {
161 map = mblock_maps[j];
162 if (map->addrHigh32 == (StgWord)mblock >> 32) {
163 i = MBLOCK_MAP_ENTRY(mblock) + 1;
167 for (; i < MBLOCK_MAP_SIZE; i++) {
168 if (map->mblocks[i]) return mapEntryToMBlock(map,i);
174 #endif // SIZEOF_VOID_P
178 /* -----------------------------------------------------------------------------
179 Allocate new mblock(s)
180 -------------------------------------------------------------------------- */
185 return getMBlocks(1);
188 // The external interface: allocate 'n' mblocks, and return the
197 ret = osGetMBlocks(n);
199 debugTrace(DEBUG_gc, "allocated %d megablock(s) at %p",n,ret);
202 for (i = 0; i < n; i++) {
203 markHeapAlloced( ret + i * MBLOCK_SIZE );
206 mblocks_allocated += n;