1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2008 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) 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 typedef struct _vminit_ 39 { 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; 46 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 55 { 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; 64 65 if(!meth || !disc || !(memoryf = disc->memoryf) ) 66 return NIL(Vmalloc_t*); 67 68 GETPAGESIZE(_Vmpagesize); 69 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; 78 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; 84 85 /* align this address */ 86 if((a = (size_t)(VLONG(addr)%ALIGN)) != 0) 87 addr += ALIGN-a; 88 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 return vm; 94 } 95 else 96 { open_error: 97 vmfree(Vmheap,vm); 98 return NIL(Vmalloc_t*); 99 } 100 } 101 } 102 103 /* make sure vd->incr is properly rounded */ 104 incr = disc->round <= 0 ? _Vmpagesize : disc->round; 105 incr = MULTIPLE(incr,ALIGN); 106 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*); 112 } 113 114 /* make sure that addr is aligned */ 115 if((a = (size_t)(VLONG(addr)%ALIGN)) != 0) 116 addr += ALIGN-a; 117 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*); 124 125 if(vd->mode&(VM_TRACE|VM_MTDEBUG)) 126 vd->mode &= ~VM_TRUST; 127 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); 135 } 136 else incr = OFFSET(Vmdata_t,root); 137 138 vd->seg = (Seg_t*)(addr + ROUND(incr,ALIGN)); 139 /**/ ASSERT(VLONG(vd->seg)%ALIGN == 0); 140 141 seg = vd->seg; 142 seg->next = NIL(Seg_t*); 143 seg->vm = vm; 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*); 150 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); 158 159 /* make a fake header for next block in case of noncontiguous segments */ 160 SEG(NEXT(b)) = seg; 161 SIZE(NEXT(b)) = BUSY|PFREE; 162 163 if(vd->mode&(VM_MTLAST|VM_MTPOOL)) 164 seg->free = b; 165 else vd->wild = b; 166 167 vm->data = vd; 168 169 /* put into linked list of regions */ 170 vm->next = Vmheap->next; 171 Vmheap->next = vm; 172 173 return vm; 174 } 175 176 #endif 177