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