Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtksh / ksh93 / src / lib / libast / vmalloc / vmlast.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
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
22  */
23 /* $XConsortium: vmlast.c /main/2 1996/05/08 20:03:35 drk $ */
24 /***************************************************************
25 *                                                              *
26 *                      AT&T - PROPRIETARY                      *
27 *                                                              *
28 *         THIS IS PROPRIETARY SOURCE CODE LICENSED BY          *
29 *                          AT&T CORP.                          *
30 *                                                              *
31 *                Copyright (c) 1995 AT&T Corp.                 *
32 *                     All Rights Reserved                      *
33 *                                                              *
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        *
37 *                                                              *
38 *               This software was created by the               *
39 *           Software Engineering Research Department           *
40 *                    AT&T Bell Laboratories                    *
41 *                                                              *
42 *               For further information contact                *
43 *                     gsf@research.att.com                     *
44 *                                                              *
45 ***************************************************************/
46 #include        "vmhdr.h"
47
48 /*      Allocation with freeing and reallocing of last allocated block only.
49 **
50 **      Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94.
51 */
52
53 #if __STD_C
54 static Void_t* lastalloc(Vmalloc_t* vm, size_t size)
55 #else
56 static Void_t* lastalloc(vm, size)
57 Vmalloc_t*      vm;
58 size_t          size;
59 #endif
60 {
61         reg Block_t     *tp, *next;
62         reg Seg_t       *seg, *last;
63         reg size_t      s;
64         reg Vmdata_t*   vd = vm->data;
65         reg int         local;
66         size_t          orgsize;
67
68         if(!(local = vd->mode&VM_TRUST))
69         {       GETLOCAL(vd,local);
70                 if(ISLOCK(vd,local))
71                         return NIL(Void_t*);
72                 SETLOCK(vd,local);
73                 orgsize = size;
74         }
75
76         size = size < ALIGN ? ALIGN : ROUND(size,ALIGN);
77         for(;;)
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)
80                                 continue;
81                         if(last) /* move this segment to the front of the list */
82                         {       last->next = seg->next;
83                                 seg->next = vd->seg;
84                                 vd->seg = seg;
85                         }
86                         goto got_block;
87                 }
88
89                 /* there is no usable free space in region, try extending */
90                 if((tp = (*_Vmextend)(vm,size,NIL(Vmsearch_f))) )
91                 {       seg = SEG(tp);
92                         goto got_block;
93                 }
94                 else if(vd->mode&VM_AGAIN)
95                         vd->mode &= ~VM_AGAIN;
96                 else    goto done;
97         }
98
99 got_block:
100         if((s = SIZE(tp)) >= size)
101         {       /* there is some more space */
102                 next = (Block_t*)((uchar*)tp+size);
103                 SIZE(next) = s - size;
104                 SEG(next) = seg;
105                 seg->free = next;
106         }
107         else    seg->free = NIL(Block_t*);
108
109         vd->pool += 1;
110         vd->free  = tp;
111
112         if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
113                 (*_Vmtrace)(vm, NIL(uchar*), (uchar*)tp, orgsize);
114
115 done:
116         CLRLOCK(vd,local);
117         return (Void_t*)tp;
118 }
119
120 #if __STD_C
121 static int lastfree(Vmalloc_t* vm, reg Void_t* data )
122 #else
123 static int lastfree(vm, data)
124 Vmalloc_t*      vm;
125 reg Void_t*     data;
126 #endif
127 {
128         reg Seg_t*      seg;
129         reg Block_t*    fp;
130         reg size_t      s;
131         reg Vmdata_t*   vd = vm->data;
132         reg int         local;
133
134         if(!data)
135                 return 0;
136         if(!(local = vd->mode&VM_TRUST) )
137         {       if(ISLOCK(vd,0))
138                         return -1;
139                 SETLOCK(vd,0);
140         }
141         if(data != (Void_t*)vd->free)
142         {       if(!local && vm->disc->exceptf)
143                         (void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
144                 CLRLOCK(vd,0);
145                 return -1;
146         }
147
148         seg = vd->seg;
149         if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
150         {       if(seg->free )
151                         s = (uchar*)(seg->free) - (uchar*)data;
152                 else    s = (uchar*)BLOCK(seg->baddr) - (uchar*)data;
153                 (*_Vmtrace)(vm, (uchar*)data, NIL(uchar*), s);
154         }
155
156         vd->free = NIL(Block_t*);
157         fp = (Block_t*)data;
158         SEG(fp)  = seg;
159         SIZE(fp) = ((uchar*)BLOCK(seg->baddr) - (uchar*)data) - sizeof(Head_t);
160         seg->free = fp;
161         vd->pool -= 1;
162
163         CLRLOCK(vd,0);
164         return 0;
165 }
166
167 #if __STD_C
168 static Void_t* lastresize(Vmalloc_t* vm, reg Void_t* data, size_t size, int flags )
169 #else
170 static Void_t* lastresize(vm, data, size, flags )
171 Vmalloc_t*      vm;
172 reg Void_t*     data;
173 size_t          size;
174 int             flags;
175 #endif
176 {
177         reg Block_t*    tp;
178         reg Seg_t*      seg;
179         reg size_t      oldsize, s;
180         reg Vmdata_t*   vd = vm->data;
181         reg int         local;
182         Void_t*         orgdata;
183         size_t          orgsize;
184
185         if(!data)
186         {       if((data = lastalloc(vm,size)) && (flags & VM_RSZERO))
187                 {       reg int*        nd;
188                         s = (size+sizeof(int)-1)/sizeof(int);
189                         for(nd = (int*)data; s-- > 0; )
190                                 *nd++ = 0;
191                 }
192                 return data;
193         }
194         else if(size <= 0)
195         {       (void)lastfree(vm,data);
196                 return NIL(Void_t*);
197         }
198
199         if(!(local = vd->mode&VM_TRUST))
200         {       if(ISLOCK(vd,0))
201                         return NIL(Void_t*);
202                 SETLOCK(vd,0);
203                 orgdata = data;
204                 orgsize = size;
205         }
206
207         if(data != (Void_t*)vd->free)
208         {       if(!local && vm->disc->exceptf)
209                         (void)(*vm->disc->exceptf)(vm,VM_BADADDR,data,vm->disc);
210                 CLRLOCK(vd,0);
211                 return NIL(Void_t*);
212         }
213
214         /* current available space */
215         seg = vd->seg;
216         s = (uchar*)BLOCK(seg->baddr) - (uchar*)data;
217         if(!(tp = seg->free) )
218                 oldsize = s;
219         else
220         {       oldsize = (uchar*)tp - (uchar*)data;
221                 seg->free = NIL(Block_t*);
222         }
223
224         if((size = size < ALIGN ? ALIGN : ROUND(size,ALIGN)) > s)
225         {       reg size_t      incr;
226                 reg Void_t*     addr = seg->addr;
227                 reg Vmemory_f   memoryf = vm->disc->memoryf;
228
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)
232                 {       s += incr;
233                         seg->size += incr;
234                         seg->extent += incr;
235                         seg->baddr += incr;
236                         SIZE(BLOCK(seg->baddr)) = BUSY;
237                 }
238                 else if(!(flags & VM_RSFREE))
239                         data = NIL(Void_t*);
240                 else if(!(addr = KPVALLOC(vm,size,lastalloc)) )
241                 {       vd->free = (Block_t*)data;
242                         data = NIL(Void_t*);
243                 }
244                 else
245                 {       if(flags & VM_RSZERO)
246                         {       reg int*        di;
247                                 reg size_t      ni;
248                                 ni = (size-oldsize+sizeof(int)-1)/sizeof(int);
249                                 for(di = (int*)((char*)data+oldsize); ni-- > 0; )
250                                         *di++ = 0;
251                         }
252
253                         if(flags & VM_RSCOPY)
254                         {       reg int *od = (int*)data, *nd = (int*)addr;
255                                 for(oldsize /= sizeof(int); oldsize-- > 0; )
256                                         *nd++ = *od++;
257                         }
258
259                         if(seg != vd->seg)
260                         {       tp = (Block_t*)data;
261                                 SEG(tp) = seg;
262                                 SIZE(tp) = s - sizeof(Head_t);
263                                 seg->free = tp;
264                         }
265
266                         /* new block and size */
267                         data = addr;
268                         seg = vd->seg;
269                         s = (uchar*)BLOCK(seg->baddr) - (uchar*)data;
270                         seg->free = NIL(Block_t*);
271                 }
272         }
273
274         if(data)
275         {       if(s >= size+sizeof(Head_t))
276                 {       tp = (Block_t*)((uchar*)data + size);
277                         SEG(tp) = seg;
278                         SIZE(tp) = (s - size) - sizeof(Head_t);
279                         seg->free = tp;
280                 }
281
282                 vd->free = (Block_t*)data;
283
284                 if(!local && (vd->mode&VM_TRACE) && _Vmtrace)
285                         (*_Vmtrace)(vm,(uchar*)orgdata,(uchar*)data,orgsize);
286         }
287
288         CLRLOCK(vd,0);
289         return data;
290 }
291
292
293 #if __STD_C
294 static long lastaddr(Vmalloc_t* vm, Void_t* addr)
295 #else
296 static long lastaddr(vm, addr)
297 Vmalloc_t*      vm;
298 Void_t*         addr;
299 #endif
300 {
301         reg Vmdata_t*   vd = vm->data;
302
303         if(!(vd->mode&VM_TRUST) && ISLOCK(vd,0))
304                 return -1L;
305         if(!vd->free || addr < (Void_t*)vd->free || addr >= (Void_t*)vd->seg->baddr)
306                 return -1L;
307         else    return (uchar*)addr - (uchar*)vd->free;
308 }
309
310 #if __STD_C
311 static long lastsize(Vmalloc_t* vm, Void_t* addr)
312 #else
313 static long lastsize(vm, addr)
314 Vmalloc_t*      vm;
315 Void_t*         addr;
316 #endif
317 {
318         reg Vmdata_t*   vd = vm->data;
319
320         if(!(vd->mode&VM_TRUST) && ISLOCK(vd,0))
321                 return -1L;
322         if(!vd->free || addr != (Void_t*)vd->free )
323                 return -1L;
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);
327 }
328
329 #if __STD_C
330 static lastcompact(Vmalloc_t* vm)
331 #else
332 static lastcompact(vm)
333 Vmalloc_t*      vm;
334 #endif
335 {
336         reg Block_t*    fp;
337         reg Seg_t       *seg, *next;
338         reg size_t      s;
339         reg Vmdata_t*   vd = vm->data;
340
341         if(!(vd->mode&VM_TRUST))
342         {       if(ISLOCK(vd,0))
343                         return -1;
344                 SETLOCK(vd,0);
345         }
346
347         for(seg = vd->seg; seg; )
348         {       next = seg->next;
349
350                 if(!(fp = seg->free))
351                         goto loop;
352
353                 seg->free = NIL(Block_t*);
354                 if(seg->size == (s = SIZE(fp)&~BITS))
355                         s = seg->extent;
356                 else    s += sizeof(Head_t);
357
358                 if((*_Vmtruncate)(vm,seg,s,1) < 0)
359                         seg->free = fp;
360         loop:
361                 seg = next;
362         }
363
364         CLRLOCK(vd,0);
365         return 0;
366 }
367
368 #if __STD_C
369 static Void_t* lastalign(Vmalloc_t* vm, size_t size, size_t align)
370 #else
371 static Void_t* lastalign(vm, size, align)
372 Vmalloc_t*      vm;
373 size_t          size;
374 size_t          align;
375 #endif
376 {
377         NOTUSED(vm);
378         NOTUSED(size);
379         NOTUSED(align);
380         return NIL(Void_t*);
381 }
382
383 /* Public method for free-1 allocation */
384 Vmethod_t _Vmlast =
385 {
386         lastalloc,
387         lastresize,
388         lastfree,
389         lastaddr,
390         lastsize,
391         lastcompact,
392         lastalign,
393         VM_MTLAST
394 };