da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1985-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(_UWIN) && defined(_BLD_ast)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinvoid _STUB_vmprivate(){}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "vmhdr.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerstatic char* Version = "\n@(#)$Id: Vmalloc (AT&T Research) 2010-01-01 $\0\n";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Private code used in the vmalloc library
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin**
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Get more memory for a region */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic Block_t* vmextend(reg Vmalloc_t* vm, size_t size, Vmsearch_f searchf )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic Block_t* vmextend(vm, size, searchf )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinreg Vmalloc_t* vm; /* region to increase in size */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinsize_t size; /* desired amount of space */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinVmsearch_f searchf; /* tree search function */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg size_t s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Seg_t* seg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Block_t *bp, *t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Vmuchar_t* addr = (Vmuchar_t*)Version; /* shut compiler warning */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Vmdata_t* vd = vm->data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Vmemory_f memoryf = vm->disc->memoryf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Vmexcept_f exceptf = vm->disc->exceptf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin GETPAGESIZE(_Vmpagesize);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if DEBUG /* trace all allocation calls through the heap */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!_Vmtrace && vm == Vmheap && (vd->mode&VM_TRUST) )
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner VMOPTIONS();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(vd->incr <= 0) /* this is just _Vmheap on the first call */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz vd->incr = VMHEAPINCR;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Get slightly more for administrative data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = size + sizeof(Seg_t) + sizeof(Block_t) + sizeof(Head_t) + 2*ALIGN;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(s <= size) /* size was too large and we have wrapped around */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return NIL(Block_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((size = ROUND(s,vd->incr)) < s)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return NIL(Block_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* increase the rounding factor to reduce # of future extensions */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(size > 2*vd->incr && vm->disc->round < vd->incr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vd->incr *= 2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* see if we can extend the current segment */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(seg = vd->seg) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin addr = NIL(Vmuchar_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(!vd->wild || SEG(vd->wild) != seg)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { s = SIZE(vd->wild) + sizeof(Head_t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((s = (s/vd->incr)*vd->incr) == size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size += vd->incr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin addr = (Vmuchar_t*)(*memoryf)(vm,seg->addr,seg->extent,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->extent+size-s,vm->disc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!addr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg = NIL(Seg_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /**/ASSERT(addr == (Vmuchar_t*)seg->addr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin addr += seg->extent;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin size -= s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(!addr) /* try to get space */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if((addr = (Vmuchar_t*)(*memoryf)(vm,NIL(Void_t*),0,size,vm->disc)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check with exception handler to see if we should continue */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!exceptf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return NIL(Block_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { int rv, lock;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin lock = vd->mode&VM_LOCK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vd->mode &= ~VM_LOCK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin rv = (*exceptf)(vm,VM_NOMEM,(Void_t*)size,vm->disc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vd->mode |= lock;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(rv <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(rv == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vd->mode |= VM_AGAIN;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return NIL(Block_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(seg)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* extending current segment */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner bp = BLOCK(seg->baddr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE) )
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner { /**/ ASSERT((SIZE(bp)&~BITS) == 0);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner /**/ ASSERT(SEG(bp) == seg);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if(!ISPFREE(SIZE(bp)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SIZE(bp) = size - sizeof(Head_t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /**/ ASSERT(searchf);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bp = LAST(bp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(bp == vd->wild)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vd->wild = NIL(Block_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else REMOVE(vd,bp,INDEX(SIZE(bp)),t,(*searchf));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SIZE(bp) += size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(seg->free)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { bp = seg->free;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->free = NIL(Block_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SIZE(bp) += size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner else
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner { SEG(bp) = seg;
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner SIZE(bp) = size - sizeof(Head_t);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->size += size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->extent += size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->baddr += size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* creating a new segment */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Seg_t *sp, *lastsp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((s = (size_t)(VLONG(addr)%ALIGN)) != 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin addr += ALIGN-s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg = (Seg_t*)addr;
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner seg->vmdt = vd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->addr = (Void_t*)(addr - (s ? ALIGN-s : 0));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->extent = size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->baddr = addr + size - (s ? 2*ALIGN : 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->free = NIL(Block_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bp = SEGBLOCK(seg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SEG(bp) = seg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SIZE(bp) = seg->baddr - (Vmuchar_t*)bp - 2*sizeof(Head_t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* NOTE: for Vmbest, Vmdebug and Vmprofile the region's segment list
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin is reversely ordered by addresses. This is so that we can easily
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin check for the wild block.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin lastsp = NIL(Seg_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp = vd->seg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(; sp; lastsp = sp, sp = sp->next)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(seg->addr > sp->addr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->next = sp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(lastsp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin lastsp->next = seg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else vd->seg = seg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->size = SIZE(bp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make a fake header for possible segmented memory */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t = NEXT(bp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SEG(t) = seg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SIZE(t) = BUSY;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* see if the wild block is still wild */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((t = vd->wild) && (seg = SEG(t)) != vd->seg)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { CLRPFREE(SIZE(NEXT(t)));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { SIZE(t) |= BUSY|JUNK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin LINK(t) = CACHE(vd)[C_INDEX(SIZE(t))];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin CACHE(vd)[C_INDEX(SIZE(t))] = t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else seg->free = t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vd->wild = NIL(Block_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return bp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Truncate a segment if possible */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic ssize_t vmtruncate(Vmalloc_t* vm, Seg_t* seg, size_t size, int exact)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic ssize_t vmtruncate(vm, seg, size, exact)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinVmalloc_t* vm; /* containing region */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinSeg_t* seg; /* the one to be truncated */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinsize_t size; /* amount of free space */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint exact;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Void_t* caddr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Seg_t* last;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Vmdata_t* vd = vm->data;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Vmemory_f memoryf = vm->disc->memoryf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin caddr = seg->addr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(size < seg->size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { reg ssize_t less;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(exact)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin less = size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else /* keep truncated amount to discipline requirements */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if((less = vm->disc->round) <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin less = _Vmpagesize;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin less = (size/less)*less;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin less = (less/vd->incr)*vd->incr;
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if(less > 0 && size > (size_t)less && (size-(size_t)less) < sizeof(Block_t) )
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner less = (size_t)less <= vd->incr ? 0 : (size_t)less - vd->incr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(less <= 0 ||
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (*memoryf)(vm,caddr,seg->extent,seg->extent-less,vm->disc) != caddr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->extent -= less;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->size -= less;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->baddr -= less;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SEG(BLOCK(seg->baddr)) = seg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SIZE(BLOCK(seg->baddr)) = BUSY;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return less;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* unlink segment from region */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(seg == vd->seg)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { vd->seg = seg->next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin last = NIL(Seg_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { for(last = vd->seg; last->next != seg; last = last->next)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin last->next = seg->next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* now delete it */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((*memoryf)(vm,caddr,seg->extent,0,vm->disc) == caddr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* space reduction failed, reinsert segment */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(last)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { seg->next = last->next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin last->next = seg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { seg->next = vd->seg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vd->seg = seg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Externally visible names but local to library */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinVmextern_t _Vmextern =
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{ vmextend, /* _Vmextend */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vmtruncate, /* _Vmtruncate */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 0, /* _Vmpagesize */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin NIL(char*(*)_ARG_((char*,const char*,int))), /* _Vmstrcpy */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin NIL(char*(*)_ARG_((Vmulong_t,int))), /* _Vmitoa */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin NIL(void(*)_ARG_((Vmalloc_t*,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Vmuchar_t*,Vmuchar_t*,size_t,size_t))), /* _Vmtrace */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin NIL(void(*)_ARG_((Vmalloc_t*))) /* _Vmpfclose */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif