xref: /titanic_51/usr/src/lib/libast/common/vmalloc/vmopen.c (revision 3e14f97f673e8a630f076077de35afdd43dc1587)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*3e14f97fSRoger A. Faulkner *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6da2e3ebdSchin *                  Common Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10da2e3ebdSchin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11da2e3ebdSchin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
19da2e3ebdSchin *                   Phong Vo <kpv@research.att.com>                    *
20da2e3ebdSchin *                                                                      *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #if defined(_UWIN) && defined(_BLD_ast)
23da2e3ebdSchin 
_STUB_vmopen()24da2e3ebdSchin void _STUB_vmopen(){}
25da2e3ebdSchin 
26da2e3ebdSchin #else
27da2e3ebdSchin 
28da2e3ebdSchin #include	"vmhdr.h"
29da2e3ebdSchin 
30da2e3ebdSchin /*	Opening a new region of allocation.
31da2e3ebdSchin **	Note that because of possible exotic memory types,
32da2e3ebdSchin **	all region data must be stored within the space given
33da2e3ebdSchin **	by the discipline.
34da2e3ebdSchin **
35da2e3ebdSchin **	Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
36da2e3ebdSchin */
37da2e3ebdSchin 
38da2e3ebdSchin typedef struct _vminit_
39da2e3ebdSchin {
40da2e3ebdSchin 	Vmdata_t	vd;		/* space for the region itself	*/
41da2e3ebdSchin 	Seg_t		seg;		/* space for segment		*/
42da2e3ebdSchin 	Block_t		block;		/* space for a block		*/
43da2e3ebdSchin 	Head_t		head;		/* space for the fake header	*/
44da2e3ebdSchin 	char		a[3*ALIGN];	/* extra to fuss with alignment	*/
45da2e3ebdSchin } Vminit_t;
46da2e3ebdSchin 
47da2e3ebdSchin #if __STD_C
vmopen(Vmdisc_t * disc,Vmethod_t * meth,int mode)48da2e3ebdSchin Vmalloc_t* vmopen(Vmdisc_t* disc, Vmethod_t* meth, int mode)
49da2e3ebdSchin #else
50da2e3ebdSchin Vmalloc_t* vmopen(disc, meth, mode)
51da2e3ebdSchin Vmdisc_t*	disc;	/* discipline to get segments	*/
52da2e3ebdSchin Vmethod_t*	meth;	/* method to manage space	*/
53da2e3ebdSchin int		mode;	/* type of region		*/
54da2e3ebdSchin #endif
55da2e3ebdSchin {
56da2e3ebdSchin 	reg Vmalloc_t*	vm;
57da2e3ebdSchin 	reg Vmdata_t*	vd;
58da2e3ebdSchin 	reg size_t	s, a, incr;
59da2e3ebdSchin 	reg Block_t*	b;
60da2e3ebdSchin 	reg Seg_t*	seg;
61da2e3ebdSchin 	Vmuchar_t*	addr;
62da2e3ebdSchin 	reg Vmemory_f	memoryf;
63da2e3ebdSchin 	reg int		e;
64da2e3ebdSchin 
65da2e3ebdSchin 	if(!meth || !disc || !(memoryf = disc->memoryf) )
66da2e3ebdSchin 		return NIL(Vmalloc_t*);
67da2e3ebdSchin 
68da2e3ebdSchin 	GETPAGESIZE(_Vmpagesize);
69da2e3ebdSchin 
70da2e3ebdSchin 	/* note that Vmalloc_t space must be local to process since that's
71da2e3ebdSchin 	   where the meth&disc function addresses are going to be stored */
72da2e3ebdSchin 	if(!(vm = (Vmalloc_t*)vmalloc(Vmheap,sizeof(Vmalloc_t))) )
73da2e3ebdSchin 		return NIL(Vmalloc_t*);
74da2e3ebdSchin 	vm->meth = *meth;
75da2e3ebdSchin 	vm->disc = disc;
76da2e3ebdSchin 	vm->file = NIL(char*);
77da2e3ebdSchin 	vm->line = 0;
78da2e3ebdSchin 
79da2e3ebdSchin 	if(disc->exceptf)
80da2e3ebdSchin 	{	addr = NIL(Vmuchar_t*);
81da2e3ebdSchin 		if((e = (*disc->exceptf)(vm,VM_OPEN,(Void_t*)(&addr),disc)) != 0)
82da2e3ebdSchin 		{	if(e < 0 || !addr)
83da2e3ebdSchin 				goto open_error;
84da2e3ebdSchin 
85da2e3ebdSchin 			/* align this address */
86da2e3ebdSchin 			if((a = (size_t)(VLONG(addr)%ALIGN)) != 0)
87da2e3ebdSchin 				addr += ALIGN-a;
88da2e3ebdSchin 
89da2e3ebdSchin 			/* see if it's a valid region */
90da2e3ebdSchin 			vd = (Vmdata_t*)addr;
91da2e3ebdSchin 			if((vd->mode&meth->meth) != 0)
92da2e3ebdSchin 			{	vm->data = vd;
93*3e14f97fSRoger A. Faulkner 				goto done;
94da2e3ebdSchin 			}
95da2e3ebdSchin 			else
96da2e3ebdSchin 			{ open_error:
97da2e3ebdSchin 				vmfree(Vmheap,vm);
98da2e3ebdSchin 				return NIL(Vmalloc_t*);
99da2e3ebdSchin 			}
100da2e3ebdSchin 		}
101da2e3ebdSchin 	}
102da2e3ebdSchin 
103da2e3ebdSchin 	/* make sure vd->incr is properly rounded */
104da2e3ebdSchin 	incr = disc->round <= 0 ? _Vmpagesize : disc->round;
105da2e3ebdSchin 	incr = MULTIPLE(incr,ALIGN);
106da2e3ebdSchin 
107da2e3ebdSchin 	/* get space for region data */
108da2e3ebdSchin 	s = ROUND(sizeof(Vminit_t),incr);
109da2e3ebdSchin 	if(!(addr = (Vmuchar_t*)(*memoryf)(vm,NIL(Void_t*),0,s,disc)) )
110da2e3ebdSchin 	{	vmfree(Vmheap,vm);
111da2e3ebdSchin 		return NIL(Vmalloc_t*);
112da2e3ebdSchin 	}
113da2e3ebdSchin 
114da2e3ebdSchin 	/* make sure that addr is aligned */
115da2e3ebdSchin 	if((a = (size_t)(VLONG(addr)%ALIGN)) != 0)
116da2e3ebdSchin 		addr += ALIGN-a;
117da2e3ebdSchin 
118da2e3ebdSchin 	/* initialize region */
119da2e3ebdSchin 	vd = (Vmdata_t*)addr;
120da2e3ebdSchin 	vd->mode = (mode&VM_FLAGS) | meth->meth;
121da2e3ebdSchin 	vd->incr = incr;
122da2e3ebdSchin 	vd->pool = 0;
123da2e3ebdSchin 	vd->free = vd->wild = NIL(Block_t*);
124da2e3ebdSchin 
125da2e3ebdSchin 	if(vd->mode&(VM_TRACE|VM_MTDEBUG))
126da2e3ebdSchin 		vd->mode &= ~VM_TRUST;
127da2e3ebdSchin 
128da2e3ebdSchin 	if(vd->mode&(VM_MTBEST|VM_MTDEBUG|VM_MTPROFILE))
129da2e3ebdSchin 	{	vd->root = NIL(Block_t*);
130da2e3ebdSchin 		for(e = S_TINY-1; e >= 0; --e)
131da2e3ebdSchin 			TINY(vd)[e] = NIL(Block_t*);
132da2e3ebdSchin 		for(e = S_CACHE; e >= 0; --e)
133da2e3ebdSchin 			CACHE(vd)[e] = NIL(Block_t*);
134da2e3ebdSchin 		incr = sizeof(Vmdata_t);
135da2e3ebdSchin 	}
136da2e3ebdSchin 	else	incr = OFFSET(Vmdata_t,root);
137da2e3ebdSchin 
138da2e3ebdSchin 	vd->seg = (Seg_t*)(addr + ROUND(incr,ALIGN));
139da2e3ebdSchin 	/**/ ASSERT(VLONG(vd->seg)%ALIGN == 0);
140da2e3ebdSchin 
141da2e3ebdSchin 	seg = vd->seg;
142da2e3ebdSchin 	seg->next = NIL(Seg_t*);
143*3e14f97fSRoger A. Faulkner 	seg->vmdt = vd;
144da2e3ebdSchin 	seg->addr = (Void_t*)(addr - (a ? ALIGN-a : 0));
145da2e3ebdSchin 	seg->extent = s;
146da2e3ebdSchin 	seg->baddr = addr + s - (a ? ALIGN : 0);
147da2e3ebdSchin 	seg->size = s;	/* this size is larger than usual so that the segment
148da2e3ebdSchin 			   will not be freed until the region is closed. */
149da2e3ebdSchin 	seg->free = NIL(Block_t*);
150da2e3ebdSchin 
151da2e3ebdSchin 	/* make a data block out of the remainder */
152da2e3ebdSchin 	b = SEGBLOCK(seg);
153da2e3ebdSchin 	SEG(b) = seg;
154da2e3ebdSchin 	SIZE(b) = seg->baddr - (Vmuchar_t*)b - 2*sizeof(Head_t);
155da2e3ebdSchin 	*SELF(b) = b;
156da2e3ebdSchin 	/**/ ASSERT(SIZE(b)%ALIGN == 0);
157da2e3ebdSchin 	/**/ ASSERT(VLONG(b)%ALIGN == 0);
158da2e3ebdSchin 
159da2e3ebdSchin 	/* make a fake header for next block in case of noncontiguous segments */
160da2e3ebdSchin 	SEG(NEXT(b)) = seg;
161da2e3ebdSchin 	SIZE(NEXT(b)) = BUSY|PFREE;
162da2e3ebdSchin 
163da2e3ebdSchin 	if(vd->mode&(VM_MTLAST|VM_MTPOOL))
164da2e3ebdSchin 		seg->free = b;
165da2e3ebdSchin 	else	vd->wild = b;
166da2e3ebdSchin 
167da2e3ebdSchin 	vm->data = vd;
168da2e3ebdSchin 
169*3e14f97fSRoger A. Faulkner done:	/* add to the linked list of regions */
170da2e3ebdSchin 	vm->next = Vmheap->next;
171da2e3ebdSchin 	Vmheap->next = vm;
172da2e3ebdSchin 
173da2e3ebdSchin 	return vm;
174da2e3ebdSchin }
175da2e3ebdSchin 
176da2e3ebdSchin #endif
177