import less(1)
[unleashed/tickless.git] / usr / src / lib / libast / common / vmalloc / vmpool.c
blob965712cf9b3fb6f6a96e5a2b4338a51e0f74d7c9
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_vmpool(){}
26 #else
28 #include "vmhdr.h"
30 #define POOLFREE 0x55555555L /* block free indicator */
32 /* Method for pool allocation.
33 ** All elements in a pool have the same size.
34 ** The following fields of Vmdata_t are used as:
35 ** pool: size of a block.
36 ** free: list of free blocks.
38 ** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
41 #if __STD_C
42 static Void_t* poolalloc(Vmalloc_t* vm, reg size_t size)
43 #else
44 static Void_t* poolalloc(vm, size )
45 Vmalloc_t* vm;
46 reg size_t size;
47 #endif
49 reg Vmdata_t* vd = vm->data;
50 reg Block_t *tp, *next;
51 reg size_t s;
52 reg Seg_t* seg;
53 reg int local, inuse;
55 if(size <= 0)
56 return NIL(Void_t*);
57 if(size != vd->pool)
58 { if(vd->pool <= 0)
59 vd->pool = size;
60 else return NIL(Void_t*);
63 SETINUSE(vd, inuse);
64 if(!(local = vd->mode&VM_TRUST) )
65 { GETLOCAL(vd,local);
66 if(ISLOCK(vd, local))
67 { CLRINUSE(vd, inuse);
68 return NIL(Void_t*);
70 SETLOCK(vd, local);
73 if((tp = vd->free) ) /* there is a ready free block */
74 { vd->free = SEGLINK(tp);
75 goto done;
78 size = ROUND(size,ALIGN);
80 /* look thru all segments for a suitable free block */
81 for(tp = NIL(Block_t*), seg = vd->seg; seg; seg = seg->next)
82 { if((tp = seg->free) &&
83 (s = (SIZE(tp) & ~BITS) + sizeof(Head_t)) >= size )
84 goto has_blk;
87 for(;;) /* must extend region */
88 { if((tp = (*_Vmextend)(vm,ROUND(size,vd->incr),NIL(Vmsearch_f))) )
89 { s = (SIZE(tp) & ~BITS) + sizeof(Head_t);
90 seg = SEG(tp);
91 goto has_blk;
93 else if(vd->mode&VM_AGAIN)
94 vd->mode &= ~VM_AGAIN;
95 else goto done;
98 has_blk: /* if get here, (tp, s, seg) must be well-defined */
99 next = (Block_t*)((Vmuchar_t*)tp+size);
100 if((s -= size) <= (size + sizeof(Head_t)) )
101 { for(; s >= size; s -= size)
102 { SIZE(next) = POOLFREE;
103 SEGLINK(next) = vd->free;
104 vd->free = next;
105 next = (Block_t*)((Vmuchar_t*)next + size);
107 seg->free = NIL(Block_t*);
109 else
110 { SIZE(next) = s - sizeof(Head_t);
111 SEG(next) = seg;
112 seg->free = next;
115 done:
116 if(!local && (vd->mode&VM_TRACE) && _Vmtrace && tp)
117 (*_Vmtrace)(vm,NIL(Vmuchar_t*),(Vmuchar_t*)tp,vd->pool,0);
119 CLRLOCK(vd, local);
120 ANNOUNCE(local, vm, VM_ALLOC, (Void_t*)tp, vm->disc);
121 CLRINUSE(vd, inuse);
122 return (Void_t*)tp;
125 #if __STD_C
126 static long pooladdr(Vmalloc_t* vm, reg Void_t* addr)
127 #else
128 static long pooladdr(vm, addr)
129 Vmalloc_t* vm;
130 reg Void_t* addr;
131 #endif
133 reg Block_t *bp, *tp;
134 reg Vmuchar_t *laddr, *baddr;
135 reg size_t size;
136 reg Seg_t* seg;
137 reg long offset;
138 reg Vmdata_t* vd = vm->data;
139 reg int local, inuse;
141 SETINUSE(vd, inuse);
142 if(!(local = vd->mode&VM_TRUST))
143 { GETLOCAL(vd,local);
144 if(ISLOCK(vd,local))
145 { CLRINUSE(vd, inuse);
146 return -1L;
148 SETLOCK(vd,local);
151 offset = -1L;
152 for(seg = vd->seg; seg; seg = seg->next)
153 { laddr = (Vmuchar_t*)SEGBLOCK(seg);
154 baddr = seg->baddr-sizeof(Head_t);
155 if((Vmuchar_t*)addr < laddr || (Vmuchar_t*)addr >= baddr)
156 continue;
158 /* the block that has this address */
159 size = ROUND(vd->pool,ALIGN);
160 tp = (Block_t*)(laddr + (((Vmuchar_t*)addr-laddr)/size)*size );
162 /* see if this block has been freed */
163 if(SIZE(tp) == POOLFREE) /* may be a coincidence - make sure */
164 for(bp = vd->free; bp; bp = SEGLINK(bp))
165 if(bp == tp)
166 goto done;
168 offset = (Vmuchar_t*)addr - (Vmuchar_t*)tp;
169 goto done;
172 done :
173 CLRLOCK(vd,local);
174 CLRINUSE(vd, inuse);
175 return offset;
178 #if __STD_C
179 static int poolfree(reg Vmalloc_t* vm, reg Void_t* data )
180 #else
181 static int poolfree(vm, data)
182 reg Vmalloc_t* vm;
183 reg Void_t* data;
184 #endif
186 reg Block_t* bp;
187 reg Vmdata_t* vd = vm->data;
188 reg int local, inuse;
190 if(!data)
191 return 0;
193 SETINUSE(vd, inuse);
194 if(!(local = vd->mode&VM_TRUST))
195 { GETLOCAL(vd, local);
197 if(ISLOCK(vd, local) || vd->pool <= 0)
198 { CLRINUSE(vd, inuse);
199 return -1;
202 if(KPVADDR(vm,data,pooladdr) != 0)
203 { if(vm->disc->exceptf)
204 (void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
205 CLRINUSE(vd, inuse);
206 return -1;
209 SETLOCK(vd, local);
212 bp = (Block_t*)data;
213 SIZE(bp) = POOLFREE;
214 SEGLINK(bp) = vd->free;
215 vd->free = bp;
217 if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
218 (*_Vmtrace)(vm, (Vmuchar_t*)data, NIL(Vmuchar_t*), vd->pool, 0);
220 CLRLOCK(vd,local);
221 ANNOUNCE(local, vm, VM_FREE, data, vm->disc);
222 CLRINUSE(vd, inuse);
223 return 0;
226 #if __STD_C
227 static Void_t* poolresize(Vmalloc_t* vm, Void_t* data, size_t size, int type )
228 #else
229 static Void_t* poolresize(vm, data, size, type )
230 Vmalloc_t* vm;
231 Void_t* data;
232 size_t size;
233 int type;
234 #endif
236 int local, inuse;
237 reg Vmdata_t* vd = vm->data;
239 NOTUSED(type);
241 SETINUSE(vd, inuse);
242 if(!data)
243 { if((data = poolalloc(vm,size)) && (type&VM_RSZERO) )
244 { reg int *d = (int*)data, *ed = (int*)((char*)data+size);
245 do { *d++ = 0;} while(d < ed);
247 CLRINUSE(vd, inuse);
248 return data;
250 if(size == 0)
251 { (void)poolfree(vm,data);
252 CLRINUSE(vd, inuse);
253 return NIL(Void_t*);
256 if(!(local = vd->mode&VM_TRUST) )
257 { GETLOCAL(vd, local);
259 if(ISLOCK(vd, local) )
260 { CLRINUSE(vd, inuse);
261 return NIL(Void_t*);
264 if(size != vd->pool || KPVADDR(vm,data,pooladdr) != 0)
265 { if(vm->disc->exceptf)
266 (void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
267 CLRINUSE(vd, inuse);
268 return NIL(Void_t*);
271 if((vd->mode&VM_TRACE) && _Vmtrace)
272 (*_Vmtrace)(vm, (Vmuchar_t*)data, (Vmuchar_t*)data, size, 0);
275 ANNOUNCE(local, vm, VM_RESIZE, data, vm->disc);
276 CLRINUSE(vd, inuse);
277 return data;
280 #if __STD_C
281 static long poolsize(Vmalloc_t* vm, Void_t* addr)
282 #else
283 static long poolsize(vm, addr)
284 Vmalloc_t* vm;
285 Void_t* addr;
286 #endif
288 return pooladdr(vm,addr) == 0 ? (long)vm->data->pool : -1L;
291 #if __STD_C
292 static int poolcompact(Vmalloc_t* vm)
293 #else
294 static int poolcompact(vm)
295 Vmalloc_t* vm;
296 #endif
298 reg Block_t* fp;
299 reg Seg_t *seg, *next;
300 reg size_t s;
301 reg Vmdata_t* vd = vm->data;
302 reg int inuse;
304 SETINUSE(vd, inuse);
305 if(!(vd->mode&VM_TRUST))
306 { if(ISLOCK(vd,0))
307 { CLRINUSE(vd, inuse);
308 return -1;
310 SETLOCK(vd,0);
313 for(seg = vd->seg; seg; seg = next)
314 { next = seg->next;
316 if(!(fp = seg->free))
317 continue;
319 seg->free = NIL(Block_t*);
320 if(seg->size == (s = SIZE(fp)&~BITS))
321 s = seg->extent;
322 else s += sizeof(Head_t);
324 if((*_Vmtruncate)(vm,seg,s,1) == s)
325 seg->free = fp;
328 if((vd->mode&VM_TRACE) && _Vmtrace)
329 (*_Vmtrace)(vm, (Vmuchar_t*)0, (Vmuchar_t*)0, 0, 0);
331 CLRLOCK(vd,0);
332 CLRINUSE(vd, inuse);
333 return 0;
336 #if __STD_C
337 static Void_t* poolalign(Vmalloc_t* vm, size_t size, size_t align)
338 #else
339 static Void_t* poolalign(vm, size, align)
340 Vmalloc_t* vm;
341 size_t size;
342 size_t align;
343 #endif
345 NOTUSED(vm);
346 NOTUSED(size);
347 NOTUSED(align);
348 return NIL(Void_t*);
351 /* Public interface */
352 static Vmethod_t _Vmpool =
354 poolalloc,
355 poolresize,
356 poolfree,
357 pooladdr,
358 poolsize,
359 poolcompact,
360 poolalign,
361 VM_MTPOOL
364 __DEFINE__(Vmethod_t*,Vmpool,&_Vmpool);
366 #ifdef NoF
367 NoF(vmpool)
368 #endif
370 #endif