1 /***********************************************************************
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 *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
22 #if defined(_UWIN) && defined(_BLD_ast)
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.
42 static Void_t
* poolalloc(Vmalloc_t
* vm
, reg
size_t size
)
44 static Void_t
* poolalloc(vm
, size
)
49 reg Vmdata_t
* vd
= vm
->data
;
50 reg Block_t
*tp
, *next
;
60 else return NIL(Void_t
*);
64 if(!(local
= vd
->mode
&VM_TRUST
) )
67 { CLRINUSE(vd
, inuse
);
73 if((tp
= vd
->free
) ) /* there is a ready free block */
74 { vd
->free
= SEGLINK(tp
);
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
)
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
);
93 else if(vd
->mode
&VM_AGAIN
)
94 vd
->mode
&= ~VM_AGAIN
;
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
;
105 next
= (Block_t
*)((Vmuchar_t
*)next
+ size
);
107 seg
->free
= NIL(Block_t
*);
110 { SIZE(next
) = s
- sizeof(Head_t
);
116 if(!local
&& (vd
->mode
&VM_TRACE
) && _Vmtrace
&& tp
)
117 (*_Vmtrace
)(vm
,NIL(Vmuchar_t
*),(Vmuchar_t
*)tp
,vd
->pool
,0);
120 ANNOUNCE(local
, vm
, VM_ALLOC
, (Void_t
*)tp
, vm
->disc
);
126 static long pooladdr(Vmalloc_t
* vm
, reg Void_t
* addr
)
128 static long pooladdr(vm
, addr
)
133 reg Block_t
*bp
, *tp
;
134 reg Vmuchar_t
*laddr
, *baddr
;
138 reg Vmdata_t
* vd
= vm
->data
;
139 reg
int local
, inuse
;
142 if(!(local
= vd
->mode
&VM_TRUST
))
143 { GETLOCAL(vd
,local
);
145 { CLRINUSE(vd
, inuse
);
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
)
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
))
168 offset
= (Vmuchar_t
*)addr
- (Vmuchar_t
*)tp
;
179 static int poolfree(reg Vmalloc_t
* vm
, reg Void_t
* data
)
181 static int poolfree(vm
, data
)
187 reg Vmdata_t
* vd
= vm
->data
;
188 reg
int local
, inuse
;
194 if(!(local
= vd
->mode
&VM_TRUST
))
195 { GETLOCAL(vd
, local
);
197 if(ISLOCK(vd
, local
) || vd
->pool
<= 0)
198 { CLRINUSE(vd
, inuse
);
202 if(KPVADDR(vm
,data
,pooladdr
) != 0)
203 { if(vm
->disc
->exceptf
)
204 (void)(*vm
->disc
->exceptf
)(vm
,VM_BADADDR
,data
,vm
->disc
);
214 SEGLINK(bp
) = vd
->free
;
217 if(!local
&& (vd
->mode
&VM_TRACE
) && _Vmtrace
)
218 (*_Vmtrace
)(vm
, (Vmuchar_t
*)data
, NIL(Vmuchar_t
*), vd
->pool
, 0);
221 ANNOUNCE(local
, vm
, VM_FREE
, data
, vm
->disc
);
227 static Void_t
* poolresize(Vmalloc_t
* vm
, Void_t
* data
, size_t size
, int type
)
229 static Void_t
* poolresize(vm
, data
, size
, type
)
237 reg Vmdata_t
* vd
= vm
->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
);
251 { (void)poolfree(vm
,data
);
256 if(!(local
= vd
->mode
&VM_TRUST
) )
257 { GETLOCAL(vd
, local
);
259 if(ISLOCK(vd
, local
) )
260 { CLRINUSE(vd
, inuse
);
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
);
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
);
281 static long poolsize(Vmalloc_t
* vm
, Void_t
* addr
)
283 static long poolsize(vm
, addr
)
288 return pooladdr(vm
,addr
) == 0 ? (long)vm
->data
->pool
: -1L;
292 static int poolcompact(Vmalloc_t
* vm
)
294 static int poolcompact(vm
)
299 reg Seg_t
*seg
, *next
;
301 reg Vmdata_t
* vd
= vm
->data
;
305 if(!(vd
->mode
&VM_TRUST
))
307 { CLRINUSE(vd
, inuse
);
313 for(seg
= vd
->seg
; seg
; seg
= next
)
316 if(!(fp
= seg
->free
))
319 seg
->free
= NIL(Block_t
*);
320 if(seg
->size
== (s
= SIZE(fp
)&~BITS
))
322 else s
+= sizeof(Head_t
);
324 if((*_Vmtruncate
)(vm
,seg
,s
,1) == s
)
328 if((vd
->mode
&VM_TRACE
) && _Vmtrace
)
329 (*_Vmtrace
)(vm
, (Vmuchar_t
*)0, (Vmuchar_t
*)0, 0, 0);
337 static Void_t
* poolalign(Vmalloc_t
* vm
, size_t size
, size_t align
)
339 static Void_t
* poolalign(vm
, size
, align
)
351 /* Public interface */
352 static Vmethod_t _Vmpool
=
364 __DEFINE__(Vmethod_t
*,Vmpool
,&_Vmpool
);