1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman *                                                                      *
3*b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2012 AT&T Intellectual Property          *
5*b30d1939SAndy Fiddaman *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*b30d1939SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*b30d1939SAndy Fiddaman *                                                                      *
9*b30d1939SAndy Fiddaman *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*b30d1939SAndy Fiddaman *                                                                      *
13*b30d1939SAndy Fiddaman *              Information and Software Systems Research               *
14*b30d1939SAndy Fiddaman *                            AT&T Research                             *
15*b30d1939SAndy Fiddaman *                           Florham Park NJ                            *
16*b30d1939SAndy Fiddaman *                                                                      *
17*b30d1939SAndy Fiddaman *                 Glenn Fowler <gsf@research.att.com>                  *
18*b30d1939SAndy Fiddaman *                  David Korn <dgk@research.att.com>                   *
19*b30d1939SAndy Fiddaman *                   Phong Vo <kpv@research.att.com>                    *
20*b30d1939SAndy Fiddaman *                                                                      *
21*b30d1939SAndy Fiddaman ***********************************************************************/
22*b30d1939SAndy Fiddaman #if defined(_UWIN) && defined(_BLD_ast)
23*b30d1939SAndy Fiddaman 
_STUB_vmopen()24*b30d1939SAndy Fiddaman void _STUB_vmopen(){}
25*b30d1939SAndy Fiddaman 
26*b30d1939SAndy Fiddaman #else
27*b30d1939SAndy Fiddaman 
28*b30d1939SAndy Fiddaman #include	"vmhdr.h"
29*b30d1939SAndy Fiddaman 
30*b30d1939SAndy Fiddaman /*	Opening a new region of allocation.
31*b30d1939SAndy Fiddaman **	Note that because of possible exotic memory types,
32*b30d1939SAndy Fiddaman **	all region data must be stored within the space given
33*b30d1939SAndy Fiddaman **	by the discipline.
34*b30d1939SAndy Fiddaman **
35*b30d1939SAndy Fiddaman **	Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
36*b30d1939SAndy Fiddaman */
37*b30d1939SAndy Fiddaman 
38*b30d1939SAndy Fiddaman /* this structure lives in the top data segment of the region */
39*b30d1939SAndy Fiddaman typedef struct _vminit_s
40*b30d1939SAndy Fiddaman {	union
41*b30d1939SAndy Fiddaman 	{ Vmdata_t	vd;		/* root of usable data space  	*/
42*b30d1939SAndy Fiddaman 	  Vmuchar_t	a[ROUND(sizeof(Vmdata_t),ALIGN)];
43*b30d1939SAndy Fiddaman 	} vd;
44*b30d1939SAndy Fiddaman 	union
45*b30d1939SAndy Fiddaman 	{ Vmalloc_t	vm;		/* embedded region if needed	*/
46*b30d1939SAndy Fiddaman 	  Vmuchar_t	a[ROUND(sizeof(Vmalloc_t),ALIGN)];
47*b30d1939SAndy Fiddaman 	} vm;
48*b30d1939SAndy Fiddaman 	union
49*b30d1939SAndy Fiddaman 	{ Seg_t		seg;		/* space for segment		*/
50*b30d1939SAndy Fiddaman 	  Vmuchar_t	a[ROUND(sizeof(Seg_t),ALIGN)];
51*b30d1939SAndy Fiddaman 	} seg;
52*b30d1939SAndy Fiddaman 	Block_t		block[16];	/* space for a few blocks	*/
53*b30d1939SAndy Fiddaman } Vminit_t;
54*b30d1939SAndy Fiddaman 
55*b30d1939SAndy Fiddaman #if __STD_C
vmopen(Vmdisc_t * disc,Vmethod_t * meth,int mode)56*b30d1939SAndy Fiddaman Vmalloc_t* vmopen(Vmdisc_t* disc, Vmethod_t* meth, int mode)
57*b30d1939SAndy Fiddaman #else
58*b30d1939SAndy Fiddaman Vmalloc_t* vmopen(disc, meth, mode)
59*b30d1939SAndy Fiddaman Vmdisc_t*	disc;	/* discipline to get segments	*/
60*b30d1939SAndy Fiddaman Vmethod_t*	meth;	/* method to manage space	*/
61*b30d1939SAndy Fiddaman int		mode;	/* type of region		*/
62*b30d1939SAndy Fiddaman #endif
63*b30d1939SAndy Fiddaman {
64*b30d1939SAndy Fiddaman 	Vmalloc_t	*vm, *vmp, vmproto;
65*b30d1939SAndy Fiddaman 	Vmdata_t	*vd;
66*b30d1939SAndy Fiddaman 	Vminit_t	*init;
67*b30d1939SAndy Fiddaman 	size_t		algn, size, incr;
68*b30d1939SAndy Fiddaman 	Block_t		*bp, *np;
69*b30d1939SAndy Fiddaman 	Seg_t		*seg;
70*b30d1939SAndy Fiddaman 	Vmuchar_t	*addr;
71*b30d1939SAndy Fiddaman 	int		rv;
72*b30d1939SAndy Fiddaman 
73*b30d1939SAndy Fiddaman 	if(!meth || !disc || !disc->memoryf )
74*b30d1939SAndy Fiddaman 		return NIL(Vmalloc_t*);
75*b30d1939SAndy Fiddaman 
76*b30d1939SAndy Fiddaman 	GETPAGESIZE(_Vmpagesize);
77*b30d1939SAndy Fiddaman 
78*b30d1939SAndy Fiddaman 	vmp = &vmproto; /* avoid memory allocation here! */
79*b30d1939SAndy Fiddaman 	memset(vmp, 0, sizeof(Vmalloc_t));
80*b30d1939SAndy Fiddaman 	memcpy(&vmp->meth, meth, sizeof(Vmethod_t));
81*b30d1939SAndy Fiddaman 	vmp->disc = disc;
82*b30d1939SAndy Fiddaman 
83*b30d1939SAndy Fiddaman 	mode &= VM_FLAGS; /* start with user-settable flags */
84*b30d1939SAndy Fiddaman 	size = 0;
85*b30d1939SAndy Fiddaman 
86*b30d1939SAndy Fiddaman 	if(disc->exceptf)
87*b30d1939SAndy Fiddaman 	{	addr = NIL(Vmuchar_t*);
88*b30d1939SAndy Fiddaman 		if((rv = (*disc->exceptf)(vmp,VM_OPEN,(Void_t*)(&addr),disc)) < 0)
89*b30d1939SAndy Fiddaman 			return NIL(Vmalloc_t*);
90*b30d1939SAndy Fiddaman 		else if(rv == 0 )
91*b30d1939SAndy Fiddaman 		{	if(addr) /* vm itself is in memory from disc->memoryf */
92*b30d1939SAndy Fiddaman 				mode |= VM_MEMORYF;
93*b30d1939SAndy Fiddaman 		}
94*b30d1939SAndy Fiddaman 		else if(rv > 0) /* the data section is being restored */
95*b30d1939SAndy Fiddaman 		{	if(!(init = (Vminit_t*)addr) )
96*b30d1939SAndy Fiddaman 				return NIL(Vmalloc_t*);
97*b30d1939SAndy Fiddaman 			size = -1; /* to tell that addr was not from disc->memoryf */
98*b30d1939SAndy Fiddaman 			vd = &init->vd.vd; /**/ASSERT(VLONG(vd)%ALIGN == 0);
99*b30d1939SAndy Fiddaman 			goto done;
100*b30d1939SAndy Fiddaman 		}
101*b30d1939SAndy Fiddaman 	}
102*b30d1939SAndy Fiddaman 
103*b30d1939SAndy Fiddaman 	/* make sure vd->incr is properly rounded and get initial memory */
104*b30d1939SAndy Fiddaman 	incr = disc->round <= 0 ? _Vmpagesize : disc->round;
105*b30d1939SAndy Fiddaman 	incr = MULTIPLE(incr,ALIGN);
106*b30d1939SAndy Fiddaman 	size = ROUND(sizeof(Vminit_t),incr); /* get initial memory */
107*b30d1939SAndy Fiddaman 	if(!(addr = (Vmuchar_t*)(*disc->memoryf)(vmp, NIL(Void_t*), 0, size, disc)) )
108*b30d1939SAndy Fiddaman 		return NIL(Vmalloc_t*);
109*b30d1939SAndy Fiddaman 	memset(addr, 0, size);
110*b30d1939SAndy Fiddaman 
111*b30d1939SAndy Fiddaman 	/* initialize region data */
112*b30d1939SAndy Fiddaman 	algn = (size_t)(VLONG(addr)%ALIGN);
113*b30d1939SAndy Fiddaman 	init = (Vminit_t*)(addr + (algn ? ALIGN-algn : 0)); /**/ASSERT(VLONG(init)%ALIGN == 0);
114*b30d1939SAndy Fiddaman 	vd = &init->vd.vd; /**/ASSERT(VLONG(vd)%ALIGN == 0);
115*b30d1939SAndy Fiddaman 	vd->mode = mode | meth->meth;
116*b30d1939SAndy Fiddaman 	vd->incr = incr;
117*b30d1939SAndy Fiddaman 	vd->pool = 0;
118*b30d1939SAndy Fiddaman 	vd->free = vd->wild = NIL(Block_t*);
119*b30d1939SAndy Fiddaman 
120*b30d1939SAndy Fiddaman 	if(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE))
121*b30d1939SAndy Fiddaman 	{	int	k;
122*b30d1939SAndy Fiddaman 		vd->root = NIL(Block_t*);
123*b30d1939SAndy Fiddaman 		for(k = S_TINY-1; k >= 0; --k)
124*b30d1939SAndy Fiddaman 			TINY(vd)[k] = NIL(Block_t*);
125*b30d1939SAndy Fiddaman 		for(k = S_CACHE; k >= 0; --k)
126*b30d1939SAndy Fiddaman 			CACHE(vd)[k] = NIL(Block_t*);
127*b30d1939SAndy Fiddaman 	}
128*b30d1939SAndy Fiddaman 
129*b30d1939SAndy Fiddaman 	vd->seg = &init->seg.seg; /**/ ASSERT(VLONG(vd->seg)%ALIGN == 0);
130*b30d1939SAndy Fiddaman 	seg = vd->seg;
131*b30d1939SAndy Fiddaman 	seg->next = NIL(Seg_t*);
132*b30d1939SAndy Fiddaman 	seg->vmdt = vd;
133*b30d1939SAndy Fiddaman 	seg->addr = (Void_t*)addr;
134*b30d1939SAndy Fiddaman 	seg->extent = size;
135*b30d1939SAndy Fiddaman 	seg->baddr = addr + size;
136*b30d1939SAndy Fiddaman 	seg->size = size; /* Note: this size is unusually large to mark seg as
137*b30d1939SAndy Fiddaman 			   the root segment and can be freed only at closing */
138*b30d1939SAndy Fiddaman 	seg->free = NIL(Block_t*);
139*b30d1939SAndy Fiddaman 
140*b30d1939SAndy Fiddaman 	/* make a data block out of the remainder */
141*b30d1939SAndy Fiddaman 	bp = SEGBLOCK(seg);
142*b30d1939SAndy Fiddaman 	SEG(bp) = seg;
143*b30d1939SAndy Fiddaman 	size = ((seg->baddr - (Vmuchar_t*)bp)/ALIGN) * ALIGN; /**/ ASSERT(size > 0);
144*b30d1939SAndy Fiddaman 	SIZE(bp) = size - 2*sizeof(Head_t); /**/ASSERT(SIZE(bp) > 0 && (SIZE(bp)%ALIGN) == 0);
145*b30d1939SAndy Fiddaman 	SELF(bp) = bp;
146*b30d1939SAndy Fiddaman 	/**/ ASSERT(SIZE(bp)%ALIGN == 0);
147*b30d1939SAndy Fiddaman 	/**/ ASSERT(VLONG(bp)%ALIGN == 0);
148*b30d1939SAndy Fiddaman 
149*b30d1939SAndy Fiddaman 	/* make a fake header for next block in case of noncontiguous segments */
150*b30d1939SAndy Fiddaman 	np = NEXT(bp);
151*b30d1939SAndy Fiddaman 	SEG(np) = seg;
152*b30d1939SAndy Fiddaman 	SIZE(np) = BUSY|PFREE;
153*b30d1939SAndy Fiddaman 
154*b30d1939SAndy Fiddaman 	if(vd->mode&(VM_MTLAST|VM_MTPOOL))
155*b30d1939SAndy Fiddaman 		seg->free = bp;
156*b30d1939SAndy Fiddaman 	else	vd->wild = bp;
157*b30d1939SAndy Fiddaman 
158*b30d1939SAndy Fiddaman done:	/* now make the region handle */
159*b30d1939SAndy Fiddaman 	if(vd->mode&VM_MEMORYF)
160*b30d1939SAndy Fiddaman 		vm = &init->vm.vm;
161*b30d1939SAndy Fiddaman 	else if(!(vm = vmalloc(Vmheap, sizeof(Vmalloc_t))) )
162*b30d1939SAndy Fiddaman 	{	if(size > 0)
163*b30d1939SAndy Fiddaman 			(void)(*disc->memoryf)(vmp, addr, size, 0, disc);
164*b30d1939SAndy Fiddaman 		return NIL(Vmalloc_t*);
165*b30d1939SAndy Fiddaman 	}
166*b30d1939SAndy Fiddaman 	memcpy(vm, vmp, sizeof(Vmalloc_t));
167*b30d1939SAndy Fiddaman 	vm->data = vd;
168*b30d1939SAndy Fiddaman 
169*b30d1939SAndy Fiddaman 	if(disc->exceptf) /* signaling that vmopen succeeded */
170*b30d1939SAndy Fiddaman 		(void)(*disc->exceptf)(vm, VM_ENDOPEN, NIL(Void_t*), disc);
171*b30d1939SAndy Fiddaman 
172*b30d1939SAndy Fiddaman 	/* add to the linked list of regions */
173*b30d1939SAndy Fiddaman 	_vmlock(NIL(Vmalloc_t*), 1);
174*b30d1939SAndy Fiddaman 	vm->next = Vmheap->next; Vmheap->next = vm;
175*b30d1939SAndy Fiddaman 	_vmlock(NIL(Vmalloc_t*), 0);
176*b30d1939SAndy Fiddaman 
177*b30d1939SAndy Fiddaman 	return vm;
178*b30d1939SAndy Fiddaman }
179*b30d1939SAndy Fiddaman 
180*b30d1939SAndy Fiddaman #endif
181