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"
15 #include "BlockAlloc.h"
21 lnat mblocks_allocated = 0;
24 /* -----------------------------------------------------------------------------
25 The MBlock Map: provides our implementation of HEAP_ALLOCED()
26 -------------------------------------------------------------------------- */
28 #if SIZEOF_VOID_P == 4
29 StgWord8 mblock_map[MBLOCK_MAP_SIZE]; // initially all zeros
32 markHeapAlloced(void *p)
34 mblock_map[MBLOCK_MAP_ENTRY(p)] = 1;
37 #elif SIZEOF_VOID_P == 8
39 MBlockMap **mblock_maps = NULL;
41 nat mblock_map_count = 0;
43 MbcCacheLine mblock_cache[MBC_ENTRIES];
46 findMBlockMap(void *p)
49 StgWord32 hi = (StgWord32) (((StgWord)p) >> 32);
50 for( i = 0; i < mblock_map_count; i++ )
52 if(mblock_maps[i]->addrHigh32 == hi)
54 return mblock_maps[i];
60 StgBool HEAP_ALLOCED_miss(StgWord mblock, void *p)
66 entry_no = mblock & (MBC_ENTRIES-1);
68 map = findMBlockMap(p);
72 value = map->lines[MBLOCK_MAP_LINE(p)];
73 mblock_cache[entry_no] = (mblock<<1) | value;
78 mblock_cache[entry_no] = (mblock<<1);
84 markHeapAlloced(void *p)
86 MBlockMap *map = findMBlockMap(p);
90 mblock_maps = realloc(mblock_maps,
91 sizeof(MBlockMap*) * mblock_map_count);
92 map = mblock_maps[mblock_map_count-1] =
93 stgMallocBytes(sizeof(MBlockMap),"markHeapAlloced");
94 memset(map,0,sizeof(MBlockMap));
95 map->addrHigh32 = (StgWord32) (((StgWord)p) >> 32);
98 map->lines[MBLOCK_MAP_LINE(p)] = 1;
104 mblock = (StgWord)p >> MBLOCK_SHIFT;
105 entry_no = mblock & (MBC_ENTRIES-1);
106 mblock_cache[entry_no] = (mblock << 1) + 1;
111 /* ----------------------------------------------------------------------------
112 Debugging code for traversing the allocated MBlocks
114 This is used for searching for lost blocks when a memory leak is
115 detected; see Blocks.c:findUnmarkedBlock().
116 ------------------------------------------------------------------------ */
120 #if SIZEOF_VOID_P == 4
123 void * mapEntryToMBlock(nat i)
125 return (void *)((StgWord)i << MBLOCK_SHIFT);
128 void * getFirstMBlock(void)
132 for (i = 0; i < MBLOCK_MAP_SIZE; i++) {
133 if (mblock_map[i]) return mapEntryToMBlock(i);
138 void * getNextMBlock(void *mblock)
142 for (i = MBLOCK_MAP_ENTRY(mblock) + 1; i < MBLOCK_MAP_SIZE; i++) {
143 if (mblock_map[i]) return mapEntryToMBlock(i);
148 #elif SIZEOF_VOID_P == 8
150 void * getNextMBlock(void *p)
157 for (j = 0; j < mblock_map_count; j++) {
158 map = mblock_maps[j];
159 if (map->addrHigh32 == (StgWord)p >> 32) break;
161 if (j == mblock_map_count) return NULL;
163 for (; j < mblock_map_count; j++) {
164 map = mblock_maps[j];
165 if (map->addrHigh32 == (StgWord)p >> 32) {
166 line_no = MBLOCK_MAP_LINE(p);
167 off = (((StgWord)p >> MBLOCK_SHIFT) & (MBC_LINE_SIZE-1)) + 1;
168 // + 1 because we want the *next* mblock
170 line_no = 0; off = 0;
172 for (; line_no < MBLOCK_MAP_ENTRIES; line_no++) {
173 line = map->lines[line_no];
174 for (; off < MBC_LINE_SIZE; off++) {
175 if (line & (1<<off)) {
176 return (void*)(((StgWord)map->addrHigh32 << 32) +
177 line_no * MBC_LINE_SIZE * MBLOCK_SIZE +
187 void * getFirstMBlock(void)
189 MBlockMap *map = mblock_maps[0];
193 for (line_no = 0; line_no < MBLOCK_MAP_ENTRIES; line_no++) {
194 line = map->lines[line_no];
196 for (off = 0; off < MBC_LINE_SIZE; off++) {
197 if (line & (1<<off)) {
198 return (void*)(((StgWord)map->addrHigh32 << 32) +
199 line_no * MBC_LINE_SIZE * MBLOCK_SIZE +
208 #endif // SIZEOF_VOID_P
212 /* -----------------------------------------------------------------------------
213 Allocate new mblock(s)
214 -------------------------------------------------------------------------- */
219 return getMBlocks(1);
222 // The external interface: allocate 'n' mblocks, and return the
231 ret = osGetMBlocks(n);
233 debugTrace(DEBUG_gc, "allocated %d megablock(s) at %p",n,ret);
236 for (i = 0; i < n; i++) {
237 markHeapAlloced( (StgWord8*)ret + i * MBLOCK_SIZE );
240 mblocks_allocated += n;
255 #if SIZEOF_VOID_P == 8
256 memset(mblock_cache,0xff,sizeof(mblock_cache));