3
static char* Version = "\n@(#)Vmalloc (AT&T Labs - kpv) 1999-08-05\0\n";
6
/* Private code used in the vmalloc library
8
** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
11
/* Get more memory for a region */
13
static Block_t* vmextend(reg Vmalloc_t* vm, size_t size, Vmsearch_f searchf )
15
static Block_t* vmextend(vm, size, searchf )
16
reg Vmalloc_t* vm; /* region to increase in size */
17
size_t size; /* desired amount of space */
18
Vmsearch_f searchf; /* tree search function */
25
reg Vmdata_t* vd = vm->data;
26
reg Vmemory_f memoryf = vm->disc->memoryf;
27
reg Vmexcept_f exceptf = vm->disc->exceptf;
29
GETPAGESIZE(_Vmpagesize);
31
if(vd->incr <= 0) /* this is just _Vmheap on the first call */
32
vd->incr = 4*_Vmpagesize;
34
/* Get slightly more for administrative data */
35
s = size + sizeof(Seg_t) + sizeof(Block_t) + sizeof(Head_t) + 2*ALIGN;
36
if(s <= size) /* size was too large and we have wrapped around */
38
if((size = ROUND(s,vd->incr)) < s)
41
/* see if we can extend the current segment */
43
addr = NIL(Vmuchar_t*);
45
{ if(!vd->wild || SEG(vd->wild) != seg)
48
{ s = SIZE(vd->wild) + sizeof(Head_t);
49
if((s = (s/vd->incr)*vd->incr) == size)
52
addr = (Vmuchar_t*)(*memoryf)(vm,seg->addr,seg->extent,
53
seg->extent+size-s,vm->disc);
57
{ /**/ASSERT(addr == (Vmuchar_t*)seg->addr);
63
while(!addr) /* try to get space */
64
{ if((addr = (Vmuchar_t*)(*memoryf)(vm,NIL(Void_t*),0,size,vm->disc)) )
67
/* check with exception handler to see if we should continue */
72
lock = vd->mode&VM_LOCK;
74
rv = (*exceptf)(vm,VM_NOMEM,(Void_t*)size,vm->disc);
85
{ /* extending current segment */
86
bp = BLOCK(seg->baddr); /**/ ASSERT((SIZE(bp)&~BITS) == 0);
87
/**/ ASSERT(SEG(bp) == seg);
89
if(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE) )
90
{ if(!ISPFREE(SIZE(bp)) )
91
SIZE(bp) = size - sizeof(Head_t);
93
{ /**/ ASSERT(searchf);
96
vd->wild = NIL(Block_t*);
97
else REMOVE(vd,bp,INDEX(SIZE(bp)),t,(*searchf));
104
seg->free = NIL(Block_t*);
107
else SIZE(bp) = size - sizeof(Head_t);
115
{ /* creating a new segment */
116
reg Seg_t *sp, *lastsp;
118
if((s = (size_t)(VLONG(addr)%ALIGN)) != 0)
123
seg->addr = (Void_t*)(addr - (s ? ALIGN-s : 0));
125
seg->baddr = addr + size - (s ? 2*ALIGN : 0);
126
seg->free = NIL(Block_t*);
129
SIZE(bp) = seg->baddr - (Vmuchar_t*)bp - 2*sizeof(Head_t);
131
/* NOTE: for Vmbest, Vmdebug and Vmprofile the region's segment list
132
is reversely ordered by addresses. This is so that we can easily
133
check for the wild block.
135
lastsp = NIL(Seg_t*);
137
if(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE))
138
for(; sp; lastsp = sp, sp = sp->next)
139
if(seg->addr > sp->addr)
146
seg->size = SIZE(bp);
149
/* make a fake header for possible segmented memory */
154
/* see if the wild block is still wild */
155
if((t = vd->wild) && (seg = SEG(t)) != vd->seg)
156
{ CLRPFREE(SIZE(NEXT(t)));
157
if(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE) )
158
{ SIZE(t) |= BUSY|JUNK;
159
LINK(t) = CACHE(vd)[C_INDEX(SIZE(t))];
160
CACHE(vd)[C_INDEX(SIZE(t))] = t;
164
vd->wild = NIL(Block_t*);
170
/* Truncate a segment if possible */
172
static int vmtruncate(Vmalloc_t* vm, Seg_t* seg, size_t size, int exact)
174
static int vmtruncate(vm, seg, size, exact)
175
Vmalloc_t* vm; /* containing region */
176
Seg_t* seg; /* the one to be truncated */
177
size_t size; /* amount of free space */
178
int exact; /* amount given was exact */
183
reg Vmdata_t* vd = vm->data;
184
reg Vmemory_f memoryf = vm->disc->memoryf;
191
/* the truncated amount must satisfy the discipline requirement */
192
if((less = vm->disc->round) <= 0)
194
less = (size/less)*less;
195
less = (less/ALIGN)*ALIGN;
197
if(!exact) /* only truncate multiples of incr */
198
less = (less/vd->incr)*vd->incr;
200
if(less > 0 && size > less && (size-less) < sizeof(Block_t) )
204
(*memoryf)(vm,caddr,seg->extent,seg->extent-less,vm->disc) != caddr)
210
SIZE(BLOCK(seg->baddr)) = BUSY;
214
/* unlink segment from region */
216
{ vd->seg = seg->next;
220
{ for(last = vd->seg; last->next != seg; last = last->next)
222
last->next = seg->next;
226
if((*memoryf)(vm,caddr,seg->extent,0,vm->disc) == caddr)
229
/* space reduction failed, reinsert segment */
231
{ seg->next = last->next;
235
{ seg->next = vd->seg;
241
/* Externally visible names but local to library */
242
Vmextern_t _Vmextern =
243
{ vmextend, /* _Vmextend */
244
vmtruncate, /* _Vmtruncate */
246
NIL(char*(*)_ARG_((char*,char*,int))), /* _Vmstrcpy */
247
NIL(char*(*)_ARG_((Vmulong_t,int))), /* _Vmitoa */
248
NIL(void(*)_ARG_((Vmalloc_t*,
249
Vmuchar_t*,Vmuchar_t*,size_t,size_t))), /* _Vmtrace */
250
NIL(void(*)_ARG_((Vmalloc_t*))) /* _Vmpfclose */