1 /* -----------------------------------------------------------------------------
2 * $Id: Storage.c,v 1.2 1998/12/02 13:28:57 simonm Exp $
4 * Storage manager front end
6 * ---------------------------------------------------------------------------*/
13 #include "BlockAlloc.h"
18 #include "StoragePriv.h"
20 bdescr *nursery; /* chained-blocks in the nursery */
21 bdescr *current_nursery; /* next available nursery block, or NULL */
22 nat nursery_blocks; /* number of blocks in the nursery */
24 StgClosure *caf_list = NULL;
26 bdescr *small_alloc_list; /* allocate()d small objects */
27 bdescr *large_alloc_list; /* allocate()d large objects */
28 nat alloc_blocks; /* number of allocate()d blocks since GC */
29 nat alloc_blocks_lim; /* approximate limit on alloc_blocks */
31 StgPtr alloc_Hp = NULL; /* next free byte in small_alloc_list */
32 StgPtr alloc_HpLim = NULL; /* end of block at small_alloc_list */
37 static void *stgAllocForGMP (size_t size_in_bytes);
38 static void *stgReallocForGMP (void *ptr, size_t old_size, size_t new_size);
39 static void stgDeallocForGMP (void *ptr, size_t size);
46 nursery = allocNursery(NULL, RtsFlags.GcFlags.minAllocAreaSize);
51 /* initialise the allocate() interface */
52 small_alloc_list = NULL;
53 large_alloc_list = NULL;
55 alloc_blocks_lim = RtsFlags.GcFlags.minAllocAreaSize;
58 /* Tell GNU multi-precision pkg about our custom alloc functions */
59 mp_set_memory_functions(stgAllocForGMP, stgReallocForGMP, stgDeallocForGMP);
64 allocNursery (bdescr *last_bd, nat blocks)
69 /* Allocate a nursery */
70 for (i=0; i < blocks; i++) {
77 nursery_blocks = blocks;
78 current_nursery = last_bd;
88 /* Return code ignored for now */
89 /* ToDo: allocation figure is slightly wrong (see also GarbageCollect()) */
90 allocated = (nursery_blocks * BLOCK_SIZE_W) + allocated_bytes();
91 for ( bd = current_nursery->link; bd != NULL; bd = bd->link ) {
92 allocated -= BLOCK_SIZE_W;
98 newCAF(StgClosure* caf)
100 const StgInfoTable *info = get_itbl(caf);
102 ASSERT(info->type == IND_STATIC);
103 STATIC_LINK2(info,caf) = caf_list;
107 /* -----------------------------------------------------------------------------
108 The allocate() interface
110 allocate(n) always succeeds, and returns a chunk of memory n words
111 long. n can be larger than the size of a block if necessary, in
112 which case a contiguous block group will be allocated.
113 -------------------------------------------------------------------------- */
121 TICK_ALLOC_PRIM(n,wibble,wibble,wibble)
124 /* big allocation (>LARGE_OBJECT_THRESHOLD) */
125 if (n >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
126 nat req_blocks = (lnat)BLOCK_ROUND_UP(n*sizeof(W_)) / BLOCK_SIZE;
127 bd = allocGroup(req_blocks);
128 bd->link = large_alloc_list;
130 if (large_alloc_list) {
131 large_alloc_list->back = bd; /* double-link the list */
133 large_alloc_list = bd;
135 /* don't add these blocks to alloc_blocks, since we're assuming
136 * that large objects are likely to remain live for quite a while
137 * (eg. running threads), so garbage collecting early won't make
142 /* small allocation (<LARGE_OBJECT_THRESHOLD) */
143 } else if (small_alloc_list == NULL || alloc_Hp + n > alloc_HpLim) {
144 if (small_alloc_list) {
145 small_alloc_list->free = alloc_Hp;
148 bd->link = small_alloc_list;
149 small_alloc_list = bd;
151 alloc_Hp = bd->start;
152 alloc_HpLim = bd->start + BLOCK_SIZE_W;
161 lnat allocated_bytes(void)
163 return (alloc_blocks * BLOCK_SIZE_W - (alloc_HpLim - alloc_Hp));
166 /* -----------------------------------------------------------------------------
167 Allocation functions for GMP.
169 These all use the allocate() interface - we can't have any garbage
170 collection going on during a gmp operation, so we use allocate()
171 which always succeeds. The gmp operations which might need to
172 allocate will ask the storage manager (via doYouWantToGC()) whether
173 a garbage collection is required, in case we get into a loop doing
174 only allocate() style allocation.
175 -------------------------------------------------------------------------- */
178 stgAllocForGMP (size_t size_in_bytes)
181 nat data_size_in_words, total_size_in_words;
183 /* should be a multiple of sizeof(StgWord) (whole no. of limbs) */
184 ASSERT(size_in_bytes % sizeof(W_) == 0);
186 data_size_in_words = size_in_bytes / sizeof(W_);
187 total_size_in_words = sizeofW(StgArrWords) + data_size_in_words;
189 /* allocate and fill it in. */
190 arr = (StgArrWords *)allocate(total_size_in_words);
191 SET_ARR_HDR(arr, &ARR_WORDS_info, CCCS, data_size_in_words);
193 /* and return a ptr to the goods inside the array */
194 return(BYTE_ARR_CTS(arr));
198 stgReallocForGMP (void *ptr, size_t old_size, size_t new_size)
200 void *new_stuff_ptr = stgAllocForGMP(new_size);
202 char *p = (char *) ptr;
203 char *q = (char *) new_stuff_ptr;
205 for (; i < old_size; i++, p++, q++) {
209 return(new_stuff_ptr);
213 stgDeallocForGMP (void *ptr STG_UNUSED,
214 size_t size STG_UNUSED)
216 /* easy for us: the garbage collector does the dealloc'n */