3
/* Allocation with freeing and reallocing of last allocated block only.
5
** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
9
static Void_t* lastalloc(Vmalloc_t* vm, size_t size)
11
static Void_t* lastalloc(vm, size)
16
reg Block_t *tp, *next;
17
reg Seg_t *seg, *last;
19
reg Vmdata_t* vd = vm->data;
23
if(!(local = vd->mode&VM_TRUST))
31
size = size < ALIGN ? ALIGN : ROUND(size,ALIGN);
33
{ for(last = NIL(Seg_t*), seg = vd->seg; seg; last = seg, seg = seg->next)
34
{ if(!(tp = seg->free) || (SIZE(tp)+sizeof(Head_t)) < size)
37
{ last->next = seg->next;
44
/* there is no usable free space in region, try extending */
45
if((tp = (*_Vmextend)(vm,size,NIL(Vmsearch_f))) )
49
else if(vd->mode&VM_AGAIN)
50
vd->mode &= ~VM_AGAIN;
55
if((s = SIZE(tp)) >= size)
56
{ next = (Block_t*)((Vmuchar_t*)tp+size);
57
SIZE(next) = s - size;
61
else seg->free = NIL(Block_t*);
63
vd->free = seg->last = tp;
65
if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
66
(*_Vmtrace)(vm, NIL(Vmuchar_t*), (Vmuchar_t*)tp, orgsize, 0);
74
static int lastfree(Vmalloc_t* vm, reg Void_t* data )
76
static int lastfree(vm, data)
84
reg Vmdata_t* vd = vm->data;
89
if(!(local = vd->mode&VM_TRUST) )
94
if(data != (Void_t*)vd->free)
95
{ if(!local && vm->disc->exceptf)
96
(void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
102
if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
104
s = (Vmuchar_t*)(seg->free) - (Vmuchar_t*)data;
105
else s = (Vmuchar_t*)BLOCK(seg->baddr) - (Vmuchar_t*)data;
106
(*_Vmtrace)(vm, (Vmuchar_t*)data, NIL(Vmuchar_t*), s, 0);
109
vd->free = NIL(Block_t*);
112
SIZE(fp) = ((Vmuchar_t*)BLOCK(seg->baddr) - (Vmuchar_t*)data) - sizeof(Head_t);
114
seg->last = NIL(Block_t*);
121
static Void_t* lastresize(Vmalloc_t* vm, reg Void_t* data, size_t size, int type )
123
static Void_t* lastresize(vm, data, size, type )
135
reg Vmdata_t* vd = vm->data;
143
data = lastalloc(vm,size);
147
{ (void)lastfree(vm,data);
151
if(!(local = vd->mode&VM_TRUST))
159
if(data == (Void_t*)vd->free)
162
{ /* see if it was one of ours */
163
for(seg = vd->seg; seg; seg = seg->next)
164
if(data >= seg->addr && data < (Void_t*)seg->baddr)
166
if(!seg || (VLONG(data)%ALIGN) != 0 ||
167
(seg->last && (Vmuchar_t*)data > (Vmuchar_t*)seg->last) )
173
/* set 's' to be the current available space */
174
if(data != seg->last)
175
{ if(seg->last && (Vmuchar_t*)data < (Vmuchar_t*)seg->last)
176
oldsize = (Vmuchar_t*)seg->last - (Vmuchar_t*)data;
177
else oldsize = (Vmuchar_t*)BLOCK(seg->baddr) - (Vmuchar_t*)data;
181
{ s = (Vmuchar_t*)BLOCK(seg->baddr) - (Vmuchar_t*)data;
182
if(!(tp = seg->free) )
185
{ oldsize = (Vmuchar_t*)tp - (Vmuchar_t*)data;
186
seg->free = NIL(Block_t*);
190
size = size < ALIGN ? ALIGN : ROUND(size,ALIGN);
191
if(s < 0 || (ssize_t)size > s)
192
{ if(s >= 0) /* amount to extend */
193
{ ds = size-s; ds = ROUND(ds,vd->incr);
194
addr = (*vm->disc->memoryf)(vm, seg->addr, seg->extent,
195
seg->extent+ds, vm->disc);
196
if(addr == seg->addr)
201
SIZE(BLOCK(seg->baddr)) = BUSY;
207
if(!(type&(VM_RSMOVE|VM_RSCOPY)) )
211
if(!(addr = KPVALLOC(vm,size,lastalloc)) )
219
ds = oldsize < size ? oldsize : size;
223
if(s >= 0 && seg != vd->seg)
224
{ tp = (Block_t*)data;
226
SIZE(tp) = s - sizeof(Head_t);
230
/* new block and size */
233
s = (Vmuchar_t*)BLOCK(seg->baddr) -
235
seg->free = NIL(Block_t*);
242
{ if(s >= (ssize_t)(size+sizeof(Head_t)) )
243
{ tp = (Block_t*)((Vmuchar_t*)data + size);
245
SIZE(tp) = (s - size) - sizeof(Head_t);
249
vd->free = seg->last = (Block_t*)data;
251
if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
252
(*_Vmtrace)(vm,(Vmuchar_t*)orgdata,(Vmuchar_t*)data,orgsize,0);
257
done: if(data && (type&VM_RSZERO) && size > oldsize)
258
{ d = (int*)((char*)data + oldsize);
268
static long lastaddr(Vmalloc_t* vm, Void_t* addr)
270
static long lastaddr(vm, addr)
275
reg Vmdata_t* vd = vm->data;
277
if(!(vd->mode&VM_TRUST) && ISLOCK(vd,0))
279
if(!vd->free || addr < (Void_t*)vd->free || addr >= (Void_t*)vd->seg->baddr)
281
else return (Vmuchar_t*)addr - (Vmuchar_t*)vd->free;
285
static long lastsize(Vmalloc_t* vm, Void_t* addr)
287
static long lastsize(vm, addr)
292
reg Vmdata_t* vd = vm->data;
294
if(!(vd->mode&VM_TRUST) && ISLOCK(vd,0))
296
if(!vd->free || addr != (Void_t*)vd->free )
298
else if(vd->seg->free)
299
return (Vmuchar_t*)vd->seg->free - (Vmuchar_t*)addr;
300
else return (Vmuchar_t*)vd->seg->baddr - (Vmuchar_t*)addr - sizeof(Head_t);
304
static int lastcompact(Vmalloc_t* vm)
306
static int lastcompact(vm)
311
reg Seg_t *seg, *next;
313
reg Vmdata_t* vd = vm->data;
315
if(!(vd->mode&VM_TRUST))
321
for(seg = vd->seg; seg; seg = next)
324
if(!(fp = seg->free))
327
seg->free = NIL(Block_t*);
328
if(seg->size == (s = SIZE(fp)&~BITS))
330
else s += sizeof(Head_t);
332
if((*_Vmtruncate)(vm,seg,s,1) < 0)
336
if((vd->mode&VM_TRACE) && _Vmtrace)
337
(*_Vmtrace)(vm,(Vmuchar_t*)0,(Vmuchar_t*)0,0,0);
344
static Void_t* lastalign(Vmalloc_t* vm, size_t size, size_t align)
346
static Void_t* lastalign(vm, size, align)
353
reg size_t s, orgsize, orgalign;
357
reg Vmdata_t* vd = vm->data;
359
if(size <= 0 || align <= 0)
362
if(!(local = vd->mode&VM_TRUST) )
363
{ GETLOCAL(vd,local);
364
if(ISLOCK(vd,local) )
371
size = size <= TINYSIZE ? TINYSIZE : ROUND(size,ALIGN);
372
align = MULTIPLE(align,ALIGN);
375
if(!(data = (Vmuchar_t*)KPVALLOC(vm,s,lastalloc)) )
378
/* find the segment containing this block */
379
for(seg = vd->seg; seg; seg = seg->next)
380
if(seg->last == (Block_t*)data)
384
/* get a suitably aligned address */
385
if((s = (size_t)(VLONG(data)%align)) != 0)
386
data += align-s; /**/ASSERT((VLONG(data)%align) == 0);
388
/* free the unused tail */
389
next = (Block_t*)(data+size);
390
if((s = (seg->baddr - (Vmuchar_t*)next)) >= sizeof(Block_t))
392
SIZE(next) = s - sizeof(Head_t);
396
vd->free = seg->last = (Block_t*)data;
398
if(!local && !(vd->mode&VM_TRUST) && _Vmtrace && (vd->mode&VM_TRACE) )
399
(*_Vmtrace)(vm,NIL(Vmuchar_t*),data,orgsize,orgalign);
404
return (Void_t*)data;
407
/* Public method for free-1 allocation */
408
static Vmethod_t _Vmlast =
420
__DEFINE__(Vmethod_t*,Vmlast,&_Vmlast);