3
#define POOLFREE 0x55555555L /* block free indicator */
5
/* Method for pool allocation.
6
** All elements in a pool have the same size.
7
** The following fields of Vmdata_t are used as:
8
** pool: size of a block.
9
** free: list of free blocks.
11
** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
15
static Void_t* poolalloc(Vmalloc_t* vm, reg size_t size)
17
static Void_t* poolalloc(vm, size )
22
reg Vmdata_t* vd = vm->data;
23
reg Block_t *tp, *next;
30
else if(size != vd->pool)
33
else return NIL(Void_t*);
36
if(!(local = vd->mode&VM_TRUST) )
42
if((tp = vd->free) ) /* there is a ready free block */
43
{ vd->free = SEGLINK(tp);
47
size = ROUND(size,ALIGN);
49
/* look thru all segments for a suitable free block */
50
for(tp = NIL(Block_t*), seg = vd->seg; seg; seg = seg->next)
51
{ if((tp = seg->free) &&
52
(s = (SIZE(tp) & ~BITS) + sizeof(Head_t)) >= size )
56
for(;;) /* must extend region */
57
{ if((tp = (*_Vmextend)(vm,ROUND(size,vd->incr),NIL(Vmsearch_f))) )
58
{ s = (SIZE(tp) & ~BITS) + sizeof(Head_t);
62
else if(vd->mode&VM_AGAIN)
63
vd->mode &= ~VM_AGAIN;
67
has_blk: /* if get here, (tp, s, seg) must be well-defined */
68
next = (Block_t*)((Vmuchar_t*)tp+size);
69
if((s -= size) <= (size + sizeof(Head_t)) )
70
{ for(; s >= size; s -= size)
71
{ SIZE(next) = POOLFREE;
72
SEGLINK(next) = vd->free;
74
next = (Block_t*)((Vmuchar_t*)next + size);
76
seg->free = NIL(Block_t*);
79
{ SIZE(next) = s - sizeof(Head_t);
85
if(!local && (vd->mode&VM_TRACE) && _Vmtrace && tp)
86
(*_Vmtrace)(vm,NIL(Vmuchar_t*),(Vmuchar_t*)tp,vd->pool,0);
93
static long pooladdr(Vmalloc_t* vm, reg Void_t* addr)
95
static long pooladdr(vm, addr)
100
reg Block_t *bp, *tp;
101
reg Vmuchar_t *laddr, *baddr;
105
reg Vmdata_t* vd = vm->data;
108
if(!(local = vd->mode&VM_TRUST))
109
{ GETLOCAL(vd,local);
116
for(seg = vd->seg; seg; seg = seg->next)
117
{ laddr = (Vmuchar_t*)SEGBLOCK(seg);
118
baddr = seg->baddr-sizeof(Head_t);
119
if((Vmuchar_t*)addr < laddr || (Vmuchar_t*)addr >= baddr)
122
/* the block that has this address */
123
size = ROUND(vd->pool,ALIGN);
124
tp = (Block_t*)(laddr + (((Vmuchar_t*)addr-laddr)/size)*size );
126
/* see if this block has been freed */
127
if(SIZE(tp) == POOLFREE) /* may be a coincidence - make sure */
128
for(bp = vd->free; bp; bp = SEGLINK(bp))
132
offset = (Vmuchar_t*)addr - (Vmuchar_t*)tp;
142
static int poolfree(reg Vmalloc_t* vm, reg Void_t* data )
144
static int poolfree(vm, data)
150
reg Vmdata_t* vd = vm->data;
156
if(!(local = vd->mode&VM_TRUST))
157
{ if(ISLOCK(vd,0) || vd->pool <= 0)
160
if(KPVADDR(vm,data,pooladdr) != 0)
161
{ if(vm->disc->exceptf)
162
(void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
171
SEGLINK(bp) = vd->free;
174
if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
175
(*_Vmtrace)(vm, (Vmuchar_t*)data, NIL(Vmuchar_t*), vd->pool, 0);
182
static Void_t* poolresize(Vmalloc_t* vm, Void_t* data, size_t size, int type )
184
static Void_t* poolresize(vm, data, size, type )
191
reg Vmdata_t* vd = vm->data;
196
{ if((data = poolalloc(vm,size)) && (type&VM_RSZERO) )
197
{ reg int *d = (int*)data, *ed = (int*)((char*)data+size);
198
do { *d++ = 0;} while(d < ed);
203
{ (void)poolfree(vm,data);
207
if(!(vd->mode&VM_TRUST) )
211
if(size != vd->pool || KPVADDR(vm,data,pooladdr) != 0)
212
{ if(vm->disc->exceptf)
213
(void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
217
if((vd->mode&VM_TRACE) && _Vmtrace)
218
(*_Vmtrace)(vm, (Vmuchar_t*)data, (Vmuchar_t*)data, size, 0);
225
static long poolsize(Vmalloc_t* vm, Void_t* addr)
227
static long poolsize(vm, addr)
232
return pooladdr(vm,addr) == 0 ? (long)vm->data->pool : -1L;
236
static int poolcompact(Vmalloc_t* vm)
238
static int poolcompact(vm)
243
reg Seg_t *seg, *next;
245
reg Vmdata_t* vd = vm->data;
247
if(!(vd->mode&VM_TRUST))
253
for(seg = vd->seg; seg; seg = next)
256
if(!(fp = seg->free))
259
seg->free = NIL(Block_t*);
260
if(seg->size == (s = SIZE(fp)&~BITS))
262
else s += sizeof(Head_t);
264
if((*_Vmtruncate)(vm,seg,s,1) < 0)
268
if((vd->mode&VM_TRACE) && _Vmtrace)
269
(*_Vmtrace)(vm, (Vmuchar_t*)0, (Vmuchar_t*)0, 0, 0);
276
static Void_t* poolalign(Vmalloc_t* vm, size_t size, size_t align)
278
static Void_t* poolalign(vm, size, align)
290
/* Public interface */
291
static Vmethod_t _Vmpool =
303
__DEFINE__(Vmethod_t*,Vmpool,&_Vmpool);