1 /* -----------------------------------------------------------------------------
2 $Id: Arena.c,v 1.4 2002/07/28 02:31:11 sof Exp $
3 (c) The University of Glasgow 2001
5 Arena allocation. Arenas provide fast memory allocation at the
6 expense of fine-grained recycling of storage: memory may be
7 only be returned to the system by freeing the entire arena, it
8 isn't possible to return individual objects within an arena.
10 Do not assume that sequentially allocated objects will be adjacent
13 Quirks: this allocator makes use of the RTS block allocator. If
14 the current block doesn't have enough room for the requested
15 object, then a new block is allocated. This means that allocating
16 large objects will tend to result in wasted space at the end of
17 each block. In the worst case, half of the allocated space is
18 wasted. This allocator is therefore best suited to situations in
19 which most allocations are small.
20 -------------------------------------------------------------------------- */
25 #include "BlockAlloc.h"
28 // Each arena struct is allocated using malloc().
31 StgWord *free; // ptr to next free byte in current block
32 StgWord *lim; // limit (== last free byte + 1)
35 // We like to keep track of how many blocks we've allocated for
36 // Storage.c:memInventory().
37 static long arena_blocks = 0;
45 arena = stgMallocBytes(sizeof(Arena), "newArena");
46 arena->current = allocBlock();
47 arena->current->link = NULL;
48 arena->free = arena->current->start;
49 arena->lim = arena->current->start + BLOCK_SIZE_W;
55 // Allocate some memory in an arena
57 arenaAlloc( Arena *arena, size_t size )
64 // The minimum alignment of an allocated block.
67 // size of allocated block in words, rounded up to the nearest
69 size_w = ((size + MIN_ALIGN - 1) / MIN_ALIGN) * (MIN_ALIGN/sizeof(W_));
71 if ( arena->free + size_w < arena->lim ) {
72 // enough room in the current block...
74 arena->free += size_w;
77 // allocate a fresh block...
78 req_blocks = (lnat)BLOCK_ROUND_UP(size_w*sizeof(W_)) / BLOCK_SIZE;
79 bd = allocGroup(req_blocks);
80 arena_blocks += req_blocks;
86 bd->link = arena->current;
88 arena->free = bd->free + size_w;
89 arena->lim = bd->free + bd->blocks * BLOCK_SIZE_W;
94 // Free an entire arena
96 arenaFree( Arena *arena )
100 for (bd = arena->current; bd != NULL; bd = next) {
102 arena_blocks -= bd->blocks;
103 ASSERT(arena_blocks >= 0);