Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/vmalloc/vmopen.c
1810 views
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 <[email protected]> *
18
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
20
* *
21
***********************************************************************/
22
#if defined(_UWIN) && defined(_BLD_ast)
23
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, [email protected], 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
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
182