2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: vmlast.c /main/2 1996/05/08 20:03:35 drk $ */
24 /***************************************************************
26 * AT&T - PROPRIETARY *
28 * THIS IS PROPRIETARY SOURCE CODE LICENSED BY *
31 * Copyright (c) 1995 AT&T Corp. *
32 * All Rights Reserved *
34 * This software is licensed by AT&T Corp. *
35 * under the terms and conditions of the license in *
36 * http://www.research.att.com/orgs/ssr/book/reuse *
38 * This software was created by the *
39 * Software Engineering Research Department *
40 * AT&T Bell Laboratories *
42 * For further information contact *
43 * gsf@research.att.com *
45 ***************************************************************/
48 /* Allocation with freeing and reallocing of last allocated block only.
50 ** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
54 static Void_t* lastalloc(Vmalloc_t* vm, size_t size)
56 static Void_t* lastalloc(vm, size)
61 reg Block_t *tp, *next;
62 reg Seg_t *seg, *last;
64 reg Vmdata_t* vd = vm->data;
68 if(!(local = vd->mode&VM_TRUST))
76 size = size < ALIGN ? ALIGN : ROUND(size,ALIGN);
78 { for(last = NIL(Seg_t*), seg = vd->seg; seg; last = seg, seg = seg->next)
79 { if(!(tp = seg->free) || (SIZE(tp)+sizeof(Head_t)) < size)
81 if(last) /* move this segment to the front of the list */
82 { last->next = seg->next;
89 /* there is no usable free space in region, try extending */
90 if((tp = (*_Vmextend)(vm,size,NIL(Vmsearch_f))) )
94 else if(vd->mode&VM_AGAIN)
95 vd->mode &= ~VM_AGAIN;
100 if((s = SIZE(tp)) >= size)
101 { /* there is some more space */
102 next = (Block_t*)((uchar*)tp+size);
103 SIZE(next) = s - size;
107 else seg->free = NIL(Block_t*);
112 if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
113 (*_Vmtrace)(vm, NIL(uchar*), (uchar*)tp, orgsize);
121 static int lastfree(Vmalloc_t* vm, reg Void_t* data )
123 static int lastfree(vm, data)
131 reg Vmdata_t* vd = vm->data;
136 if(!(local = vd->mode&VM_TRUST) )
141 if(data != (Void_t*)vd->free)
142 { if(!local && vm->disc->exceptf)
143 (void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
149 if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
151 s = (uchar*)(seg->free) - (uchar*)data;
152 else s = (uchar*)BLOCK(seg->baddr) - (uchar*)data;
153 (*_Vmtrace)(vm, (uchar*)data, NIL(uchar*), s);
156 vd->free = NIL(Block_t*);
159 SIZE(fp) = ((uchar*)BLOCK(seg->baddr) - (uchar*)data) - sizeof(Head_t);
168 static Void_t* lastresize(Vmalloc_t* vm, reg Void_t* data, size_t size, int flags )
170 static Void_t* lastresize(vm, data, size, flags )
179 reg size_t oldsize, s;
180 reg Vmdata_t* vd = vm->data;
186 { if((data = lastalloc(vm,size)) && (flags & VM_RSZERO))
188 s = (size+sizeof(int)-1)/sizeof(int);
189 for(nd = (int*)data; s-- > 0; )
195 { (void)lastfree(vm,data);
199 if(!(local = vd->mode&VM_TRUST))
207 if(data != (Void_t*)vd->free)
208 { if(!local && vm->disc->exceptf)
209 (void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
214 /* current available space */
216 s = (uchar*)BLOCK(seg->baddr) - (uchar*)data;
217 if(!(tp = seg->free) )
220 { oldsize = (uchar*)tp - (uchar*)data;
221 seg->free = NIL(Block_t*);
224 if((size = size < ALIGN ? ALIGN : ROUND(size,ALIGN)) > s)
226 reg Void_t* addr = seg->addr;
227 reg Vmemory_f memoryf = vm->disc->memoryf;
229 /* amount to extend */
230 incr = size-s; incr = ROUND(incr,vd->incr);
231 if((*memoryf)(vm,addr,seg->extent,seg->extent+incr,vm->disc) == addr)
236 SIZE(BLOCK(seg->baddr)) = BUSY;
238 else if(!(flags & VM_RSFREE))
240 else if(!(addr = KPVALLOC(vm,size,lastalloc)) )
241 { vd->free = (Block_t*)data;
245 { if(flags & VM_RSZERO)
248 ni = (size-oldsize+sizeof(int)-1)/sizeof(int);
249 for(di = (int*)((char*)data+oldsize); ni-- > 0; )
253 if(flags & VM_RSCOPY)
254 { reg int *od = (int*)data, *nd = (int*)addr;
255 for(oldsize /= sizeof(int); oldsize-- > 0; )
260 { tp = (Block_t*)data;
262 SIZE(tp) = s - sizeof(Head_t);
266 /* new block and size */
269 s = (uchar*)BLOCK(seg->baddr) - (uchar*)data;
270 seg->free = NIL(Block_t*);
275 { if(s >= size+sizeof(Head_t))
276 { tp = (Block_t*)((uchar*)data + size);
278 SIZE(tp) = (s - size) - sizeof(Head_t);
282 vd->free = (Block_t*)data;
284 if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
285 (*_Vmtrace)(vm,(uchar*)orgdata,(uchar*)data,orgsize);
294 static long lastaddr(Vmalloc_t* vm, Void_t* addr)
296 static long lastaddr(vm, addr)
301 reg Vmdata_t* vd = vm->data;
303 if(!(vd->mode&VM_TRUST) && ISLOCK(vd,0))
305 if(!vd->free || addr < (Void_t*)vd->free || addr >= (Void_t*)vd->seg->baddr)
307 else return (uchar*)addr - (uchar*)vd->free;
311 static long lastsize(Vmalloc_t* vm, Void_t* addr)
313 static long lastsize(vm, addr)
318 reg Vmdata_t* vd = vm->data;
320 if(!(vd->mode&VM_TRUST) && ISLOCK(vd,0))
322 if(!vd->free || addr != (Void_t*)vd->free )
324 else if(vd->seg->free)
325 return (uchar*)vd->seg->free - (uchar*)addr;
326 else return (uchar*)vd->seg->baddr - (uchar*)addr - sizeof(Head_t);
330 static lastcompact(Vmalloc_t* vm)
332 static lastcompact(vm)
337 reg Seg_t *seg, *next;
339 reg Vmdata_t* vd = vm->data;
341 if(!(vd->mode&VM_TRUST))
347 for(seg = vd->seg; seg; )
350 if(!(fp = seg->free))
353 seg->free = NIL(Block_t*);
354 if(seg->size == (s = SIZE(fp)&~BITS))
356 else s += sizeof(Head_t);
358 if((*_Vmtruncate)(vm,seg,s,1) < 0)
369 static Void_t* lastalign(Vmalloc_t* vm, size_t size, size_t align)
371 static Void_t* lastalign(vm, size, align)
383 /* Public method for free-1 allocation */