Refactoring: extract platform-specific code from sm/MBlock.c
[ghc-hetmet.git] / rts / sm / MBlock.c
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team 1998-2007
4  *
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.
8  *
9  * ---------------------------------------------------------------------------*/
10
11 #include "PosixSource.h"
12
13 #include "Rts.h"
14 #include "RtsUtils.h"
15 #include "MBlock.h"
16 #include "BlockAlloc.h"
17 #include "Trace.h"
18 #include "OSMem.h"
19
20 lnat mblocks_allocated = 0;
21
22 void
23 initMBlocks(void)
24 {
25     osMemInit();
26 }
27
28 /* -----------------------------------------------------------------------------
29    The MBlock Map: provides our implementation of HEAP_ALLOCED()
30    -------------------------------------------------------------------------- */
31
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 int mblock_map_count = 0;
38 MBlockMap **mblock_maps = NULL;
39
40 static MBlockMap *
41 findMBlockMap(void *p)
42 {
43     int i;
44     StgWord32 hi = (StgWord32) (((StgWord)p) >> 32);
45     for( i = 0; i < mblock_map_count; i++ )
46     {
47         if(mblock_maps[i]->addrHigh32 == hi)
48         {
49             return mblock_maps[i];
50         }
51     }
52     return NULL;
53 }
54
55 StgBool
56 slowIsHeapAlloced(void *p)
57 {
58     MBlockMap *map = findMBlockMap(p);
59     if(map)
60     {
61         mblock_cache = map;
62         return map->mblocks[MBLOCK_MAP_ENTRY(p)];
63     }
64     else
65         return 0;
66 }
67 #endif
68
69 static void
70 markHeapAlloced(void *p)
71 {
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);
76     if(map == NULL)
77     {
78         mblock_map_count++;
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);
83     }
84     map->mblocks[MBLOCK_MAP_ENTRY(p)] = 1;
85     mblock_cache = map;
86 #endif
87 }
88
89 /* -----------------------------------------------------------------------------
90    Allocate new mblock(s)
91    -------------------------------------------------------------------------- */
92
93 void *
94 getMBlock(void)
95 {
96   return getMBlocks(1);
97 }
98
99 // The external interface: allocate 'n' mblocks, and return the
100 // address.
101
102 void *
103 getMBlocks(nat n)
104 {
105     nat i;
106     void *ret;
107
108     ret = osGetMBlocks(n);
109
110     debugTrace(DEBUG_gc, "allocated %d megablock(s) at %p",n,ret);
111     
112     // fill in the table
113     for (i = 0; i < n; i++) {
114         markHeapAlloced( ret + i * MBLOCK_SIZE );
115     }
116     
117     mblocks_allocated += n;
118
119     return ret;
120 }
121
122 void
123 freeAllMBlocks(void)
124 {
125     osFreeAllMBlocks();
126 }