14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * David Korn <dgk@research.att.com> *
194887Schin * Phong Vo <kpv@research.att.com> *
204887Schin * *
214887Schin ***********************************************************************/
224887Schin #if defined(_UWIN) && defined(_BLD_ast)
234887Schin
_STUB_vmpool()244887Schin void _STUB_vmpool(){}
254887Schin
264887Schin #else
274887Schin
284887Schin #include "vmhdr.h"
294887Schin
304887Schin #define POOLFREE 0x55555555L /* block free indicator */
314887Schin
324887Schin /* Method for pool allocation.
334887Schin ** All elements in a pool have the same size.
344887Schin ** The following fields of Vmdata_t are used as:
354887Schin ** pool: size of a block.
364887Schin ** free: list of free blocks.
374887Schin **
384887Schin ** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
394887Schin */
404887Schin
414887Schin #if __STD_C
poolalloc(Vmalloc_t * vm,reg size_t size)424887Schin static Void_t* poolalloc(Vmalloc_t* vm, reg size_t size)
434887Schin #else
444887Schin static Void_t* poolalloc(vm, size )
454887Schin Vmalloc_t* vm;
464887Schin reg size_t size;
474887Schin #endif
484887Schin {
494887Schin reg Vmdata_t* vd = vm->data;
504887Schin reg Block_t *tp, *next;
514887Schin reg size_t s;
524887Schin reg Seg_t* seg;
538462SApril.Chin@Sun.COM reg int local, inuse;
544887Schin
554887Schin if(size <= 0)
564887Schin return NIL(Void_t*);
57*12068SRoger.Faulkner@Oracle.COM if(size != vd->pool)
584887Schin { if(vd->pool <= 0)
594887Schin vd->pool = size;
604887Schin else return NIL(Void_t*);
614887Schin }
624887Schin
638462SApril.Chin@Sun.COM SETINUSE(vd, inuse);
644887Schin if(!(local = vd->mode&VM_TRUST) )
654887Schin { GETLOCAL(vd,local);
664887Schin if(ISLOCK(vd, local))
678462SApril.Chin@Sun.COM { CLRINUSE(vd, inuse);
684887Schin return NIL(Void_t*);
698462SApril.Chin@Sun.COM }
704887Schin SETLOCK(vd, local);
714887Schin }
724887Schin
734887Schin if((tp = vd->free) ) /* there is a ready free block */
744887Schin { vd->free = SEGLINK(tp);
754887Schin goto done;
764887Schin }
774887Schin
784887Schin size = ROUND(size,ALIGN);
794887Schin
804887Schin /* look thru all segments for a suitable free block */
814887Schin for(tp = NIL(Block_t*), seg = vd->seg; seg; seg = seg->next)
824887Schin { if((tp = seg->free) &&
834887Schin (s = (SIZE(tp) & ~BITS) + sizeof(Head_t)) >= size )
844887Schin goto has_blk;
854887Schin }
864887Schin
874887Schin for(;;) /* must extend region */
884887Schin { if((tp = (*_Vmextend)(vm,ROUND(size,vd->incr),NIL(Vmsearch_f))) )
894887Schin { s = (SIZE(tp) & ~BITS) + sizeof(Head_t);
904887Schin seg = SEG(tp);
914887Schin goto has_blk;
924887Schin }
934887Schin else if(vd->mode&VM_AGAIN)
944887Schin vd->mode &= ~VM_AGAIN;
954887Schin else goto done;
964887Schin }
974887Schin
984887Schin has_blk: /* if get here, (tp, s, seg) must be well-defined */
994887Schin next = (Block_t*)((Vmuchar_t*)tp+size);
1004887Schin if((s -= size) <= (size + sizeof(Head_t)) )
1014887Schin { for(; s >= size; s -= size)
1024887Schin { SIZE(next) = POOLFREE;
1034887Schin SEGLINK(next) = vd->free;
1044887Schin vd->free = next;
1054887Schin next = (Block_t*)((Vmuchar_t*)next + size);
1064887Schin }
1074887Schin seg->free = NIL(Block_t*);
1084887Schin }
1094887Schin else
1104887Schin { SIZE(next) = s - sizeof(Head_t);
1114887Schin SEG(next) = seg;
1124887Schin seg->free = next;
1134887Schin }
1144887Schin
1154887Schin done:
1164887Schin if(!local && (vd->mode&VM_TRACE) && _Vmtrace && tp)
1174887Schin (*_Vmtrace)(vm,NIL(Vmuchar_t*),(Vmuchar_t*)tp,vd->pool,0);
1184887Schin
1194887Schin CLRLOCK(vd, local);
1204887Schin ANNOUNCE(local, vm, VM_ALLOC, (Void_t*)tp, vm->disc);
1218462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
1224887Schin return (Void_t*)tp;
1234887Schin }
1244887Schin
1254887Schin #if __STD_C
pooladdr(Vmalloc_t * vm,reg Void_t * addr)1264887Schin static long pooladdr(Vmalloc_t* vm, reg Void_t* addr)
1274887Schin #else
1284887Schin static long pooladdr(vm, addr)
1294887Schin Vmalloc_t* vm;
1304887Schin reg Void_t* addr;
1314887Schin #endif
1324887Schin {
1334887Schin reg Block_t *bp, *tp;
1344887Schin reg Vmuchar_t *laddr, *baddr;
1354887Schin reg size_t size;
1364887Schin reg Seg_t* seg;
1374887Schin reg long offset;
1384887Schin reg Vmdata_t* vd = vm->data;
1398462SApril.Chin@Sun.COM reg int local, inuse;
1404887Schin
1418462SApril.Chin@Sun.COM SETINUSE(vd, inuse);
1424887Schin if(!(local = vd->mode&VM_TRUST))
1434887Schin { GETLOCAL(vd,local);
1444887Schin if(ISLOCK(vd,local))
1458462SApril.Chin@Sun.COM { CLRINUSE(vd, inuse);
1464887Schin return -1L;
1478462SApril.Chin@Sun.COM }
1484887Schin SETLOCK(vd,local);
1494887Schin }
1504887Schin
1514887Schin offset = -1L;
1524887Schin for(seg = vd->seg; seg; seg = seg->next)
1534887Schin { laddr = (Vmuchar_t*)SEGBLOCK(seg);
1544887Schin baddr = seg->baddr-sizeof(Head_t);
1554887Schin if((Vmuchar_t*)addr < laddr || (Vmuchar_t*)addr >= baddr)
1564887Schin continue;
1574887Schin
1584887Schin /* the block that has this address */
1594887Schin size = ROUND(vd->pool,ALIGN);
1604887Schin tp = (Block_t*)(laddr + (((Vmuchar_t*)addr-laddr)/size)*size );
1614887Schin
1624887Schin /* see if this block has been freed */
1634887Schin if(SIZE(tp) == POOLFREE) /* may be a coincidence - make sure */
1644887Schin for(bp = vd->free; bp; bp = SEGLINK(bp))
1654887Schin if(bp == tp)
1664887Schin goto done;
1674887Schin
1684887Schin offset = (Vmuchar_t*)addr - (Vmuchar_t*)tp;
1694887Schin goto done;
1704887Schin }
1714887Schin
1724887Schin done :
1734887Schin CLRLOCK(vd,local);
1748462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
1754887Schin return offset;
1764887Schin }
1774887Schin
1784887Schin #if __STD_C
poolfree(reg Vmalloc_t * vm,reg Void_t * data)1794887Schin static int poolfree(reg Vmalloc_t* vm, reg Void_t* data )
1804887Schin #else
1814887Schin static int poolfree(vm, data)
1824887Schin reg Vmalloc_t* vm;
1834887Schin reg Void_t* data;
1844887Schin #endif
1854887Schin {
1864887Schin reg Block_t* bp;
1874887Schin reg Vmdata_t* vd = vm->data;
1888462SApril.Chin@Sun.COM reg int local, inuse;
1894887Schin
1904887Schin if(!data)
1914887Schin return 0;
1924887Schin
1938462SApril.Chin@Sun.COM SETINUSE(vd, inuse);
1944887Schin if(!(local = vd->mode&VM_TRUST))
1954887Schin { GETLOCAL(vd, local);
1964887Schin
1974887Schin if(ISLOCK(vd, local) || vd->pool <= 0)
1988462SApril.Chin@Sun.COM { CLRINUSE(vd, inuse);
1994887Schin return -1;
2008462SApril.Chin@Sun.COM }
2014887Schin
2024887Schin if(KPVADDR(vm,data,pooladdr) != 0)
2034887Schin { if(vm->disc->exceptf)
2044887Schin (void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
2058462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
2064887Schin return -1;
2074887Schin }
2084887Schin
2094887Schin SETLOCK(vd, local);
2104887Schin }
2114887Schin
2124887Schin bp = (Block_t*)data;
2134887Schin SIZE(bp) = POOLFREE;
2144887Schin SEGLINK(bp) = vd->free;
2154887Schin vd->free = bp;
2164887Schin
2174887Schin if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
2184887Schin (*_Vmtrace)(vm, (Vmuchar_t*)data, NIL(Vmuchar_t*), vd->pool, 0);
2194887Schin
2204887Schin CLRLOCK(vd,local);
2214887Schin ANNOUNCE(local, vm, VM_FREE, data, vm->disc);
2228462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
2234887Schin return 0;
2244887Schin }
2254887Schin
2264887Schin #if __STD_C
poolresize(Vmalloc_t * vm,Void_t * data,size_t size,int type)2274887Schin static Void_t* poolresize(Vmalloc_t* vm, Void_t* data, size_t size, int type )
2284887Schin #else
2294887Schin static Void_t* poolresize(vm, data, size, type )
2304887Schin Vmalloc_t* vm;
2314887Schin Void_t* data;
2324887Schin size_t size;
2334887Schin int type;
2344887Schin #endif
2354887Schin {
2368462SApril.Chin@Sun.COM int local, inuse;
2374887Schin reg Vmdata_t* vd = vm->data;
2384887Schin
2394887Schin NOTUSED(type);
2404887Schin
2418462SApril.Chin@Sun.COM SETINUSE(vd, inuse);
2424887Schin if(!data)
2434887Schin { if((data = poolalloc(vm,size)) && (type&VM_RSZERO) )
2444887Schin { reg int *d = (int*)data, *ed = (int*)((char*)data+size);
2454887Schin do { *d++ = 0;} while(d < ed);
2464887Schin }
2478462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
2484887Schin return data;
2494887Schin }
2504887Schin if(size == 0)
2514887Schin { (void)poolfree(vm,data);
2528462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
2534887Schin return NIL(Void_t*);
2544887Schin }
2554887Schin
2564887Schin if(!(local = vd->mode&VM_TRUST) )
2574887Schin { GETLOCAL(vd, local);
2584887Schin
2594887Schin if(ISLOCK(vd, local) )
2608462SApril.Chin@Sun.COM { CLRINUSE(vd, inuse);
2614887Schin return NIL(Void_t*);
2628462SApril.Chin@Sun.COM }
2634887Schin
2644887Schin if(size != vd->pool || KPVADDR(vm,data,pooladdr) != 0)
2654887Schin { if(vm->disc->exceptf)
2664887Schin (void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
2678462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
2684887Schin return NIL(Void_t*);
2694887Schin }
2704887Schin
2714887Schin if((vd->mode&VM_TRACE) && _Vmtrace)
2724887Schin (*_Vmtrace)(vm, (Vmuchar_t*)data, (Vmuchar_t*)data, size, 0);
2734887Schin }
2744887Schin
2754887Schin ANNOUNCE(local, vm, VM_RESIZE, data, vm->disc);
2768462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
2774887Schin return data;
2784887Schin }
2794887Schin
2804887Schin #if __STD_C
poolsize(Vmalloc_t * vm,Void_t * addr)2814887Schin static long poolsize(Vmalloc_t* vm, Void_t* addr)
2824887Schin #else
2834887Schin static long poolsize(vm, addr)
2844887Schin Vmalloc_t* vm;
2854887Schin Void_t* addr;
2864887Schin #endif
2874887Schin {
2884887Schin return pooladdr(vm,addr) == 0 ? (long)vm->data->pool : -1L;
2894887Schin }
2904887Schin
2914887Schin #if __STD_C
poolcompact(Vmalloc_t * vm)2924887Schin static int poolcompact(Vmalloc_t* vm)
2934887Schin #else
2944887Schin static int poolcompact(vm)
2954887Schin Vmalloc_t* vm;
2964887Schin #endif
2974887Schin {
2984887Schin reg Block_t* fp;
2994887Schin reg Seg_t *seg, *next;
3004887Schin reg size_t s;
3014887Schin reg Vmdata_t* vd = vm->data;
3028462SApril.Chin@Sun.COM reg int inuse;
3034887Schin
3048462SApril.Chin@Sun.COM SETINUSE(vd, inuse);
3054887Schin if(!(vd->mode&VM_TRUST))
3064887Schin { if(ISLOCK(vd,0))
3078462SApril.Chin@Sun.COM { CLRINUSE(vd, inuse);
3084887Schin return -1;
3098462SApril.Chin@Sun.COM }
3104887Schin SETLOCK(vd,0);
3114887Schin }
3124887Schin
3134887Schin for(seg = vd->seg; seg; seg = next)
3144887Schin { next = seg->next;
3154887Schin
3164887Schin if(!(fp = seg->free))
3174887Schin continue;
3184887Schin
3194887Schin seg->free = NIL(Block_t*);
3204887Schin if(seg->size == (s = SIZE(fp)&~BITS))
3214887Schin s = seg->extent;
3224887Schin else s += sizeof(Head_t);
3234887Schin
3244887Schin if((*_Vmtruncate)(vm,seg,s,1) == s)
3254887Schin seg->free = fp;
3264887Schin }
3274887Schin
3284887Schin if((vd->mode&VM_TRACE) && _Vmtrace)
3294887Schin (*_Vmtrace)(vm, (Vmuchar_t*)0, (Vmuchar_t*)0, 0, 0);
3304887Schin
3314887Schin CLRLOCK(vd,0);
3328462SApril.Chin@Sun.COM CLRINUSE(vd, inuse);
3334887Schin return 0;
3344887Schin }
3354887Schin
3364887Schin #if __STD_C
poolalign(Vmalloc_t * vm,size_t size,size_t align)3374887Schin static Void_t* poolalign(Vmalloc_t* vm, size_t size, size_t align)
3384887Schin #else
3394887Schin static Void_t* poolalign(vm, size, align)
3404887Schin Vmalloc_t* vm;
3414887Schin size_t size;
3424887Schin size_t align;
3434887Schin #endif
3444887Schin {
3454887Schin NOTUSED(vm);
3464887Schin NOTUSED(size);
3474887Schin NOTUSED(align);
3484887Schin return NIL(Void_t*);
3494887Schin }
3504887Schin
3514887Schin /* Public interface */
3524887Schin static Vmethod_t _Vmpool =
3534887Schin {
3544887Schin poolalloc,
3554887Schin poolresize,
3564887Schin poolfree,
3574887Schin pooladdr,
3584887Schin poolsize,
3594887Schin poolcompact,
3604887Schin poolalign,
3614887Schin VM_MTPOOL
3624887Schin };
3634887Schin
3644887Schin __DEFINE__(Vmethod_t*,Vmpool,&_Vmpool);
3654887Schin
3664887Schin #ifdef NoF
3674887Schin NoF(vmpool)
3684887Schin #endif
3694887Schin
3704887Schin #endif
371