xref: /titanic_44/usr/src/lib/libast/common/vmalloc/vmlast.c (revision 3e14f97f673e8a630f076077de35afdd43dc1587)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*3e14f97fSRoger A. Faulkner *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6da2e3ebdSchin *                  Common Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10da2e3ebdSchin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11da2e3ebdSchin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
19da2e3ebdSchin *                   Phong Vo <kpv@research.att.com>                    *
20da2e3ebdSchin *                                                                      *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #if defined(_UWIN) && defined(_BLD_ast)
23da2e3ebdSchin 
_STUB_vmlast()24da2e3ebdSchin void _STUB_vmlast(){}
25da2e3ebdSchin 
26da2e3ebdSchin #else
27da2e3ebdSchin 
28da2e3ebdSchin #include	"vmhdr.h"
29da2e3ebdSchin 
30da2e3ebdSchin /*	Allocation with freeing and reallocing of last allocated block only.
31da2e3ebdSchin **
32da2e3ebdSchin **	Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
33da2e3ebdSchin */
34da2e3ebdSchin 
35da2e3ebdSchin #if __STD_C
lastalloc(Vmalloc_t * vm,size_t size)36da2e3ebdSchin static Void_t* lastalloc(Vmalloc_t* vm, size_t size)
37da2e3ebdSchin #else
38da2e3ebdSchin static Void_t* lastalloc(vm, size)
39da2e3ebdSchin Vmalloc_t*	vm;
40da2e3ebdSchin size_t		size;
41da2e3ebdSchin #endif
42da2e3ebdSchin {
43da2e3ebdSchin 	reg Block_t	*tp, *next;
44da2e3ebdSchin 	reg Seg_t	*seg, *last;
45da2e3ebdSchin 	reg size_t	s;
46da2e3ebdSchin 	reg Vmdata_t*	vd = vm->data;
477c2fbfb3SApril Chin 	reg int		local, inuse;
48da2e3ebdSchin 	size_t		orgsize = 0;
49da2e3ebdSchin 
507c2fbfb3SApril Chin 	SETINUSE(vd, inuse);
51da2e3ebdSchin 	if(!(local = vd->mode&VM_TRUST))
52da2e3ebdSchin 	{	GETLOCAL(vd,local);
53da2e3ebdSchin 		if(ISLOCK(vd,local))
547c2fbfb3SApril Chin 		{	CLRINUSE(vd, inuse);
55da2e3ebdSchin 			return NIL(Void_t*);
567c2fbfb3SApril Chin 		}
57da2e3ebdSchin 		SETLOCK(vd,local);
58da2e3ebdSchin 		orgsize = size;
59da2e3ebdSchin 	}
60da2e3ebdSchin 
61da2e3ebdSchin 	size = size < ALIGN ? ALIGN : ROUND(size,ALIGN);
62da2e3ebdSchin 	for(;;)
63da2e3ebdSchin 	{	for(last = NIL(Seg_t*), seg = vd->seg; seg; last = seg, seg = seg->next)
64da2e3ebdSchin 		{	if(!(tp = seg->free) || (SIZE(tp)+sizeof(Head_t)) < size)
65da2e3ebdSchin 				continue;
66da2e3ebdSchin 			if(last)
67da2e3ebdSchin 			{	last->next = seg->next;
68da2e3ebdSchin 				seg->next = vd->seg;
69da2e3ebdSchin 				vd->seg = seg;
70da2e3ebdSchin 			}
71da2e3ebdSchin 			goto got_block;
72da2e3ebdSchin 		}
73da2e3ebdSchin 
74da2e3ebdSchin 		/* there is no usable free space in region, try extending */
75da2e3ebdSchin 		if((tp = (*_Vmextend)(vm,size,NIL(Vmsearch_f))) )
76da2e3ebdSchin 		{	seg = SEG(tp);
77da2e3ebdSchin 			goto got_block;
78da2e3ebdSchin 		}
79da2e3ebdSchin 		else if(vd->mode&VM_AGAIN)
80da2e3ebdSchin 			vd->mode &= ~VM_AGAIN;
81da2e3ebdSchin 		else	goto done;
82da2e3ebdSchin 	}
83da2e3ebdSchin 
84da2e3ebdSchin got_block:
85da2e3ebdSchin 	if((s = SIZE(tp)) >= size)
86da2e3ebdSchin 	{	next = (Block_t*)((Vmuchar_t*)tp+size);
87da2e3ebdSchin 		SIZE(next) = s - size;
88da2e3ebdSchin 		SEG(next) = seg;
89da2e3ebdSchin 		seg->free = next;
90da2e3ebdSchin 	}
91da2e3ebdSchin 	else	seg->free = NIL(Block_t*);
92da2e3ebdSchin 
93da2e3ebdSchin 	vd->free = seg->last = tp;
94da2e3ebdSchin 
95da2e3ebdSchin 	if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
96da2e3ebdSchin 		(*_Vmtrace)(vm, NIL(Vmuchar_t*), (Vmuchar_t*)tp, orgsize, 0);
97da2e3ebdSchin 
98da2e3ebdSchin done:
99da2e3ebdSchin 	CLRLOCK(vd,local);
100da2e3ebdSchin 	ANNOUNCE(local, vm, VM_ALLOC, (Void_t*)tp, vm->disc);
1017c2fbfb3SApril Chin 	CLRINUSE(vd, inuse);
102da2e3ebdSchin 	return (Void_t*)tp;
103da2e3ebdSchin }
104da2e3ebdSchin 
105da2e3ebdSchin #if __STD_C
lastfree(Vmalloc_t * vm,reg Void_t * data)106da2e3ebdSchin static int lastfree(Vmalloc_t* vm, reg Void_t* data )
107da2e3ebdSchin #else
108da2e3ebdSchin static int lastfree(vm, data)
109da2e3ebdSchin Vmalloc_t*	vm;
110da2e3ebdSchin reg Void_t*	data;
111da2e3ebdSchin #endif
112da2e3ebdSchin {
113da2e3ebdSchin 	reg Seg_t*	seg;
114da2e3ebdSchin 	reg Block_t*	fp;
115da2e3ebdSchin 	reg size_t	s;
116da2e3ebdSchin 	reg Vmdata_t*	vd = vm->data;
1177c2fbfb3SApril Chin 	reg int		local, inuse;
118da2e3ebdSchin 
119da2e3ebdSchin 	if(!data)
120da2e3ebdSchin 		return 0;
1217c2fbfb3SApril Chin 
1227c2fbfb3SApril Chin 	SETINUSE(vd, inuse);
123da2e3ebdSchin 	if(!(local = vd->mode&VM_TRUST) )
124da2e3ebdSchin 	{	GETLOCAL(vd, local);
125da2e3ebdSchin 		if(ISLOCK(vd, local))
1267c2fbfb3SApril Chin 		{	CLRINUSE(vd, inuse);
127da2e3ebdSchin 			return -1;
1287c2fbfb3SApril Chin 		}
129da2e3ebdSchin 		SETLOCK(vd, local);
130da2e3ebdSchin 	}
131da2e3ebdSchin 	if(data != (Void_t*)vd->free)
132da2e3ebdSchin 	{	if(!local && vm->disc->exceptf)
133da2e3ebdSchin 			(void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
134da2e3ebdSchin 		CLRLOCK(vd, local);
1357c2fbfb3SApril Chin 		CLRINUSE(vd, inuse);
136da2e3ebdSchin 		return -1;
137da2e3ebdSchin 	}
138da2e3ebdSchin 
139da2e3ebdSchin 	seg = vd->seg;
140da2e3ebdSchin 	if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
141da2e3ebdSchin 	{	if(seg->free )
142da2e3ebdSchin 			s = (Vmuchar_t*)(seg->free) - (Vmuchar_t*)data;
143da2e3ebdSchin 		else	s = (Vmuchar_t*)BLOCK(seg->baddr) - (Vmuchar_t*)data;
144da2e3ebdSchin 		(*_Vmtrace)(vm, (Vmuchar_t*)data, NIL(Vmuchar_t*), s, 0);
145da2e3ebdSchin 	}
146da2e3ebdSchin 
147da2e3ebdSchin 	vd->free = NIL(Block_t*);
148da2e3ebdSchin 	fp = (Block_t*)data;
149da2e3ebdSchin 	SEG(fp)  = seg;
150da2e3ebdSchin 	SIZE(fp) = ((Vmuchar_t*)BLOCK(seg->baddr) - (Vmuchar_t*)data) - sizeof(Head_t);
151da2e3ebdSchin 	seg->free = fp;
152da2e3ebdSchin 	seg->last = NIL(Block_t*);
153da2e3ebdSchin 
154da2e3ebdSchin 	CLRLOCK(vd, local);
155da2e3ebdSchin 	ANNOUNCE(local, vm, VM_FREE, data, vm->disc);
15634f9b3eeSRoland Mainz 
1577c2fbfb3SApril Chin 	CLRINUSE(vd, inuse);
158da2e3ebdSchin 	return 0;
159da2e3ebdSchin }
160da2e3ebdSchin 
161da2e3ebdSchin #if __STD_C
lastresize(Vmalloc_t * vm,reg Void_t * data,size_t size,int type)162da2e3ebdSchin static Void_t* lastresize(Vmalloc_t* vm, reg Void_t* data, size_t size, int type )
163da2e3ebdSchin #else
164da2e3ebdSchin static Void_t* lastresize(vm, data, size, type )
165da2e3ebdSchin Vmalloc_t*	vm;
166da2e3ebdSchin reg Void_t*	data;
167da2e3ebdSchin size_t		size;
168da2e3ebdSchin int		type;
169da2e3ebdSchin #endif
170da2e3ebdSchin {
171da2e3ebdSchin 	reg Block_t*	tp;
172da2e3ebdSchin 	reg Seg_t	*seg;
173da2e3ebdSchin 	reg size_t	oldsize;
174da2e3ebdSchin 	reg ssize_t	s, ds;
175da2e3ebdSchin 	reg Vmdata_t*	vd = vm->data;
1767c2fbfb3SApril Chin 	reg int		local, inuse;
177da2e3ebdSchin 	reg Void_t*	addr;
178da2e3ebdSchin 	Void_t*		orgdata = NIL(Void_t*);
179da2e3ebdSchin 	size_t		orgsize = 0;
180da2e3ebdSchin 
1817c2fbfb3SApril Chin 	SETINUSE(vd, inuse);
182da2e3ebdSchin 	if(!data)
183da2e3ebdSchin 	{	oldsize = 0;
184da2e3ebdSchin 		data = lastalloc(vm,size);
185da2e3ebdSchin 		goto done;
186da2e3ebdSchin 	}
187da2e3ebdSchin 	if(size <= 0)
188da2e3ebdSchin 	{	(void)lastfree(vm,data);
1897c2fbfb3SApril Chin 		CLRINUSE(vd, inuse);
190da2e3ebdSchin 		return NIL(Void_t*);
191da2e3ebdSchin 	}
192da2e3ebdSchin 
193da2e3ebdSchin 	if(!(local = vd->mode&VM_TRUST))
194da2e3ebdSchin 	{	GETLOCAL(vd, local);
195da2e3ebdSchin 		if(ISLOCK(vd, local))
1967c2fbfb3SApril Chin 		{	CLRINUSE(vd, inuse);
197da2e3ebdSchin 			return NIL(Void_t*);
1987c2fbfb3SApril Chin 		}
199da2e3ebdSchin 		SETLOCK(vd, local);
200da2e3ebdSchin 		orgdata = data;
201da2e3ebdSchin 		orgsize = size;
202da2e3ebdSchin 	}
203da2e3ebdSchin 
204da2e3ebdSchin 	if(data == (Void_t*)vd->free)
205da2e3ebdSchin 		seg = vd->seg;
206da2e3ebdSchin 	else
207da2e3ebdSchin 	{	/* see if it was one of ours */
208da2e3ebdSchin 		for(seg = vd->seg; seg; seg = seg->next)
209da2e3ebdSchin 			if(data >= seg->addr && data < (Void_t*)seg->baddr)
210da2e3ebdSchin 				break;
211da2e3ebdSchin 		if(!seg || (VLONG(data)%ALIGN) != 0 ||
212da2e3ebdSchin 		   (seg->last && (Vmuchar_t*)data > (Vmuchar_t*)seg->last) )
213da2e3ebdSchin 		{	CLRLOCK(vd,0);
2147c2fbfb3SApril Chin 			CLRINUSE(vd, inuse);
215da2e3ebdSchin 			return NIL(Void_t*);
216da2e3ebdSchin 		}
217da2e3ebdSchin 	}
218da2e3ebdSchin 
219da2e3ebdSchin 	/* set 's' to be the current available space */
220da2e3ebdSchin 	if(data != seg->last)
221da2e3ebdSchin 	{	if(seg->last && (Vmuchar_t*)data < (Vmuchar_t*)seg->last)
222da2e3ebdSchin 			oldsize = (Vmuchar_t*)seg->last - (Vmuchar_t*)data;
223da2e3ebdSchin 		else	oldsize = (Vmuchar_t*)BLOCK(seg->baddr) - (Vmuchar_t*)data;
224da2e3ebdSchin 		s = -1;
225da2e3ebdSchin 	}
226da2e3ebdSchin 	else
227da2e3ebdSchin 	{	s = (Vmuchar_t*)BLOCK(seg->baddr) - (Vmuchar_t*)data;
228da2e3ebdSchin 		if(!(tp = seg->free) )
229da2e3ebdSchin 			oldsize = s;
230da2e3ebdSchin 		else
231da2e3ebdSchin 		{	oldsize = (Vmuchar_t*)tp - (Vmuchar_t*)data;
232da2e3ebdSchin 			seg->free = NIL(Block_t*);
233da2e3ebdSchin 		}
234da2e3ebdSchin 	}
235da2e3ebdSchin 
236da2e3ebdSchin 	size = size < ALIGN ? ALIGN : ROUND(size,ALIGN);
237da2e3ebdSchin 	if(s < 0 || (ssize_t)size > s)
238da2e3ebdSchin 	{	if(s >= 0) /* amount to extend */
239da2e3ebdSchin 		{	ds = size-s; ds = ROUND(ds,vd->incr);
240da2e3ebdSchin 			addr = (*vm->disc->memoryf)(vm, seg->addr, seg->extent,
241da2e3ebdSchin 						    seg->extent+ds, vm->disc);
242da2e3ebdSchin 			if(addr == seg->addr)
243da2e3ebdSchin 			{	s += ds;
244da2e3ebdSchin 				seg->size += ds;
245da2e3ebdSchin 				seg->extent += ds;
246da2e3ebdSchin 				seg->baddr += ds;
247da2e3ebdSchin 				SIZE(BLOCK(seg->baddr)) = BUSY;
248da2e3ebdSchin 			}
249da2e3ebdSchin 			else	goto do_alloc;
250da2e3ebdSchin 		}
251da2e3ebdSchin 		else
252da2e3ebdSchin 		{ do_alloc:
253da2e3ebdSchin 			if(!(type&(VM_RSMOVE|VM_RSCOPY)) )
254da2e3ebdSchin 				data = NIL(Void_t*);
255da2e3ebdSchin 			else
256da2e3ebdSchin 			{	tp = vd->free;
257da2e3ebdSchin 				if(!(addr = KPVALLOC(vm,size,lastalloc)) )
258da2e3ebdSchin 				{	vd->free = tp;
259da2e3ebdSchin 					data = NIL(Void_t*);
260da2e3ebdSchin 				}
261da2e3ebdSchin 				else
262da2e3ebdSchin 				{	if(type&VM_RSCOPY)
263da2e3ebdSchin 					{	ds = oldsize < size ? oldsize : size;
264da2e3ebdSchin 						memcpy(addr, data, ds);
265da2e3ebdSchin 					}
266da2e3ebdSchin 
267da2e3ebdSchin 					if(s >= 0 && seg != vd->seg)
268da2e3ebdSchin 					{	tp = (Block_t*)data;
269da2e3ebdSchin 						SEG(tp) = seg;
270da2e3ebdSchin 						SIZE(tp) = s - sizeof(Head_t);
271da2e3ebdSchin 						seg->free = tp;
272da2e3ebdSchin 					}
273da2e3ebdSchin 
274da2e3ebdSchin 					/* new block and size */
275da2e3ebdSchin 					data = addr;
276da2e3ebdSchin 					seg = vd->seg;
277da2e3ebdSchin 					s = (Vmuchar_t*)BLOCK(seg->baddr) -
278da2e3ebdSchin 					    (Vmuchar_t*)data;
279da2e3ebdSchin 					seg->free = NIL(Block_t*);
280da2e3ebdSchin 				}
281da2e3ebdSchin 			}
282da2e3ebdSchin 		}
283da2e3ebdSchin 	}
284da2e3ebdSchin 
285da2e3ebdSchin 	if(data)
286da2e3ebdSchin 	{	if(s >= (ssize_t)(size+sizeof(Head_t)) )
287da2e3ebdSchin 		{	tp = (Block_t*)((Vmuchar_t*)data + size);
288da2e3ebdSchin 			SEG(tp) = seg;
289da2e3ebdSchin 			SIZE(tp) = (s - size) - sizeof(Head_t);
290da2e3ebdSchin 			seg->free = tp;
291da2e3ebdSchin 		}
292da2e3ebdSchin 
293da2e3ebdSchin 		vd->free = seg->last = (Block_t*)data;
294da2e3ebdSchin 
295da2e3ebdSchin 		if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
296da2e3ebdSchin 			(*_Vmtrace)(vm,(Vmuchar_t*)orgdata,(Vmuchar_t*)data,orgsize,0);
297da2e3ebdSchin 	}
298da2e3ebdSchin 
299da2e3ebdSchin 	CLRLOCK(vd, local);
300da2e3ebdSchin 	ANNOUNCE(local, vm, VM_RESIZE, data, vm->disc);
301da2e3ebdSchin 
302da2e3ebdSchin done:	if(data && (type&VM_RSZERO) && size > oldsize)
303da2e3ebdSchin 		memset((Void_t*)((Vmuchar_t*)data + oldsize), 0, size-oldsize);
304da2e3ebdSchin 
3057c2fbfb3SApril Chin 	CLRINUSE(vd, inuse);
306da2e3ebdSchin 	return data;
307da2e3ebdSchin }
308da2e3ebdSchin 
309da2e3ebdSchin 
310da2e3ebdSchin #if __STD_C
lastaddr(Vmalloc_t * vm,Void_t * addr)311da2e3ebdSchin static long lastaddr(Vmalloc_t* vm, Void_t* addr)
312da2e3ebdSchin #else
313da2e3ebdSchin static long lastaddr(vm, addr)
314da2e3ebdSchin Vmalloc_t*	vm;
315da2e3ebdSchin Void_t*		addr;
316da2e3ebdSchin #endif
317da2e3ebdSchin {
318da2e3ebdSchin 	reg Vmdata_t*	vd = vm->data;
319da2e3ebdSchin 
320da2e3ebdSchin 	if(!(vd->mode&VM_TRUST) && ISLOCK(vd,0))
321da2e3ebdSchin 		return -1L;
322da2e3ebdSchin 	if(!vd->free || addr < (Void_t*)vd->free || addr >= (Void_t*)vd->seg->baddr)
323da2e3ebdSchin 		return -1L;
324da2e3ebdSchin 	else	return (Vmuchar_t*)addr - (Vmuchar_t*)vd->free;
325da2e3ebdSchin }
326da2e3ebdSchin 
327da2e3ebdSchin #if __STD_C
lastsize(Vmalloc_t * vm,Void_t * addr)328da2e3ebdSchin static long lastsize(Vmalloc_t* vm, Void_t* addr)
329da2e3ebdSchin #else
330da2e3ebdSchin static long lastsize(vm, addr)
331da2e3ebdSchin Vmalloc_t*	vm;
332da2e3ebdSchin Void_t*		addr;
333da2e3ebdSchin #endif
334da2e3ebdSchin {
335da2e3ebdSchin 	reg Vmdata_t*	vd = vm->data;
336da2e3ebdSchin 
337da2e3ebdSchin 	if(!(vd->mode&VM_TRUST) && ISLOCK(vd,0))
338da2e3ebdSchin 		return -1L;
339da2e3ebdSchin 	if(!vd->free || addr != (Void_t*)vd->free )
340da2e3ebdSchin 		return -1L;
341da2e3ebdSchin 	else if(vd->seg->free)
342da2e3ebdSchin 		return (Vmuchar_t*)vd->seg->free - (Vmuchar_t*)addr;
343da2e3ebdSchin 	else	return (Vmuchar_t*)vd->seg->baddr - (Vmuchar_t*)addr - sizeof(Head_t);
344da2e3ebdSchin }
345da2e3ebdSchin 
346da2e3ebdSchin #if __STD_C
lastcompact(Vmalloc_t * vm)347da2e3ebdSchin static int lastcompact(Vmalloc_t* vm)
348da2e3ebdSchin #else
349da2e3ebdSchin static int lastcompact(vm)
350da2e3ebdSchin Vmalloc_t*	vm;
351da2e3ebdSchin #endif
352da2e3ebdSchin {
353da2e3ebdSchin 	reg Block_t*	fp;
354da2e3ebdSchin 	reg Seg_t	*seg, *next;
355da2e3ebdSchin 	reg size_t	s;
356da2e3ebdSchin 	reg Vmdata_t*	vd = vm->data;
3577c2fbfb3SApril Chin 	reg int		inuse;
358da2e3ebdSchin 
3597c2fbfb3SApril Chin 	SETINUSE(vd, inuse);
360da2e3ebdSchin 	if(!(vd->mode&VM_TRUST))
361da2e3ebdSchin 	{	if(ISLOCK(vd,0))
3627c2fbfb3SApril Chin 		{	CLRINUSE(vd, inuse);
363da2e3ebdSchin 			return -1;
3647c2fbfb3SApril Chin 		}
365da2e3ebdSchin 		SETLOCK(vd,0);
366da2e3ebdSchin 	}
367da2e3ebdSchin 
368da2e3ebdSchin 	for(seg = vd->seg; seg; seg = next)
369da2e3ebdSchin 	{	next = seg->next;
370da2e3ebdSchin 
371da2e3ebdSchin 		if(!(fp = seg->free))
372da2e3ebdSchin 			continue;
373da2e3ebdSchin 
374da2e3ebdSchin 		seg->free = NIL(Block_t*);
375da2e3ebdSchin 		if(seg->size == (s = SIZE(fp)&~BITS))
376da2e3ebdSchin 			s = seg->extent;
377da2e3ebdSchin 		else	s += sizeof(Head_t);
378da2e3ebdSchin 
379da2e3ebdSchin 		if((*_Vmtruncate)(vm,seg,s,1) == s)
380da2e3ebdSchin 			seg->free = fp;
381da2e3ebdSchin 	}
382da2e3ebdSchin 
383da2e3ebdSchin 	if((vd->mode&VM_TRACE) && _Vmtrace)
384da2e3ebdSchin 		(*_Vmtrace)(vm,(Vmuchar_t*)0,(Vmuchar_t*)0,0,0);
385da2e3ebdSchin 
386da2e3ebdSchin 	CLRLOCK(vd,0);
3877c2fbfb3SApril Chin 	CLRINUSE(vd, inuse);
388da2e3ebdSchin 	return 0;
389da2e3ebdSchin }
390da2e3ebdSchin 
391da2e3ebdSchin #if __STD_C
lastalign(Vmalloc_t * vm,size_t size,size_t align)392da2e3ebdSchin static Void_t* lastalign(Vmalloc_t* vm, size_t size, size_t align)
393da2e3ebdSchin #else
394da2e3ebdSchin static Void_t* lastalign(vm, size, align)
395da2e3ebdSchin Vmalloc_t*	vm;
396da2e3ebdSchin size_t		size;
397da2e3ebdSchin size_t		align;
398da2e3ebdSchin #endif
399da2e3ebdSchin {
400da2e3ebdSchin 	reg Vmuchar_t*	data;
401da2e3ebdSchin 	reg Seg_t*	seg;
402da2e3ebdSchin 	reg Block_t*	next;
4037c2fbfb3SApril Chin 	reg int		local, inuse;
404da2e3ebdSchin 	reg size_t	s, orgsize = 0, orgalign = 0;
405da2e3ebdSchin 	reg Vmdata_t*	vd = vm->data;
406da2e3ebdSchin 
407da2e3ebdSchin 	if(size <= 0 || align <= 0)
408da2e3ebdSchin 		return NIL(Void_t*);
409da2e3ebdSchin 
4107c2fbfb3SApril Chin 	SETINUSE(vd, inuse);
411da2e3ebdSchin 	if(!(local = vd->mode&VM_TRUST) )
412da2e3ebdSchin 	{	GETLOCAL(vd,local);
413da2e3ebdSchin 		if(ISLOCK(vd,local) )
4147c2fbfb3SApril Chin 		{	CLRINUSE(vd, inuse);
415da2e3ebdSchin 			return NIL(Void_t*);
4167c2fbfb3SApril Chin 		}
417da2e3ebdSchin 		SETLOCK(vd,local);
418da2e3ebdSchin 		orgsize = size;
419da2e3ebdSchin 		orgalign = align;
420da2e3ebdSchin 	}
421da2e3ebdSchin 
422da2e3ebdSchin 	size = size <= TINYSIZE ? TINYSIZE : ROUND(size,ALIGN);
423da2e3ebdSchin 	align = MULTIPLE(align,ALIGN);
424da2e3ebdSchin 
425da2e3ebdSchin 	s = size + align;
426da2e3ebdSchin 	if(!(data = (Vmuchar_t*)KPVALLOC(vm,s,lastalloc)) )
427da2e3ebdSchin 		goto done;
428da2e3ebdSchin 
429da2e3ebdSchin 	/* find the segment containing this block */
430da2e3ebdSchin 	for(seg = vd->seg; seg; seg = seg->next)
431da2e3ebdSchin 		if(seg->last == (Block_t*)data)
432da2e3ebdSchin 			break;
433da2e3ebdSchin 	/**/ASSERT(seg);
434da2e3ebdSchin 
435da2e3ebdSchin 	/* get a suitably aligned address */
436da2e3ebdSchin 	if((s = (size_t)(VLONG(data)%align)) != 0)
437da2e3ebdSchin 		data += align-s; /**/ASSERT((VLONG(data)%align) == 0);
438da2e3ebdSchin 
439da2e3ebdSchin 	/* free the unused tail */
440da2e3ebdSchin 	next = (Block_t*)(data+size);
441da2e3ebdSchin 	if((s = (seg->baddr - (Vmuchar_t*)next)) >= sizeof(Block_t))
442da2e3ebdSchin 	{	SEG(next) = seg;
443da2e3ebdSchin 		SIZE(next) = s - sizeof(Head_t);
444da2e3ebdSchin 		seg->free = next;
445da2e3ebdSchin 	}
446da2e3ebdSchin 
447da2e3ebdSchin 	vd->free = seg->last = (Block_t*)data;
448da2e3ebdSchin 
449da2e3ebdSchin 	if(!local && !(vd->mode&VM_TRUST) && _Vmtrace && (vd->mode&VM_TRACE) )
450da2e3ebdSchin 		(*_Vmtrace)(vm,NIL(Vmuchar_t*),data,orgsize,orgalign);
451da2e3ebdSchin 
452da2e3ebdSchin done:
453da2e3ebdSchin 	CLRLOCK(vd,local);
454da2e3ebdSchin 	ANNOUNCE(local, vm, VM_ALLOC, (Void_t*)data, vm->disc);
455da2e3ebdSchin 
4567c2fbfb3SApril Chin 	CLRINUSE(vd, inuse);
457da2e3ebdSchin 	return (Void_t*)data;
458da2e3ebdSchin }
459da2e3ebdSchin 
460da2e3ebdSchin /* Public method for free-1 allocation */
461da2e3ebdSchin static Vmethod_t _Vmlast =
462da2e3ebdSchin {
463da2e3ebdSchin 	lastalloc,
464da2e3ebdSchin 	lastresize,
465da2e3ebdSchin 	lastfree,
466da2e3ebdSchin 	lastaddr,
467da2e3ebdSchin 	lastsize,
468da2e3ebdSchin 	lastcompact,
469da2e3ebdSchin 	lastalign,
470da2e3ebdSchin 	VM_MTLAST
471da2e3ebdSchin };
472da2e3ebdSchin 
473da2e3ebdSchin __DEFINE__(Vmethod_t*,Vmlast,&_Vmlast);
474da2e3ebdSchin 
475da2e3ebdSchin #ifdef NoF
476da2e3ebdSchin NoF(vmlast)
477da2e3ebdSchin #endif
478da2e3ebdSchin 
479da2e3ebdSchin #endif
480