14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * David Korn <dgk@research.att.com> *
194887Schin * Phong Vo <kpv@research.att.com> *
204887Schin * *
214887Schin ***********************************************************************/
224887Schin #if defined(_UWIN) && defined(_BLD_ast)
234887Schin
_STUB_vmopen()244887Schin void _STUB_vmopen(){}
254887Schin
264887Schin #else
274887Schin
284887Schin #include "vmhdr.h"
294887Schin
304887Schin /* Opening a new region of allocation.
314887Schin ** Note that because of possible exotic memory types,
324887Schin ** all region data must be stored within the space given
334887Schin ** by the discipline.
344887Schin **
354887Schin ** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
364887Schin */
374887Schin
384887Schin typedef struct _vminit_
394887Schin {
404887Schin Vmdata_t vd; /* space for the region itself */
414887Schin Seg_t seg; /* space for segment */
424887Schin Block_t block; /* space for a block */
434887Schin Head_t head; /* space for the fake header */
444887Schin char a[3*ALIGN]; /* extra to fuss with alignment */
454887Schin } Vminit_t;
464887Schin
474887Schin #if __STD_C
vmopen(Vmdisc_t * disc,Vmethod_t * meth,int mode)484887Schin Vmalloc_t* vmopen(Vmdisc_t* disc, Vmethod_t* meth, int mode)
494887Schin #else
504887Schin Vmalloc_t* vmopen(disc, meth, mode)
514887Schin Vmdisc_t* disc; /* discipline to get segments */
524887Schin Vmethod_t* meth; /* method to manage space */
534887Schin int mode; /* type of region */
544887Schin #endif
554887Schin {
564887Schin reg Vmalloc_t* vm;
574887Schin reg Vmdata_t* vd;
584887Schin reg size_t s, a, incr;
594887Schin reg Block_t* b;
604887Schin reg Seg_t* seg;
614887Schin Vmuchar_t* addr;
624887Schin reg Vmemory_f memoryf;
634887Schin reg int e;
644887Schin
654887Schin if(!meth || !disc || !(memoryf = disc->memoryf) )
664887Schin return NIL(Vmalloc_t*);
674887Schin
684887Schin GETPAGESIZE(_Vmpagesize);
694887Schin
704887Schin /* note that Vmalloc_t space must be local to process since that's
714887Schin where the meth&disc function addresses are going to be stored */
724887Schin if(!(vm = (Vmalloc_t*)vmalloc(Vmheap,sizeof(Vmalloc_t))) )
734887Schin return NIL(Vmalloc_t*);
744887Schin vm->meth = *meth;
754887Schin vm->disc = disc;
764887Schin vm->file = NIL(char*);
774887Schin vm->line = 0;
784887Schin
794887Schin if(disc->exceptf)
804887Schin { addr = NIL(Vmuchar_t*);
814887Schin if((e = (*disc->exceptf)(vm,VM_OPEN,(Void_t*)(&addr),disc)) != 0)
824887Schin { if(e < 0 || !addr)
834887Schin goto open_error;
844887Schin
854887Schin /* align this address */
864887Schin if((a = (size_t)(VLONG(addr)%ALIGN)) != 0)
874887Schin addr += ALIGN-a;
884887Schin
894887Schin /* see if it's a valid region */
904887Schin vd = (Vmdata_t*)addr;
914887Schin if((vd->mode&meth->meth) != 0)
924887Schin { vm->data = vd;
93*12068SRoger.Faulkner@Oracle.COM goto done;
944887Schin }
954887Schin else
964887Schin { open_error:
974887Schin vmfree(Vmheap,vm);
984887Schin return NIL(Vmalloc_t*);
994887Schin }
1004887Schin }
1014887Schin }
1024887Schin
1034887Schin /* make sure vd->incr is properly rounded */
1044887Schin incr = disc->round <= 0 ? _Vmpagesize : disc->round;
1054887Schin incr = MULTIPLE(incr,ALIGN);
1064887Schin
1074887Schin /* get space for region data */
1084887Schin s = ROUND(sizeof(Vminit_t),incr);
1094887Schin if(!(addr = (Vmuchar_t*)(*memoryf)(vm,NIL(Void_t*),0,s,disc)) )
1104887Schin { vmfree(Vmheap,vm);
1114887Schin return NIL(Vmalloc_t*);
1124887Schin }
1134887Schin
1144887Schin /* make sure that addr is aligned */
1154887Schin if((a = (size_t)(VLONG(addr)%ALIGN)) != 0)
1164887Schin addr += ALIGN-a;
1174887Schin
1184887Schin /* initialize region */
1194887Schin vd = (Vmdata_t*)addr;
1204887Schin vd->mode = (mode&VM_FLAGS) | meth->meth;
1214887Schin vd->incr = incr;
1224887Schin vd->pool = 0;
1234887Schin vd->free = vd->wild = NIL(Block_t*);
1244887Schin
1254887Schin if(vd->mode&(VM_TRACE|VM_MTDEBUG))
1264887Schin vd->mode &= ~VM_TRUST;
1274887Schin
1284887Schin if(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE))
1294887Schin { vd->root = NIL(Block_t*);
1304887Schin for(e = S_TINY-1; e >= 0; --e)
1314887Schin TINY(vd)[e] = NIL(Block_t*);
1324887Schin for(e = S_CACHE; e >= 0; --e)
1334887Schin CACHE(vd)[e] = NIL(Block_t*);
1344887Schin incr = sizeof(Vmdata_t);
1354887Schin }
1364887Schin else incr = OFFSET(Vmdata_t,root);
1374887Schin
1384887Schin vd->seg = (Seg_t*)(addr + ROUND(incr,ALIGN));
1394887Schin /**/ ASSERT(VLONG(vd->seg)%ALIGN == 0);
1404887Schin
1414887Schin seg = vd->seg;
1424887Schin seg->next = NIL(Seg_t*);
143*12068SRoger.Faulkner@Oracle.COM seg->vmdt = vd;
1444887Schin seg->addr = (Void_t*)(addr - (a ? ALIGN-a : 0));
1454887Schin seg->extent = s;
1464887Schin seg->baddr = addr + s - (a ? ALIGN : 0);
1474887Schin seg->size = s; /* this size is larger than usual so that the segment
1484887Schin will not be freed until the region is closed. */
1494887Schin seg->free = NIL(Block_t*);
1504887Schin
1514887Schin /* make a data block out of the remainder */
1524887Schin b = SEGBLOCK(seg);
1534887Schin SEG(b) = seg;
1544887Schin SIZE(b) = seg->baddr - (Vmuchar_t*)b - 2*sizeof(Head_t);
1554887Schin *SELF(b) = b;
1564887Schin /**/ ASSERT(SIZE(b)%ALIGN == 0);
1574887Schin /**/ ASSERT(VLONG(b)%ALIGN == 0);
1584887Schin
1594887Schin /* make a fake header for next block in case of noncontiguous segments */
1604887Schin SEG(NEXT(b)) = seg;
1614887Schin SIZE(NEXT(b)) = BUSY|PFREE;
1624887Schin
1634887Schin if(vd->mode&(VM_MTLAST|VM_MTPOOL))
1644887Schin seg->free = b;
1654887Schin else vd->wild = b;
1664887Schin
1674887Schin vm->data = vd;
1684887Schin
169*12068SRoger.Faulkner@Oracle.COM done: /* add to the linked list of regions */
1704887Schin vm->next = Vmheap->next;
1714887Schin Vmheap->next = vm;
1724887Schin
1734887Schin return vm;
1744887Schin }
1754887Schin
1764887Schin #endif
177