diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
commit | 3950ffe2a485479f6561c27364d3d7df5a21d124 (patch) | |
tree | 468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib/libast/vmalloc/vmopen.c | |
download | ksh-upstream.tar.gz |
Imported Upstream version 93u+upstream
Diffstat (limited to 'src/lib/libast/vmalloc/vmopen.c')
-rw-r--r-- | src/lib/libast/vmalloc/vmopen.c | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/src/lib/libast/vmalloc/vmopen.c b/src/lib/libast/vmalloc/vmopen.c new file mode 100644 index 0000000..5f6912f --- /dev/null +++ b/src/lib/libast/vmalloc/vmopen.c @@ -0,0 +1,180 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2012 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#if defined(_UWIN) && defined(_BLD_ast) + +void _STUB_vmopen(){} + +#else + +#include "vmhdr.h" + +/* Opening a new region of allocation. +** Note that because of possible exotic memory types, +** all region data must be stored within the space given +** by the discipline. +** +** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94. +*/ + +/* this structure lives in the top data segment of the region */ +typedef struct _vminit_s +{ union + { Vmdata_t vd; /* root of usable data space */ + Vmuchar_t a[ROUND(sizeof(Vmdata_t),ALIGN)]; + } vd; + union + { Vmalloc_t vm; /* embedded region if needed */ + Vmuchar_t a[ROUND(sizeof(Vmalloc_t),ALIGN)]; + } vm; + union + { Seg_t seg; /* space for segment */ + Vmuchar_t a[ROUND(sizeof(Seg_t),ALIGN)]; + } seg; + Block_t block[16]; /* space for a few blocks */ +} Vminit_t; + +#if __STD_C +Vmalloc_t* vmopen(Vmdisc_t* disc, Vmethod_t* meth, int mode) +#else +Vmalloc_t* vmopen(disc, meth, mode) +Vmdisc_t* disc; /* discipline to get segments */ +Vmethod_t* meth; /* method to manage space */ +int mode; /* type of region */ +#endif +{ + Vmalloc_t *vm, *vmp, vmproto; + Vmdata_t *vd; + Vminit_t *init; + size_t algn, size, incr; + Block_t *bp, *np; + Seg_t *seg; + Vmuchar_t *addr; + int rv; + + if(!meth || !disc || !disc->memoryf ) + return NIL(Vmalloc_t*); + + GETPAGESIZE(_Vmpagesize); + + vmp = &vmproto; /* avoid memory allocation here! */ + memset(vmp, 0, sizeof(Vmalloc_t)); + memcpy(&vmp->meth, meth, sizeof(Vmethod_t)); + vmp->disc = disc; + + mode &= VM_FLAGS; /* start with user-settable flags */ + size = 0; + + if(disc->exceptf) + { addr = NIL(Vmuchar_t*); + if((rv = (*disc->exceptf)(vmp,VM_OPEN,(Void_t*)(&addr),disc)) < 0) + return NIL(Vmalloc_t*); + else if(rv == 0 ) + { if(addr) /* vm itself is in memory from disc->memoryf */ + mode |= VM_MEMORYF; + } + else if(rv > 0) /* the data section is being restored */ + { if(!(init = (Vminit_t*)addr) ) + return NIL(Vmalloc_t*); + size = -1; /* to tell that addr was not from disc->memoryf */ + vd = &init->vd.vd; /**/ASSERT(VLONG(vd)%ALIGN == 0); + goto done; + } + } + + /* make sure vd->incr is properly rounded and get initial memory */ + incr = disc->round <= 0 ? _Vmpagesize : disc->round; + incr = MULTIPLE(incr,ALIGN); + size = ROUND(sizeof(Vminit_t),incr); /* get initial memory */ + if(!(addr = (Vmuchar_t*)(*disc->memoryf)(vmp, NIL(Void_t*), 0, size, disc)) ) + return NIL(Vmalloc_t*); + memset(addr, 0, size); + + /* initialize region data */ + algn = (size_t)(VLONG(addr)%ALIGN); + init = (Vminit_t*)(addr + (algn ? ALIGN-algn : 0)); /**/ASSERT(VLONG(init)%ALIGN == 0); + vd = &init->vd.vd; /**/ASSERT(VLONG(vd)%ALIGN == 0); + vd->mode = mode | meth->meth; + vd->incr = incr; + vd->pool = 0; + vd->free = vd->wild = NIL(Block_t*); + + if(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE)) + { int k; + vd->root = NIL(Block_t*); + for(k = S_TINY-1; k >= 0; --k) + TINY(vd)[k] = NIL(Block_t*); + for(k = S_CACHE; k >= 0; --k) + CACHE(vd)[k] = NIL(Block_t*); + } + + vd->seg = &init->seg.seg; /**/ ASSERT(VLONG(vd->seg)%ALIGN == 0); + seg = vd->seg; + seg->next = NIL(Seg_t*); + seg->vmdt = vd; + seg->addr = (Void_t*)addr; + seg->extent = size; + seg->baddr = addr + size; + seg->size = size; /* Note: this size is unusually large to mark seg as + the root segment and can be freed only at closing */ + seg->free = NIL(Block_t*); + + /* make a data block out of the remainder */ + bp = SEGBLOCK(seg); + SEG(bp) = seg; + size = ((seg->baddr - (Vmuchar_t*)bp)/ALIGN) * ALIGN; /**/ ASSERT(size > 0); + SIZE(bp) = size - 2*sizeof(Head_t); /**/ASSERT(SIZE(bp) > 0 && (SIZE(bp)%ALIGN) == 0); + SELF(bp) = bp; + /**/ ASSERT(SIZE(bp)%ALIGN == 0); + /**/ ASSERT(VLONG(bp)%ALIGN == 0); + + /* make a fake header for next block in case of noncontiguous segments */ + np = NEXT(bp); + SEG(np) = seg; + SIZE(np) = BUSY|PFREE; + + if(vd->mode&(VM_MTLAST|VM_MTPOOL)) + seg->free = bp; + else vd->wild = bp; + +done: /* now make the region handle */ + if(vd->mode&VM_MEMORYF) + vm = &init->vm.vm; + else if(!(vm = vmalloc(Vmheap, sizeof(Vmalloc_t))) ) + { if(size > 0) + (void)(*disc->memoryf)(vmp, addr, size, 0, disc); + return NIL(Vmalloc_t*); + } + memcpy(vm, vmp, sizeof(Vmalloc_t)); + vm->data = vd; + + if(disc->exceptf) /* signaling that vmopen succeeded */ + (void)(*disc->exceptf)(vm, VM_ENDOPEN, NIL(Void_t*), disc); + + /* add to the linked list of regions */ + _vmlock(NIL(Vmalloc_t*), 1); + vm->next = Vmheap->next; Vmheap->next = vm; + _vmlock(NIL(Vmalloc_t*), 0); + + return vm; +} + +#endif |