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_vmopen(){}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "vmhdr.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Opening a new region of allocation.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Note that because of possible exotic memory types,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** all region data must be stored within the space given
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** by the discipline.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin**
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct _vminit_
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Vmdata_t vd; /* space for the region itself */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Seg_t seg; /* space for segment */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Block_t block; /* space for a block */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Head_t head; /* space for the fake header */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char a[3*ALIGN]; /* extra to fuss with alignment */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin} Vminit_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinVmalloc_t* vmopen(Vmdisc_t* disc, Vmethod_t* meth, int mode)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinVmalloc_t* vmopen(disc, meth, mode)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinVmdisc_t* disc; /* discipline to get segments */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinVmethod_t* meth; /* method to manage space */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint mode; /* type of region */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Vmalloc_t* vm;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Vmdata_t* vd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg size_t s, a, incr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Block_t* b;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Seg_t* seg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Vmuchar_t* addr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg Vmemory_f memoryf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg int e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!meth || !disc || !(memoryf = disc->memoryf) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return NIL(Vmalloc_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin GETPAGESIZE(_Vmpagesize);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* note that Vmalloc_t space must be local to process since that's
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin where the meth&disc function addresses are going to be stored */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(vm = (Vmalloc_t*)vmalloc(Vmheap,sizeof(Vmalloc_t))) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return NIL(Vmalloc_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vm->meth = *meth;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vm->disc = disc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vm->file = NIL(char*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vm->line = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(disc->exceptf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { addr = NIL(Vmuchar_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((e = (*disc->exceptf)(vm,VM_OPEN,(Void_t*)(&addr),disc)) != 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(e < 0 || !addr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto open_error;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* align this address */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((a = (size_t)(VLONG(addr)%ALIGN)) != 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin addr += ALIGN-a;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* see if it's a valid region */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vd = (Vmdata_t*)addr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((vd->mode&meth->meth) != 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { vm->data = vd;
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { open_error:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vmfree(Vmheap,vm);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return NIL(Vmalloc_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make sure vd->incr is properly rounded */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin incr = disc->round <= 0 ? _Vmpagesize : disc->round;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin incr = MULTIPLE(incr,ALIGN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* get space for region data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = ROUND(sizeof(Vminit_t),incr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(addr = (Vmuchar_t*)(*memoryf)(vm,NIL(Void_t*),0,s,disc)) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { vmfree(Vmheap,vm);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return NIL(Vmalloc_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make sure that addr is aligned */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((a = (size_t)(VLONG(addr)%ALIGN)) != 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin addr += ALIGN-a;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* initialize region */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vd = (Vmdata_t*)addr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vd->mode = (mode&VM_FLAGS) | meth->meth;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vd->incr = incr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vd->pool = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vd->free = vd->wild = NIL(Block_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(vd->mode&(VM_TRACE|VM_MTDEBUG))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vd->mode &= ~VM_TRUST;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { vd->root = NIL(Block_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(e = S_TINY-1; e >= 0; --e)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin TINY(vd)[e] = NIL(Block_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(e = S_CACHE; e >= 0; --e)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin CACHE(vd)[e] = NIL(Block_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin incr = sizeof(Vmdata_t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else incr = OFFSET(Vmdata_t,root);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vd->seg = (Seg_t*)(addr + ROUND(incr,ALIGN));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /**/ ASSERT(VLONG(vd->seg)%ALIGN == 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg = vd->seg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->next = NIL(Seg_t*);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner seg->vmdt = vd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->addr = (Void_t*)(addr - (a ? ALIGN-a : 0));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->extent = s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->baddr = addr + s - (a ? ALIGN : 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->size = s; /* this size is larger than usual so that the segment
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin will not be freed until the region is closed. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->free = NIL(Block_t*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make a data block out of the remainder */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin b = SEGBLOCK(seg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SEG(b) = seg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SIZE(b) = seg->baddr - (Vmuchar_t*)b - 2*sizeof(Head_t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *SELF(b) = b;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /**/ ASSERT(SIZE(b)%ALIGN == 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /**/ ASSERT(VLONG(b)%ALIGN == 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make a fake header for next block in case of noncontiguous segments */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SEG(NEXT(b)) = seg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SIZE(NEXT(b)) = BUSY|PFREE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(vd->mode&(VM_MTLAST|VM_MTPOOL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin seg->free = b;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else vd->wild = b;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vm->data = vd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknerdone: /* add to the linked list of regions */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin vm->next = Vmheap->next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Vmheap->next = vm;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return vm;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif