2
* mminit.c -- $Id: mminit.c,v 1.1 2003/03/08 15:26:47 travo Exp $
3
* basic memory management interface
5
* compile this file twice:
6
* P_DEBUG not defined makes production version (p_mminit)
7
* P_DEBUG defined makes debug version (p_mmdebug)
9
* Copyright (c) 1998. See accompanying LEGAL file for details.
15
typedef union mm_block mm_block;
16
typedef struct mm_arena mm_arena;
19
mm_block *next_free; /* when not in use */
20
mm_arena *arena; /* when in use */
21
/* remainder assure most restrictive alignment */
23
double d; /* long double tickles bug for linux gcc 2.7.2 */
30
# define MM_GUARD(block, n)
31
# define MM_CHECK(p, n)
36
# define MM_GUARD(block, n) p_mmguard(block, n);
37
# define MM_CHECK(p, n) if (p_mmcheck(p)) return p_mmfail(n);
38
# define MM_VCHECK(p) if (p_mmcheck(p)) { p_mmfail(0); return; }
39
long p_mmoffset = MM_OFFSET*sizeof(mm_block);
40
long p_mmextra = MM_EXTRA*sizeof(mm_block);
43
static void *bmalloc(size_t);
44
static void bfree(void *);
45
static void *brealloc(void *, size_t);
49
mm_block *blocks; /* current chunk */
50
long n_blocks; /* total number of mm_blocks per chunk */
51
long size; /* number of mm_blocks per unit */
54
/* the numbers are the number of allocation units per chunk
55
* and the number of mm_blocks per unit (augmented by MM_EXTRA) */
56
static mm_arena arenas[6] = {
57
{ 0, 0, 512*( 1+MM_EXTRA), 1+MM_EXTRA },
58
{ 0, 0, 384*( 2+MM_EXTRA), 2+MM_EXTRA },
59
{ 0, 0, 256*( 4+MM_EXTRA), 4+MM_EXTRA },
60
{ 0, 0, 128*( 8+MM_EXTRA), 8+MM_EXTRA },
61
{ 0, 0, 64 *(16+MM_EXTRA), 16+MM_EXTRA },
62
{ 0, 0, 32 *(32+MM_EXTRA), 32+MM_EXTRA }};
64
static mm_arena *arena_list[32] = {
65
arenas, arenas+1,arenas+2,arenas+2,arenas+3,arenas+3,arenas+3,arenas+3,
66
arenas+4,arenas+4,arenas+4,arenas+4,arenas+4,arenas+4,arenas+4,arenas+4,
67
arenas+5,arenas+5,arenas+5,arenas+5,arenas+5,arenas+5,arenas+5,arenas+5,
68
arenas+5,arenas+5,arenas+5,arenas+5,arenas+5,arenas+5,arenas+5,arenas+5 };
70
static mm_block *expand_arena(mm_arena *arena);
73
p_mminit(void) /* actually p_mmdebug if P_DEBUG */
77
p_realloc = &brealloc;
85
if (n <= 32*sizeof(mm_block)) {
86
mm_arena *arena = arena_list[(n-1)/sizeof(mm_block)];
87
block = arena->next_free;
89
block = expand_arena(arena);
90
if (!block) return p_mmfail(n);
92
arena->next_free = block->next_free;
96
block = (void *)malloc(MM_EXTRA*sizeof(mm_block)+n);
97
if (!block) return p_mmfail(n);
102
return block+MM_OFFSET;
109
mm_block *block = ((mm_block *)p) - MM_OFFSET;
110
mm_arena *arena = block->arena;
113
block->next_free = arena->next_free;
114
arena->next_free = block;
124
expand_arena(mm_arena *arena)
126
long n = arena->n_blocks;
127
long size = sizeof(mm_block)*(n+1);
128
mm_block *block = (void *)malloc(size);
129
if (!block) return p_mmfail(size);
130
block[0].next_free = arena->blocks;
131
arena->blocks = block++;
133
for (size=arena->size ; n-=size ; block+=size)
134
block->next_free = block + size;
135
block->next_free = 0;
136
return (arena->next_free = arena->blocks+1);
140
brealloc(void *p, size_t n)
143
mm_block *block = ((mm_block *)p) - MM_OFFSET;
144
mm_arena *arena = block->arena;
145
MM_CHECK(p, n<=0? 1 : n)
148
long i, old_n = arena->size-MM_EXTRA;
149
if (n <= sizeof(mm_block)*old_n) {
153
new_block = bmalloc(n);
154
if (!new_block) return p_mmfail(n<=0? 1 : n);
155
for (i=0 ; i<old_n ; i++) new_block[i] = block[i+MM_OFFSET];
156
block->next_free = arena->next_free;
157
arena->next_free = block;
161
/* don't bother trying to put shrinking blocks back into
162
* the small block arenas */
164
block = (void *)realloc(block, MM_EXTRA*sizeof(mm_block)+n);
165
if (!block) return p_mmfail(n);
167
return block+MM_OFFSET;
175
/* provide primitive checking for memory overrun and underrun
176
* checked on every free or realloc operation, or p_mmcheck can
177
* be called anytime by debugger or debugging code */
179
static mm_block ur_pattern;
180
static char *pattern = 0;
183
p_mmguard(void *b, unsigned long n)
186
char *p = (char *)&block[2];
189
pattern = (char *)&ur_pattern;
190
for (i=0 ; i<sizeof(mm_block) ; i++) pattern[i] = 255-i;
193
for (i=0 ; i<sizeof(mm_block) ; i++) p[i] = pattern[i];
194
p += sizeof(mm_block)+n;
195
for (i=0 ; i<sizeof(mm_block) ; i++) p[i] = pattern[i];
202
char *chk = (char *)&block[-1];
203
unsigned long n = block[-2].l;
205
for (i=0 ; i<sizeof(mm_block) ; i++) if (chk[i]!=pattern[i]) break;
206
if (i<sizeof(mm_block)) return 1; /* signal memory underrun */
207
chk += sizeof(mm_block)+n;
208
for (i=0 ; i<sizeof(mm_block) ; i++) if (chk[i]!=pattern[i]) break;
209
if (i<sizeof(mm_block)) return 2; /* signal memory overrun */