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