xref: /openbsd/gnu/usr.bin/gcc/gcc/f/malloc.c (revision c87b03e5)
1*c87b03e5Sespie /* malloc.c -- Implementation File (module.c template V1.0)
2*c87b03e5Sespie    Copyright (C) 1995 Free Software Foundation, Inc.
3*c87b03e5Sespie    Contributed by James Craig Burley.
4*c87b03e5Sespie 
5*c87b03e5Sespie This file is part of GNU Fortran.
6*c87b03e5Sespie 
7*c87b03e5Sespie GNU Fortran is free software; you can redistribute it and/or modify
8*c87b03e5Sespie it under the terms of the GNU General Public License as published by
9*c87b03e5Sespie the Free Software Foundation; either version 2, or (at your option)
10*c87b03e5Sespie any later version.
11*c87b03e5Sespie 
12*c87b03e5Sespie GNU Fortran is distributed in the hope that it will be useful,
13*c87b03e5Sespie but WITHOUT ANY WARRANTY; without even the implied warranty of
14*c87b03e5Sespie MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*c87b03e5Sespie GNU General Public License for more details.
16*c87b03e5Sespie 
17*c87b03e5Sespie You should have received a copy of the GNU General Public License
18*c87b03e5Sespie along with GNU Fortran; see the file COPYING.  If not, write to
19*c87b03e5Sespie the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20*c87b03e5Sespie 02111-1307, USA.
21*c87b03e5Sespie 
22*c87b03e5Sespie    Related Modules:
23*c87b03e5Sespie       None
24*c87b03e5Sespie 
25*c87b03e5Sespie    Description:
26*c87b03e5Sespie       Fast pool-based memory allocation.
27*c87b03e5Sespie 
28*c87b03e5Sespie    Modifications:
29*c87b03e5Sespie */
30*c87b03e5Sespie 
31*c87b03e5Sespie /* Include files. */
32*c87b03e5Sespie 
33*c87b03e5Sespie #include "proj.h"
34*c87b03e5Sespie #include "malloc.h"
35*c87b03e5Sespie 
36*c87b03e5Sespie /* Externals defined here.  */
37*c87b03e5Sespie 
38*c87b03e5Sespie struct _malloc_root_ malloc_root_
39*c87b03e5Sespie =
40*c87b03e5Sespie {
41*c87b03e5Sespie   {
42*c87b03e5Sespie     &malloc_root_.malloc_pool_image_,
43*c87b03e5Sespie     &malloc_root_.malloc_pool_image_,
44*c87b03e5Sespie     (mallocPool) &malloc_root_.malloc_pool_image_.eldest,
45*c87b03e5Sespie     (mallocPool) &malloc_root_.malloc_pool_image_.eldest,
46*c87b03e5Sespie     (mallocArea_) &malloc_root_.malloc_pool_image_.first,
47*c87b03e5Sespie     (mallocArea_) &malloc_root_.malloc_pool_image_.first,
48*c87b03e5Sespie     0,
49*c87b03e5Sespie #if MALLOC_DEBUG
50*c87b03e5Sespie     0, 0, 0, 0, 0, 0, 0, { '/' }
51*c87b03e5Sespie #else
52*c87b03e5Sespie     { 0 }
53*c87b03e5Sespie #endif
54*c87b03e5Sespie   },
55*c87b03e5Sespie };
56*c87b03e5Sespie 
57*c87b03e5Sespie /* Simple definitions and enumerations. */
58*c87b03e5Sespie 
59*c87b03e5Sespie 
60*c87b03e5Sespie /* Internal typedefs. */
61*c87b03e5Sespie 
62*c87b03e5Sespie 
63*c87b03e5Sespie /* Private include files. */
64*c87b03e5Sespie 
65*c87b03e5Sespie 
66*c87b03e5Sespie /* Internal structure definitions. */
67*c87b03e5Sespie 
68*c87b03e5Sespie 
69*c87b03e5Sespie /* Static objects accessed by functions in this module. */
70*c87b03e5Sespie 
71*c87b03e5Sespie static void *malloc_reserve_ = NULL;	/* For crashes. */
72*c87b03e5Sespie #if MALLOC_DEBUG
73*c87b03e5Sespie static const char *const malloc_types_[] =
74*c87b03e5Sespie {"KS", "KSR", "NF", "NFR", "US", "USR"};
75*c87b03e5Sespie #endif
76*c87b03e5Sespie 
77*c87b03e5Sespie /* Static functions (internal). */
78*c87b03e5Sespie 
79*c87b03e5Sespie static void malloc_kill_area_ (mallocPool pool, mallocArea_ a);
80*c87b03e5Sespie #if MALLOC_DEBUG
81*c87b03e5Sespie static void malloc_verify_area_ (mallocPool pool, mallocArea_ a);
82*c87b03e5Sespie #endif
83*c87b03e5Sespie 
84*c87b03e5Sespie /* Internal macros. */
85*c87b03e5Sespie 
86*c87b03e5Sespie #if MALLOC_DEBUG
87*c87b03e5Sespie #define malloc_kill_(ptr,s) do {memset((ptr),127,(s));free((ptr));} while(0)
88*c87b03e5Sespie #else
89*c87b03e5Sespie #define malloc_kill_(ptr,s) free((ptr))
90*c87b03e5Sespie #endif
91*c87b03e5Sespie 
92*c87b03e5Sespie /* malloc_kill_area_ -- Kill storage area and its object
93*c87b03e5Sespie 
94*c87b03e5Sespie    malloc_kill_area_(mallocPool pool,mallocArea_ area);
95*c87b03e5Sespie 
96*c87b03e5Sespie    Does the actual killing of a storage area.  */
97*c87b03e5Sespie 
98*c87b03e5Sespie static void
malloc_kill_area_(mallocPool pool UNUSED,mallocArea_ a)99*c87b03e5Sespie malloc_kill_area_ (mallocPool pool UNUSED, mallocArea_ a)
100*c87b03e5Sespie {
101*c87b03e5Sespie #if MALLOC_DEBUG
102*c87b03e5Sespie   assert (strcmp (a->name, ((char *) (a->where)) + a->size) == 0);
103*c87b03e5Sespie #endif
104*c87b03e5Sespie   malloc_kill_ (a->where, a->size);
105*c87b03e5Sespie   a->next->previous = a->previous;
106*c87b03e5Sespie   a->previous->next = a->next;
107*c87b03e5Sespie #if MALLOC_DEBUG
108*c87b03e5Sespie   pool->freed += a->size;
109*c87b03e5Sespie   pool->frees++;
110*c87b03e5Sespie #endif
111*c87b03e5Sespie   malloc_kill_ (a,
112*c87b03e5Sespie 		offsetof (struct _malloc_area_, name)
113*c87b03e5Sespie 		+ strlen (a->name) + 1);
114*c87b03e5Sespie }
115*c87b03e5Sespie 
116*c87b03e5Sespie /* malloc_verify_area_ -- Verify storage area and its object
117*c87b03e5Sespie 
118*c87b03e5Sespie    malloc_verify_area_(mallocPool pool,mallocArea_ area);
119*c87b03e5Sespie 
120*c87b03e5Sespie    Does the actual verifying of a storage area.  */
121*c87b03e5Sespie 
122*c87b03e5Sespie #if MALLOC_DEBUG
123*c87b03e5Sespie static void
malloc_verify_area_(mallocPool pool UNUSED,mallocArea_ a UNUSED)124*c87b03e5Sespie malloc_verify_area_ (mallocPool pool UNUSED, mallocArea_ a UNUSED)
125*c87b03e5Sespie {
126*c87b03e5Sespie   mallocSize s = a->size;
127*c87b03e5Sespie 
128*c87b03e5Sespie   assert (strcmp (a->name, ((char *) (a->where)) + s) == 0);
129*c87b03e5Sespie }
130*c87b03e5Sespie #endif
131*c87b03e5Sespie 
132*c87b03e5Sespie /* malloc_init -- Initialize malloc cluster
133*c87b03e5Sespie 
134*c87b03e5Sespie    malloc_init();
135*c87b03e5Sespie 
136*c87b03e5Sespie    Call malloc_init before you do anything else.  */
137*c87b03e5Sespie 
138*c87b03e5Sespie void
malloc_init()139*c87b03e5Sespie malloc_init ()
140*c87b03e5Sespie {
141*c87b03e5Sespie   if (malloc_reserve_ != NULL)
142*c87b03e5Sespie     return;
143*c87b03e5Sespie   malloc_reserve_ = xmalloc (20 * 1024); /* In case of crash, free this first. */
144*c87b03e5Sespie }
145*c87b03e5Sespie 
146*c87b03e5Sespie /* malloc_pool_display -- Display a pool
147*c87b03e5Sespie 
148*c87b03e5Sespie    mallocPool p;
149*c87b03e5Sespie    malloc_pool_display(p);
150*c87b03e5Sespie 
151*c87b03e5Sespie    Displays information associated with the pool and its subpools.  */
152*c87b03e5Sespie 
153*c87b03e5Sespie void
malloc_pool_display(mallocPool p UNUSED)154*c87b03e5Sespie malloc_pool_display (mallocPool p UNUSED)
155*c87b03e5Sespie {
156*c87b03e5Sespie #if MALLOC_DEBUG
157*c87b03e5Sespie   mallocPool q;
158*c87b03e5Sespie   mallocArea_ a;
159*c87b03e5Sespie 
160*c87b03e5Sespie   fprintf (dmpout, "Pool \"%s\": bytes allocated=%lu, freed=%lu, old sizes=%lu, new sizes\
161*c87b03e5Sespie =%lu,\n   allocations=%lu, frees=%lu, resizes=%lu, uses=%lu\n   Subpools:\n",
162*c87b03e5Sespie 	   p->name, p->allocated, p->freed, p->old_sizes, p->new_sizes, p->allocations,
163*c87b03e5Sespie 	   p->frees, p->resizes, p->uses);
164*c87b03e5Sespie 
165*c87b03e5Sespie   for (q = p->eldest; q != (mallocPool) & p->eldest; q = q->next)
166*c87b03e5Sespie     fprintf (dmpout, "      \"%s\"\n", q->name);
167*c87b03e5Sespie 
168*c87b03e5Sespie   fprintf (dmpout, "   Storage areas:\n");
169*c87b03e5Sespie 
170*c87b03e5Sespie   for (a = p->first; a != (mallocArea_) & p->first; a = a->next)
171*c87b03e5Sespie     {
172*c87b03e5Sespie       fprintf (dmpout, "      ");
173*c87b03e5Sespie       malloc_display_ (a);
174*c87b03e5Sespie     }
175*c87b03e5Sespie #endif
176*c87b03e5Sespie }
177*c87b03e5Sespie 
178*c87b03e5Sespie /* malloc_pool_kill -- Destroy a pool
179*c87b03e5Sespie 
180*c87b03e5Sespie    mallocPool p;
181*c87b03e5Sespie    malloc_pool_kill(p);
182*c87b03e5Sespie 
183*c87b03e5Sespie    Releases all storage associated with the pool and its subpools.  */
184*c87b03e5Sespie 
185*c87b03e5Sespie void
malloc_pool_kill(mallocPool p)186*c87b03e5Sespie malloc_pool_kill (mallocPool p)
187*c87b03e5Sespie {
188*c87b03e5Sespie   mallocPool q;
189*c87b03e5Sespie   mallocArea_ a;
190*c87b03e5Sespie 
191*c87b03e5Sespie   if (--p->uses != 0)
192*c87b03e5Sespie     return;
193*c87b03e5Sespie 
194*c87b03e5Sespie #if 0
195*c87b03e5Sespie   malloc_pool_display (p);
196*c87b03e5Sespie #endif
197*c87b03e5Sespie 
198*c87b03e5Sespie   assert (p->next->previous == p);
199*c87b03e5Sespie   assert (p->previous->next == p);
200*c87b03e5Sespie 
201*c87b03e5Sespie   /* Kill off all the subpools. */
202*c87b03e5Sespie 
203*c87b03e5Sespie   while ((q = p->eldest) != (mallocPool) &p->eldest)
204*c87b03e5Sespie     {
205*c87b03e5Sespie       q->uses = 1;		/* Force the kill. */
206*c87b03e5Sespie       malloc_pool_kill (q);
207*c87b03e5Sespie     }
208*c87b03e5Sespie 
209*c87b03e5Sespie   /* Now free all the storage areas. */
210*c87b03e5Sespie 
211*c87b03e5Sespie   while ((a = p->first) != (mallocArea_) & p->first)
212*c87b03e5Sespie     {
213*c87b03e5Sespie       malloc_kill_area_ (p, a);
214*c87b03e5Sespie     }
215*c87b03e5Sespie 
216*c87b03e5Sespie   /* Now remove from list of sibling pools. */
217*c87b03e5Sespie 
218*c87b03e5Sespie   p->next->previous = p->previous;
219*c87b03e5Sespie   p->previous->next = p->next;
220*c87b03e5Sespie 
221*c87b03e5Sespie   /* Finally, free the pool itself. */
222*c87b03e5Sespie 
223*c87b03e5Sespie   malloc_kill_ (p,
224*c87b03e5Sespie 		offsetof (struct _malloc_pool_, name)
225*c87b03e5Sespie 		+ strlen (p->name) + 1);
226*c87b03e5Sespie }
227*c87b03e5Sespie 
228*c87b03e5Sespie /* malloc_pool_new -- Make a new pool
229*c87b03e5Sespie 
230*c87b03e5Sespie    mallocPool p;
231*c87b03e5Sespie    p = malloc_pool_new("My new pool",malloc_pool_image(),1024);
232*c87b03e5Sespie 
233*c87b03e5Sespie    Makes a new pool with the given name and default new-chunk allocation.  */
234*c87b03e5Sespie 
235*c87b03e5Sespie mallocPool
malloc_pool_new(const char * name,mallocPool parent,unsigned long chunks UNUSED)236*c87b03e5Sespie malloc_pool_new (const char *name, mallocPool parent,
237*c87b03e5Sespie 		 unsigned long chunks UNUSED)
238*c87b03e5Sespie {
239*c87b03e5Sespie   mallocPool p;
240*c87b03e5Sespie 
241*c87b03e5Sespie   if (parent == NULL)
242*c87b03e5Sespie     parent = malloc_pool_image ();
243*c87b03e5Sespie 
244*c87b03e5Sespie   p = malloc_new_ (offsetof (struct _malloc_pool_, name)
245*c87b03e5Sespie 		   + (MALLOC_DEBUG ? strlen (name) + 1 : 0));
246*c87b03e5Sespie   p->next = (mallocPool) &(parent->eldest);
247*c87b03e5Sespie   p->previous = parent->youngest;
248*c87b03e5Sespie   parent->youngest->next = p;
249*c87b03e5Sespie   parent->youngest = p;
250*c87b03e5Sespie   p->eldest = (mallocPool) &(p->eldest);
251*c87b03e5Sespie   p->youngest = (mallocPool) &(p->eldest);
252*c87b03e5Sespie   p->first = (mallocArea_) &(p->first);
253*c87b03e5Sespie   p->last = (mallocArea_) &(p->first);
254*c87b03e5Sespie   p->uses = 1;
255*c87b03e5Sespie #if MALLOC_DEBUG
256*c87b03e5Sespie   p->allocated = p->freed = p->old_sizes = p->new_sizes = p->allocations
257*c87b03e5Sespie     = p->frees = p->resizes = 0;
258*c87b03e5Sespie   strcpy (p->name, name);
259*c87b03e5Sespie #endif
260*c87b03e5Sespie   return p;
261*c87b03e5Sespie }
262*c87b03e5Sespie 
263*c87b03e5Sespie /* malloc_pool_use -- Use an existing pool
264*c87b03e5Sespie 
265*c87b03e5Sespie    mallocPool p;
266*c87b03e5Sespie    p = malloc_pool_new(pool);
267*c87b03e5Sespie 
268*c87b03e5Sespie    Increments use count for pool; means a matching malloc_pool_kill must
269*c87b03e5Sespie    be performed before a subsequent one will actually kill the pool.  */
270*c87b03e5Sespie 
271*c87b03e5Sespie mallocPool
malloc_pool_use(mallocPool pool)272*c87b03e5Sespie malloc_pool_use (mallocPool pool)
273*c87b03e5Sespie {
274*c87b03e5Sespie   ++pool->uses;
275*c87b03e5Sespie   return pool;
276*c87b03e5Sespie }
277*c87b03e5Sespie 
278*c87b03e5Sespie /* malloc_display_ -- Display info on a mallocArea_
279*c87b03e5Sespie 
280*c87b03e5Sespie    mallocArea_ a;
281*c87b03e5Sespie    malloc_display_(a);
282*c87b03e5Sespie 
283*c87b03e5Sespie    Simple.  */
284*c87b03e5Sespie 
285*c87b03e5Sespie void
malloc_display_(mallocArea_ a UNUSED)286*c87b03e5Sespie malloc_display_ (mallocArea_ a UNUSED)
287*c87b03e5Sespie {
288*c87b03e5Sespie #if MALLOC_DEBUG
289*c87b03e5Sespie   fprintf (dmpout, "At %08lX, size=%" mallocSize_f "u, type=%s, \"%s\"\n",
290*c87b03e5Sespie 	(unsigned long) a->where, a->size, malloc_types_[a->type], a->name);
291*c87b03e5Sespie #endif
292*c87b03e5Sespie }
293*c87b03e5Sespie 
294*c87b03e5Sespie /* malloc_find_inpool_ -- Find mallocArea_ for object in pool
295*c87b03e5Sespie 
296*c87b03e5Sespie    mallocPool pool;
297*c87b03e5Sespie    void *ptr;
298*c87b03e5Sespie    mallocArea_ a;
299*c87b03e5Sespie    a = malloc_find_inpool_(pool,ptr);
300*c87b03e5Sespie 
301*c87b03e5Sespie    Search for object in list of mallocArea_s, die if not found.	 */
302*c87b03e5Sespie 
303*c87b03e5Sespie mallocArea_
malloc_find_inpool_(mallocPool pool,void * ptr)304*c87b03e5Sespie malloc_find_inpool_ (mallocPool pool, void *ptr)
305*c87b03e5Sespie {
306*c87b03e5Sespie   mallocArea_ a;
307*c87b03e5Sespie   mallocArea_ b = (mallocArea_) &pool->first;
308*c87b03e5Sespie   int n = 0;
309*c87b03e5Sespie 
310*c87b03e5Sespie   for (a = pool->first; a != (mallocArea_) &pool->first; a = a->next)
311*c87b03e5Sespie     {
312*c87b03e5Sespie       assert (("Infinite loop detected" != NULL) && (a != b));
313*c87b03e5Sespie       if (a->where == ptr)
314*c87b03e5Sespie 	return a;
315*c87b03e5Sespie       ++n;
316*c87b03e5Sespie       if (n & 1)
317*c87b03e5Sespie 	b = b->next;
318*c87b03e5Sespie     }
319*c87b03e5Sespie   assert ("Couldn't find object in pool!" == NULL);
320*c87b03e5Sespie   return NULL;
321*c87b03e5Sespie }
322*c87b03e5Sespie 
323*c87b03e5Sespie /* malloc_kill_inpool_ -- Kill object
324*c87b03e5Sespie 
325*c87b03e5Sespie    malloc_kill_inpool_(NULL,MALLOC_typeUS_,ptr,size_in_bytes);
326*c87b03e5Sespie 
327*c87b03e5Sespie    Find the mallocArea_ for the pointer, make sure the type is proper, and
328*c87b03e5Sespie    kill both of them.  */
329*c87b03e5Sespie 
330*c87b03e5Sespie void
malloc_kill_inpool_(mallocPool pool,mallocType_ type UNUSED,void * ptr,mallocSize s UNUSED)331*c87b03e5Sespie malloc_kill_inpool_ (mallocPool pool, mallocType_ type UNUSED,
332*c87b03e5Sespie 		     void *ptr, mallocSize s UNUSED)
333*c87b03e5Sespie {
334*c87b03e5Sespie   mallocArea_ a;
335*c87b03e5Sespie 
336*c87b03e5Sespie   if (pool == NULL)
337*c87b03e5Sespie     pool = malloc_pool_image ();
338*c87b03e5Sespie 
339*c87b03e5Sespie #if MALLOC_DEBUG
340*c87b03e5Sespie   assert ((pool == malloc_pool_image ())
341*c87b03e5Sespie 	  || malloc_pool_find_ (pool, malloc_pool_image ()));
342*c87b03e5Sespie #endif
343*c87b03e5Sespie 
344*c87b03e5Sespie   a = malloc_find_inpool_ (pool, ptr);
345*c87b03e5Sespie #if MALLOC_DEBUG
346*c87b03e5Sespie   assert (a->type == type);
347*c87b03e5Sespie   if ((type != MALLOC_typeUS_) && (type != MALLOC_typeUSR_))
348*c87b03e5Sespie     assert (a->size == s);
349*c87b03e5Sespie #endif
350*c87b03e5Sespie   malloc_kill_area_ (pool, a);
351*c87b03e5Sespie }
352*c87b03e5Sespie 
353*c87b03e5Sespie /* malloc_new_ -- Allocate new object, die if unable
354*c87b03e5Sespie 
355*c87b03e5Sespie    ptr = malloc_new_(size_in_bytes);
356*c87b03e5Sespie 
357*c87b03e5Sespie    Call malloc, bomb if it returns NULL.  */
358*c87b03e5Sespie 
359*c87b03e5Sespie void *
malloc_new_(mallocSize s)360*c87b03e5Sespie malloc_new_ (mallocSize s)
361*c87b03e5Sespie {
362*c87b03e5Sespie   void *ptr;
363*c87b03e5Sespie   unsigned ss = s;
364*c87b03e5Sespie 
365*c87b03e5Sespie #if MALLOC_DEBUG && 0
366*c87b03e5Sespie   assert (s == (mallocSize) ss);/* Else alloc is too big for this
367*c87b03e5Sespie 				   library/sys. */
368*c87b03e5Sespie #endif
369*c87b03e5Sespie 
370*c87b03e5Sespie   ptr = xmalloc (ss);
371*c87b03e5Sespie #if MALLOC_DEBUG
372*c87b03e5Sespie   memset (ptr, 126, ss);	/* Catch some kinds of errors more
373*c87b03e5Sespie 				   quickly/reliably. */
374*c87b03e5Sespie #endif
375*c87b03e5Sespie   return ptr;
376*c87b03e5Sespie }
377*c87b03e5Sespie 
378*c87b03e5Sespie /* malloc_new_inpool_ -- Allocate new object, die if unable
379*c87b03e5Sespie 
380*c87b03e5Sespie    ptr = malloc_new_inpool_(NULL,MALLOC_typeUS_,"object",size_in_bytes);
381*c87b03e5Sespie 
382*c87b03e5Sespie    Allocate the structure and allocate a mallocArea_ to describe it, then
383*c87b03e5Sespie    add it to the list of mallocArea_s for the pool.  */
384*c87b03e5Sespie 
385*c87b03e5Sespie void *
malloc_new_inpool_(mallocPool pool,mallocType_ type,const char * name,mallocSize s)386*c87b03e5Sespie malloc_new_inpool_ (mallocPool pool, mallocType_ type, const char *name, mallocSize s)
387*c87b03e5Sespie {
388*c87b03e5Sespie   void *ptr;
389*c87b03e5Sespie   mallocArea_ a;
390*c87b03e5Sespie   unsigned short i;
391*c87b03e5Sespie 
392*c87b03e5Sespie   if (pool == NULL)
393*c87b03e5Sespie     pool = malloc_pool_image ();
394*c87b03e5Sespie 
395*c87b03e5Sespie #if MALLOC_DEBUG
396*c87b03e5Sespie   assert ((pool == malloc_pool_image ())
397*c87b03e5Sespie 	  || malloc_pool_find_ (pool, malloc_pool_image ()));
398*c87b03e5Sespie #endif
399*c87b03e5Sespie 
400*c87b03e5Sespie   ptr = malloc_new_ (s + (i = (MALLOC_DEBUG ? strlen (name) + 1 : 0)));
401*c87b03e5Sespie #if MALLOC_DEBUG
402*c87b03e5Sespie   strcpy (((char *) (ptr)) + s, name);
403*c87b03e5Sespie #endif
404*c87b03e5Sespie   a = malloc_new_ (offsetof (struct _malloc_area_, name) + i);
405*c87b03e5Sespie   switch (type)
406*c87b03e5Sespie     {				/* A little optimization to speed up killing
407*c87b03e5Sespie 				   of non-permanent stuff. */
408*c87b03e5Sespie     case MALLOC_typeKP_:
409*c87b03e5Sespie     case MALLOC_typeKPR_:
410*c87b03e5Sespie       a->next = (mallocArea_) &pool->first;
411*c87b03e5Sespie       break;
412*c87b03e5Sespie 
413*c87b03e5Sespie     default:
414*c87b03e5Sespie       a->next = pool->first;
415*c87b03e5Sespie       break;
416*c87b03e5Sespie     }
417*c87b03e5Sespie   a->previous = a->next->previous;
418*c87b03e5Sespie   a->next->previous = a;
419*c87b03e5Sespie   a->previous->next = a;
420*c87b03e5Sespie   a->where = ptr;
421*c87b03e5Sespie #if MALLOC_DEBUG
422*c87b03e5Sespie   a->size = s;
423*c87b03e5Sespie   a->type = type;
424*c87b03e5Sespie   strcpy (a->name, name);
425*c87b03e5Sespie   pool->allocated += s;
426*c87b03e5Sespie   pool->allocations++;
427*c87b03e5Sespie #endif
428*c87b03e5Sespie   return ptr;
429*c87b03e5Sespie }
430*c87b03e5Sespie 
431*c87b03e5Sespie /* malloc_new_zinpool_ -- Allocate new zeroed object, die if unable
432*c87b03e5Sespie 
433*c87b03e5Sespie    ptr = malloc_new_zinpool_(NULL,MALLOC_typeUS_,"object",size_in_bytes,0);
434*c87b03e5Sespie 
435*c87b03e5Sespie    Like malloc_new_inpool_, but zeros out all the bytes in the area (assuming
436*c87b03e5Sespie    you pass it a 0).  */
437*c87b03e5Sespie 
438*c87b03e5Sespie void *
malloc_new_zinpool_(mallocPool pool,mallocType_ type,const char * name,mallocSize s,int z)439*c87b03e5Sespie malloc_new_zinpool_ (mallocPool pool, mallocType_ type, const char *name, mallocSize s,
440*c87b03e5Sespie 		     int z)
441*c87b03e5Sespie {
442*c87b03e5Sespie   void *ptr;
443*c87b03e5Sespie 
444*c87b03e5Sespie   ptr = malloc_new_inpool_ (pool, type, name, s);
445*c87b03e5Sespie   memset (ptr, z, s);
446*c87b03e5Sespie   return ptr;
447*c87b03e5Sespie }
448*c87b03e5Sespie 
449*c87b03e5Sespie /* malloc_pool_find_ -- See if pool is a descendant of another pool
450*c87b03e5Sespie 
451*c87b03e5Sespie    if (malloc_pool_find_(target_pool,parent_pool)) ...;
452*c87b03e5Sespie 
453*c87b03e5Sespie    Recursive descent on each of the children of the parent pool, after
454*c87b03e5Sespie    first checking the children themselves.  */
455*c87b03e5Sespie 
456*c87b03e5Sespie char
malloc_pool_find_(mallocPool pool,mallocPool parent)457*c87b03e5Sespie malloc_pool_find_ (mallocPool pool, mallocPool parent)
458*c87b03e5Sespie {
459*c87b03e5Sespie   mallocPool p;
460*c87b03e5Sespie 
461*c87b03e5Sespie   for (p = parent->eldest; p != (mallocPool) & parent->eldest; p = p->next)
462*c87b03e5Sespie     {
463*c87b03e5Sespie       if ((p == pool) || malloc_pool_find_ (pool, p))
464*c87b03e5Sespie 	return 1;
465*c87b03e5Sespie     }
466*c87b03e5Sespie   return 0;
467*c87b03e5Sespie }
468*c87b03e5Sespie 
469*c87b03e5Sespie /* malloc_resize_inpool_ -- Resize existing object in pool
470*c87b03e5Sespie 
471*c87b03e5Sespie    ptr = malloc_resize_inpool_(NULL,MALLOC_typeUSR_,ptr,new_size,old_size);
472*c87b03e5Sespie 
473*c87b03e5Sespie    Find the object's mallocArea_, check it out, then do the resizing.  */
474*c87b03e5Sespie 
475*c87b03e5Sespie void *
malloc_resize_inpool_(mallocPool pool,mallocType_ type UNUSED,void * ptr,mallocSize ns,mallocSize os UNUSED)476*c87b03e5Sespie malloc_resize_inpool_ (mallocPool pool, mallocType_ type UNUSED,
477*c87b03e5Sespie 		       void *ptr, mallocSize ns, mallocSize os UNUSED)
478*c87b03e5Sespie {
479*c87b03e5Sespie   mallocArea_ a;
480*c87b03e5Sespie 
481*c87b03e5Sespie   if (pool == NULL)
482*c87b03e5Sespie     pool = malloc_pool_image ();
483*c87b03e5Sespie 
484*c87b03e5Sespie #if MALLOC_DEBUG
485*c87b03e5Sespie   assert ((pool == malloc_pool_image ())
486*c87b03e5Sespie 	  || malloc_pool_find_ (pool, malloc_pool_image ()));
487*c87b03e5Sespie #endif
488*c87b03e5Sespie 
489*c87b03e5Sespie   a = malloc_find_inpool_ (pool, ptr);
490*c87b03e5Sespie #if MALLOC_DEBUG
491*c87b03e5Sespie   assert (a->type == type);
492*c87b03e5Sespie   if ((type == MALLOC_typeKSR_) || (type == MALLOC_typeKPR_))
493*c87b03e5Sespie     assert (a->size == os);
494*c87b03e5Sespie   assert (strcmp (a->name, ((char *) (ptr)) + os) == 0);
495*c87b03e5Sespie #endif
496*c87b03e5Sespie   ptr = malloc_resize_ (ptr, ns + (MALLOC_DEBUG ? strlen (a->name) + 1: 0));
497*c87b03e5Sespie   a->where = ptr;
498*c87b03e5Sespie #if MALLOC_DEBUG
499*c87b03e5Sespie   a->size = ns;
500*c87b03e5Sespie   strcpy (((char *) (ptr)) + ns, a->name);
501*c87b03e5Sespie   pool->old_sizes += os;
502*c87b03e5Sespie   pool->new_sizes += ns;
503*c87b03e5Sespie   pool->resizes++;
504*c87b03e5Sespie #endif
505*c87b03e5Sespie   return ptr;
506*c87b03e5Sespie }
507*c87b03e5Sespie 
508*c87b03e5Sespie /* malloc_resize_ -- Reallocate object, die if unable
509*c87b03e5Sespie 
510*c87b03e5Sespie    ptr = malloc_resize_(ptr,size_in_bytes);
511*c87b03e5Sespie 
512*c87b03e5Sespie    Call realloc, bomb if it returns NULL.  */
513*c87b03e5Sespie 
514*c87b03e5Sespie void *
malloc_resize_(void * ptr,mallocSize s)515*c87b03e5Sespie malloc_resize_ (void *ptr, mallocSize s)
516*c87b03e5Sespie {
517*c87b03e5Sespie   int ss = s;
518*c87b03e5Sespie 
519*c87b03e5Sespie #if MALLOC_DEBUG && 0
520*c87b03e5Sespie   assert (s == (mallocSize) ss);/* Too big if failure here. */
521*c87b03e5Sespie #endif
522*c87b03e5Sespie 
523*c87b03e5Sespie   ptr = xrealloc (ptr, ss);
524*c87b03e5Sespie   return ptr;
525*c87b03e5Sespie }
526*c87b03e5Sespie 
527*c87b03e5Sespie /* malloc_verify_inpool_ -- Verify object
528*c87b03e5Sespie 
529*c87b03e5Sespie    Find the mallocArea_ for the pointer, make sure the type is proper, and
530*c87b03e5Sespie    verify both of them.  */
531*c87b03e5Sespie 
532*c87b03e5Sespie void
malloc_verify_inpool_(mallocPool pool UNUSED,mallocType_ type UNUSED,void * ptr UNUSED,mallocSize s UNUSED)533*c87b03e5Sespie malloc_verify_inpool_ (mallocPool pool UNUSED, mallocType_ type UNUSED,
534*c87b03e5Sespie 		       void *ptr UNUSED, mallocSize s UNUSED)
535*c87b03e5Sespie {
536*c87b03e5Sespie #if MALLOC_DEBUG
537*c87b03e5Sespie   mallocArea_ a;
538*c87b03e5Sespie 
539*c87b03e5Sespie   if (pool == NULL)
540*c87b03e5Sespie     pool = malloc_pool_image ();
541*c87b03e5Sespie 
542*c87b03e5Sespie   assert ((pool == malloc_pool_image ())
543*c87b03e5Sespie 	  || malloc_pool_find_ (pool, malloc_pool_image ()));
544*c87b03e5Sespie 
545*c87b03e5Sespie   a = malloc_find_inpool_ (pool, ptr);
546*c87b03e5Sespie   assert (a->type == type);
547*c87b03e5Sespie   if ((type != MALLOC_typeUS_) && (type != MALLOC_typeUSR_))
548*c87b03e5Sespie     assert (a->size == s);
549*c87b03e5Sespie   malloc_verify_area_ (pool, a);
550*c87b03e5Sespie #endif
551*c87b03e5Sespie }
552