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 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 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