xref: /dflybsd-src/contrib/gcc-4.7/libiberty/objalloc.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* objalloc.c -- routines to allocate memory for objects
2*e4b17023SJohn Marino    Copyright 1997 Free Software Foundation, Inc.
3*e4b17023SJohn Marino    Written by Ian Lance Taylor, Cygnus Solutions.
4*e4b17023SJohn Marino 
5*e4b17023SJohn Marino This program is free software; you can redistribute it and/or modify it
6*e4b17023SJohn Marino under the terms of the GNU General Public License as published by the
7*e4b17023SJohn Marino Free Software Foundation; either version 2, or (at your option) any
8*e4b17023SJohn Marino later version.
9*e4b17023SJohn Marino 
10*e4b17023SJohn Marino This program is distributed in the hope that it will be useful,
11*e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
12*e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*e4b17023SJohn Marino GNU General Public License for more details.
14*e4b17023SJohn Marino 
15*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
16*e4b17023SJohn Marino along with this program; if not, write to the Free Software
17*e4b17023SJohn Marino Foundation, 51 Franklin Street - Fifth Floor,
18*e4b17023SJohn Marino Boston, MA 02110-1301, USA.  */
19*e4b17023SJohn Marino 
20*e4b17023SJohn Marino #include "config.h"
21*e4b17023SJohn Marino #include "ansidecl.h"
22*e4b17023SJohn Marino 
23*e4b17023SJohn Marino #include "objalloc.h"
24*e4b17023SJohn Marino 
25*e4b17023SJohn Marino /* Get a definition for NULL.  */
26*e4b17023SJohn Marino #include <stdio.h>
27*e4b17023SJohn Marino 
28*e4b17023SJohn Marino #if VMS
29*e4b17023SJohn Marino #include <stdlib.h>
30*e4b17023SJohn Marino #include <unixlib.h>
31*e4b17023SJohn Marino #else
32*e4b17023SJohn Marino 
33*e4b17023SJohn Marino /* Get a definition for size_t.  */
34*e4b17023SJohn Marino #include <stddef.h>
35*e4b17023SJohn Marino 
36*e4b17023SJohn Marino #ifdef HAVE_STDLIB_H
37*e4b17023SJohn Marino #include <stdlib.h>
38*e4b17023SJohn Marino #else
39*e4b17023SJohn Marino /* For systems with larger pointers than ints, this must be declared.  */
40*e4b17023SJohn Marino extern PTR malloc (size_t);
41*e4b17023SJohn Marino extern void free (PTR);
42*e4b17023SJohn Marino #endif
43*e4b17023SJohn Marino 
44*e4b17023SJohn Marino #endif
45*e4b17023SJohn Marino 
46*e4b17023SJohn Marino /* These routines allocate space for an object.  Freeing allocated
47*e4b17023SJohn Marino    space may or may not free all more recently allocated space.
48*e4b17023SJohn Marino 
49*e4b17023SJohn Marino    We handle large and small allocation requests differently.  If we
50*e4b17023SJohn Marino    don't have enough space in the current block, and the allocation
51*e4b17023SJohn Marino    request is for more than 512 bytes, we simply pass it through to
52*e4b17023SJohn Marino    malloc.  */
53*e4b17023SJohn Marino 
54*e4b17023SJohn Marino /* The objalloc structure is defined in objalloc.h.  */
55*e4b17023SJohn Marino 
56*e4b17023SJohn Marino /* This structure appears at the start of each chunk.  */
57*e4b17023SJohn Marino 
58*e4b17023SJohn Marino struct objalloc_chunk
59*e4b17023SJohn Marino {
60*e4b17023SJohn Marino   /* Next chunk.  */
61*e4b17023SJohn Marino   struct objalloc_chunk *next;
62*e4b17023SJohn Marino   /* If this chunk contains large objects, this is the value of
63*e4b17023SJohn Marino      current_ptr when this chunk was allocated.  If this chunk
64*e4b17023SJohn Marino      contains small objects, this is NULL.  */
65*e4b17023SJohn Marino   char *current_ptr;
66*e4b17023SJohn Marino };
67*e4b17023SJohn Marino 
68*e4b17023SJohn Marino /* The aligned size of objalloc_chunk.  */
69*e4b17023SJohn Marino 
70*e4b17023SJohn Marino #define CHUNK_HEADER_SIZE					\
71*e4b17023SJohn Marino   ((sizeof (struct objalloc_chunk) + OBJALLOC_ALIGN - 1)	\
72*e4b17023SJohn Marino    &~ (OBJALLOC_ALIGN - 1))
73*e4b17023SJohn Marino 
74*e4b17023SJohn Marino /* We ask for this much memory each time we create a chunk which is to
75*e4b17023SJohn Marino    hold small objects.  */
76*e4b17023SJohn Marino 
77*e4b17023SJohn Marino #define CHUNK_SIZE (4096 - 32)
78*e4b17023SJohn Marino 
79*e4b17023SJohn Marino /* A request for this amount or more is just passed through to malloc.  */
80*e4b17023SJohn Marino 
81*e4b17023SJohn Marino #define BIG_REQUEST (512)
82*e4b17023SJohn Marino 
83*e4b17023SJohn Marino /* Create an objalloc structure.  */
84*e4b17023SJohn Marino 
85*e4b17023SJohn Marino struct objalloc *
objalloc_create(void)86*e4b17023SJohn Marino objalloc_create (void)
87*e4b17023SJohn Marino {
88*e4b17023SJohn Marino   struct objalloc *ret;
89*e4b17023SJohn Marino   struct objalloc_chunk *chunk;
90*e4b17023SJohn Marino 
91*e4b17023SJohn Marino   ret = (struct objalloc *) malloc (sizeof *ret);
92*e4b17023SJohn Marino   if (ret == NULL)
93*e4b17023SJohn Marino     return NULL;
94*e4b17023SJohn Marino 
95*e4b17023SJohn Marino   ret->chunks = (PTR) malloc (CHUNK_SIZE);
96*e4b17023SJohn Marino   if (ret->chunks == NULL)
97*e4b17023SJohn Marino     {
98*e4b17023SJohn Marino       free (ret);
99*e4b17023SJohn Marino       return NULL;
100*e4b17023SJohn Marino     }
101*e4b17023SJohn Marino 
102*e4b17023SJohn Marino   chunk = (struct objalloc_chunk *) ret->chunks;
103*e4b17023SJohn Marino   chunk->next = NULL;
104*e4b17023SJohn Marino   chunk->current_ptr = NULL;
105*e4b17023SJohn Marino 
106*e4b17023SJohn Marino   ret->current_ptr = (char *) chunk + CHUNK_HEADER_SIZE;
107*e4b17023SJohn Marino   ret->current_space = CHUNK_SIZE - CHUNK_HEADER_SIZE;
108*e4b17023SJohn Marino 
109*e4b17023SJohn Marino   return ret;
110*e4b17023SJohn Marino }
111*e4b17023SJohn Marino 
112*e4b17023SJohn Marino /* Allocate space from an objalloc structure.  */
113*e4b17023SJohn Marino 
114*e4b17023SJohn Marino PTR
_objalloc_alloc(struct objalloc * o,unsigned long len)115*e4b17023SJohn Marino _objalloc_alloc (struct objalloc *o, unsigned long len)
116*e4b17023SJohn Marino {
117*e4b17023SJohn Marino   /* We avoid confusion from zero sized objects by always allocating
118*e4b17023SJohn Marino      at least 1 byte.  */
119*e4b17023SJohn Marino   if (len == 0)
120*e4b17023SJohn Marino     len = 1;
121*e4b17023SJohn Marino 
122*e4b17023SJohn Marino   len = (len + OBJALLOC_ALIGN - 1) &~ (OBJALLOC_ALIGN - 1);
123*e4b17023SJohn Marino 
124*e4b17023SJohn Marino   if (len <= o->current_space)
125*e4b17023SJohn Marino     {
126*e4b17023SJohn Marino       o->current_ptr += len;
127*e4b17023SJohn Marino       o->current_space -= len;
128*e4b17023SJohn Marino       return (PTR) (o->current_ptr - len);
129*e4b17023SJohn Marino     }
130*e4b17023SJohn Marino 
131*e4b17023SJohn Marino   if (len >= BIG_REQUEST)
132*e4b17023SJohn Marino     {
133*e4b17023SJohn Marino       char *ret;
134*e4b17023SJohn Marino       struct objalloc_chunk *chunk;
135*e4b17023SJohn Marino 
136*e4b17023SJohn Marino       ret = (char *) malloc (CHUNK_HEADER_SIZE + len);
137*e4b17023SJohn Marino       if (ret == NULL)
138*e4b17023SJohn Marino 	return NULL;
139*e4b17023SJohn Marino 
140*e4b17023SJohn Marino       chunk = (struct objalloc_chunk *) ret;
141*e4b17023SJohn Marino       chunk->next = (struct objalloc_chunk *) o->chunks;
142*e4b17023SJohn Marino       chunk->current_ptr = o->current_ptr;
143*e4b17023SJohn Marino 
144*e4b17023SJohn Marino       o->chunks = (PTR) chunk;
145*e4b17023SJohn Marino 
146*e4b17023SJohn Marino       return (PTR) (ret + CHUNK_HEADER_SIZE);
147*e4b17023SJohn Marino     }
148*e4b17023SJohn Marino   else
149*e4b17023SJohn Marino     {
150*e4b17023SJohn Marino       struct objalloc_chunk *chunk;
151*e4b17023SJohn Marino 
152*e4b17023SJohn Marino       chunk = (struct objalloc_chunk *) malloc (CHUNK_SIZE);
153*e4b17023SJohn Marino       if (chunk == NULL)
154*e4b17023SJohn Marino 	return NULL;
155*e4b17023SJohn Marino       chunk->next = (struct objalloc_chunk *) o->chunks;
156*e4b17023SJohn Marino       chunk->current_ptr = NULL;
157*e4b17023SJohn Marino 
158*e4b17023SJohn Marino       o->current_ptr = (char *) chunk + CHUNK_HEADER_SIZE;
159*e4b17023SJohn Marino       o->current_space = CHUNK_SIZE - CHUNK_HEADER_SIZE;
160*e4b17023SJohn Marino 
161*e4b17023SJohn Marino       o->chunks = (PTR) chunk;
162*e4b17023SJohn Marino 
163*e4b17023SJohn Marino       return objalloc_alloc (o, len);
164*e4b17023SJohn Marino     }
165*e4b17023SJohn Marino }
166*e4b17023SJohn Marino 
167*e4b17023SJohn Marino /* Free an entire objalloc structure.  */
168*e4b17023SJohn Marino 
169*e4b17023SJohn Marino void
objalloc_free(struct objalloc * o)170*e4b17023SJohn Marino objalloc_free (struct objalloc *o)
171*e4b17023SJohn Marino {
172*e4b17023SJohn Marino   struct objalloc_chunk *l;
173*e4b17023SJohn Marino 
174*e4b17023SJohn Marino   l = (struct objalloc_chunk *) o->chunks;
175*e4b17023SJohn Marino   while (l != NULL)
176*e4b17023SJohn Marino     {
177*e4b17023SJohn Marino       struct objalloc_chunk *next;
178*e4b17023SJohn Marino 
179*e4b17023SJohn Marino       next = l->next;
180*e4b17023SJohn Marino       free (l);
181*e4b17023SJohn Marino       l = next;
182*e4b17023SJohn Marino     }
183*e4b17023SJohn Marino 
184*e4b17023SJohn Marino   free (o);
185*e4b17023SJohn Marino }
186*e4b17023SJohn Marino 
187*e4b17023SJohn Marino /* Free a block from an objalloc structure.  This also frees all more
188*e4b17023SJohn Marino    recently allocated blocks.  */
189*e4b17023SJohn Marino 
190*e4b17023SJohn Marino void
objalloc_free_block(struct objalloc * o,PTR block)191*e4b17023SJohn Marino objalloc_free_block (struct objalloc *o, PTR block)
192*e4b17023SJohn Marino {
193*e4b17023SJohn Marino   struct objalloc_chunk *p, *small;
194*e4b17023SJohn Marino   char *b = (char *) block;
195*e4b17023SJohn Marino 
196*e4b17023SJohn Marino   /* First set P to the chunk which contains the block we are freeing,
197*e4b17023SJohn Marino      and set Q to the last small object chunk we see before P.  */
198*e4b17023SJohn Marino   small = NULL;
199*e4b17023SJohn Marino   for (p = (struct objalloc_chunk *) o->chunks; p != NULL; p = p->next)
200*e4b17023SJohn Marino     {
201*e4b17023SJohn Marino       if (p->current_ptr == NULL)
202*e4b17023SJohn Marino 	{
203*e4b17023SJohn Marino 	  if (b > (char *) p && b < (char *) p + CHUNK_SIZE)
204*e4b17023SJohn Marino 	    break;
205*e4b17023SJohn Marino 	  small = p;
206*e4b17023SJohn Marino 	}
207*e4b17023SJohn Marino       else
208*e4b17023SJohn Marino 	{
209*e4b17023SJohn Marino 	  if (b == (char *) p + CHUNK_HEADER_SIZE)
210*e4b17023SJohn Marino 	    break;
211*e4b17023SJohn Marino 	}
212*e4b17023SJohn Marino     }
213*e4b17023SJohn Marino 
214*e4b17023SJohn Marino   /* If we can't find the chunk, the caller has made a mistake.  */
215*e4b17023SJohn Marino   if (p == NULL)
216*e4b17023SJohn Marino     abort ();
217*e4b17023SJohn Marino 
218*e4b17023SJohn Marino   if (p->current_ptr == NULL)
219*e4b17023SJohn Marino     {
220*e4b17023SJohn Marino       struct objalloc_chunk *q;
221*e4b17023SJohn Marino       struct objalloc_chunk *first;
222*e4b17023SJohn Marino 
223*e4b17023SJohn Marino       /* The block is in a chunk containing small objects.  We can
224*e4b17023SJohn Marino 	 free every chunk through SMALL, because they have certainly
225*e4b17023SJohn Marino 	 been allocated more recently.  After SMALL, we will not see
226*e4b17023SJohn Marino 	 any chunks containing small objects; we can free any big
227*e4b17023SJohn Marino 	 chunk if the current_ptr is greater than or equal to B.  We
228*e4b17023SJohn Marino 	 can then reset the new current_ptr to B.  */
229*e4b17023SJohn Marino 
230*e4b17023SJohn Marino       first = NULL;
231*e4b17023SJohn Marino       q = (struct objalloc_chunk *) o->chunks;
232*e4b17023SJohn Marino       while (q != p)
233*e4b17023SJohn Marino 	{
234*e4b17023SJohn Marino 	  struct objalloc_chunk *next;
235*e4b17023SJohn Marino 
236*e4b17023SJohn Marino 	  next = q->next;
237*e4b17023SJohn Marino 	  if (small != NULL)
238*e4b17023SJohn Marino 	    {
239*e4b17023SJohn Marino 	      if (small == q)
240*e4b17023SJohn Marino 		small = NULL;
241*e4b17023SJohn Marino 	      free (q);
242*e4b17023SJohn Marino 	    }
243*e4b17023SJohn Marino 	  else if (q->current_ptr > b)
244*e4b17023SJohn Marino 	    free (q);
245*e4b17023SJohn Marino 	  else if (first == NULL)
246*e4b17023SJohn Marino 	    first = q;
247*e4b17023SJohn Marino 
248*e4b17023SJohn Marino 	  q = next;
249*e4b17023SJohn Marino 	}
250*e4b17023SJohn Marino 
251*e4b17023SJohn Marino       if (first == NULL)
252*e4b17023SJohn Marino 	first = p;
253*e4b17023SJohn Marino       o->chunks = (PTR) first;
254*e4b17023SJohn Marino 
255*e4b17023SJohn Marino       /* Now start allocating from this small block again.  */
256*e4b17023SJohn Marino       o->current_ptr = b;
257*e4b17023SJohn Marino       o->current_space = ((char *) p + CHUNK_SIZE) - b;
258*e4b17023SJohn Marino     }
259*e4b17023SJohn Marino   else
260*e4b17023SJohn Marino     {
261*e4b17023SJohn Marino       struct objalloc_chunk *q;
262*e4b17023SJohn Marino       char *current_ptr;
263*e4b17023SJohn Marino 
264*e4b17023SJohn Marino       /* This block is in a large chunk by itself.  We can free
265*e4b17023SJohn Marino          everything on the list up to and including this block.  We
266*e4b17023SJohn Marino          then start allocating from the next chunk containing small
267*e4b17023SJohn Marino          objects, setting current_ptr from the value stored with the
268*e4b17023SJohn Marino          large chunk we are freeing.  */
269*e4b17023SJohn Marino 
270*e4b17023SJohn Marino       current_ptr = p->current_ptr;
271*e4b17023SJohn Marino       p = p->next;
272*e4b17023SJohn Marino 
273*e4b17023SJohn Marino       q = (struct objalloc_chunk *) o->chunks;
274*e4b17023SJohn Marino       while (q != p)
275*e4b17023SJohn Marino 	{
276*e4b17023SJohn Marino 	  struct objalloc_chunk *next;
277*e4b17023SJohn Marino 
278*e4b17023SJohn Marino 	  next = q->next;
279*e4b17023SJohn Marino 	  free (q);
280*e4b17023SJohn Marino 	  q = next;
281*e4b17023SJohn Marino 	}
282*e4b17023SJohn Marino 
283*e4b17023SJohn Marino       o->chunks = (PTR) p;
284*e4b17023SJohn Marino 
285*e4b17023SJohn Marino       while (p->current_ptr != NULL)
286*e4b17023SJohn Marino 	p = p->next;
287*e4b17023SJohn Marino 
288*e4b17023SJohn Marino       o->current_ptr = current_ptr;
289*e4b17023SJohn Marino       o->current_space = ((char *) p + CHUNK_SIZE) - current_ptr;
290*e4b17023SJohn Marino     }
291*e4b17023SJohn Marino }
292