1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers.
3*7c478bd9Sstevel@tonic-gate * All rights reserved.
4*7c478bd9Sstevel@tonic-gate *
5*7c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set
6*7c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of
7*7c478bd9Sstevel@tonic-gate * the sendmail distribution.
8*7c478bd9Sstevel@tonic-gate */
9*7c478bd9Sstevel@tonic-gate
10*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
11*7c478bd9Sstevel@tonic-gate
12*7c478bd9Sstevel@tonic-gate #include <sm/gen.h>
13*7c478bd9Sstevel@tonic-gate SM_RCSID("@(#)$Id: heap.c,v 1.51 2004/08/03 20:32:00 ca Exp $")
14*7c478bd9Sstevel@tonic-gate
15*7c478bd9Sstevel@tonic-gate /*
16*7c478bd9Sstevel@tonic-gate ** debugging memory allocation package
17*7c478bd9Sstevel@tonic-gate ** See heap.html for documentation.
18*7c478bd9Sstevel@tonic-gate */
19*7c478bd9Sstevel@tonic-gate
20*7c478bd9Sstevel@tonic-gate #include <string.h>
21*7c478bd9Sstevel@tonic-gate
22*7c478bd9Sstevel@tonic-gate #include <sm/assert.h>
23*7c478bd9Sstevel@tonic-gate #include <sm/debug.h>
24*7c478bd9Sstevel@tonic-gate #include <sm/exc.h>
25*7c478bd9Sstevel@tonic-gate #include <sm/heap.h>
26*7c478bd9Sstevel@tonic-gate #include <sm/io.h>
27*7c478bd9Sstevel@tonic-gate #include <sm/signal.h>
28*7c478bd9Sstevel@tonic-gate #include <sm/xtrap.h>
29*7c478bd9Sstevel@tonic-gate
30*7c478bd9Sstevel@tonic-gate /* undef all macro versions of the "functions" so they can be specified here */
31*7c478bd9Sstevel@tonic-gate #undef sm_malloc
32*7c478bd9Sstevel@tonic-gate #undef sm_malloc_x
33*7c478bd9Sstevel@tonic-gate #undef sm_malloc_tagged
34*7c478bd9Sstevel@tonic-gate #undef sm_malloc_tagged_x
35*7c478bd9Sstevel@tonic-gate #undef sm_free
36*7c478bd9Sstevel@tonic-gate #undef sm_free_tagged
37*7c478bd9Sstevel@tonic-gate #undef sm_realloc
38*7c478bd9Sstevel@tonic-gate #if SM_HEAP_CHECK
39*7c478bd9Sstevel@tonic-gate # undef sm_heap_register
40*7c478bd9Sstevel@tonic-gate # undef sm_heap_checkptr
41*7c478bd9Sstevel@tonic-gate # undef sm_heap_report
42*7c478bd9Sstevel@tonic-gate #endif /* SM_HEAP_CHECK */
43*7c478bd9Sstevel@tonic-gate
44*7c478bd9Sstevel@tonic-gate #if SM_HEAP_CHECK
45*7c478bd9Sstevel@tonic-gate SM_DEBUG_T SmHeapCheck = SM_DEBUG_INITIALIZER("sm_check_heap",
46*7c478bd9Sstevel@tonic-gate "@(#)$Debug: sm_check_heap - check sm_malloc, sm_realloc, sm_free calls $");
47*7c478bd9Sstevel@tonic-gate # define HEAP_CHECK sm_debug_active(&SmHeapCheck, 1)
48*7c478bd9Sstevel@tonic-gate static int ptrhash __P((void *p));
49*7c478bd9Sstevel@tonic-gate #endif /* SM_HEAP_CHECK */
50*7c478bd9Sstevel@tonic-gate
51*7c478bd9Sstevel@tonic-gate const SM_EXC_TYPE_T SmHeapOutOfMemoryType =
52*7c478bd9Sstevel@tonic-gate {
53*7c478bd9Sstevel@tonic-gate SmExcTypeMagic,
54*7c478bd9Sstevel@tonic-gate "F:sm.heap",
55*7c478bd9Sstevel@tonic-gate "",
56*7c478bd9Sstevel@tonic-gate sm_etype_printf,
57*7c478bd9Sstevel@tonic-gate "out of memory",
58*7c478bd9Sstevel@tonic-gate };
59*7c478bd9Sstevel@tonic-gate
60*7c478bd9Sstevel@tonic-gate SM_EXC_T SmHeapOutOfMemory = SM_EXC_INITIALIZER(&SmHeapOutOfMemoryType, NULL);
61*7c478bd9Sstevel@tonic-gate
62*7c478bd9Sstevel@tonic-gate
63*7c478bd9Sstevel@tonic-gate /*
64*7c478bd9Sstevel@tonic-gate ** The behaviour of malloc with size==0 is platform dependent (it
65*7c478bd9Sstevel@tonic-gate ** says so in the C standard): it can return NULL or non-NULL. We
66*7c478bd9Sstevel@tonic-gate ** don't want sm_malloc_x(0) to raise an exception on some platforms
67*7c478bd9Sstevel@tonic-gate ** but not others, so this case requires special handling. We've got
68*7c478bd9Sstevel@tonic-gate ** two choices: "size = 1" or "return NULL". We use the former in the
69*7c478bd9Sstevel@tonic-gate ** following.
70*7c478bd9Sstevel@tonic-gate ** If we had something like autoconf we could figure out the
71*7c478bd9Sstevel@tonic-gate ** behaviour of the platform and either use this hack or just
72*7c478bd9Sstevel@tonic-gate ** use size.
73*7c478bd9Sstevel@tonic-gate */
74*7c478bd9Sstevel@tonic-gate
75*7c478bd9Sstevel@tonic-gate #define MALLOC_SIZE(size) ((size) == 0 ? 1 : (size))
76*7c478bd9Sstevel@tonic-gate
77*7c478bd9Sstevel@tonic-gate /*
78*7c478bd9Sstevel@tonic-gate ** SM_MALLOC_X -- wrapper around malloc(), raises an exception on error.
79*7c478bd9Sstevel@tonic-gate **
80*7c478bd9Sstevel@tonic-gate ** Parameters:
81*7c478bd9Sstevel@tonic-gate ** size -- size of requested memory.
82*7c478bd9Sstevel@tonic-gate **
83*7c478bd9Sstevel@tonic-gate ** Returns:
84*7c478bd9Sstevel@tonic-gate ** Pointer to memory region.
85*7c478bd9Sstevel@tonic-gate **
86*7c478bd9Sstevel@tonic-gate ** Note:
87*7c478bd9Sstevel@tonic-gate ** sm_malloc_x only gets called from source files in which heap
88*7c478bd9Sstevel@tonic-gate ** debugging is disabled at compile time. Otherwise, a call to
89*7c478bd9Sstevel@tonic-gate ** sm_malloc_x is macro expanded to a call to sm_malloc_tagged_x.
90*7c478bd9Sstevel@tonic-gate **
91*7c478bd9Sstevel@tonic-gate ** Exceptions:
92*7c478bd9Sstevel@tonic-gate ** F:sm_heap -- out of memory
93*7c478bd9Sstevel@tonic-gate */
94*7c478bd9Sstevel@tonic-gate
95*7c478bd9Sstevel@tonic-gate void *
sm_malloc_x(size)96*7c478bd9Sstevel@tonic-gate sm_malloc_x(size)
97*7c478bd9Sstevel@tonic-gate size_t size;
98*7c478bd9Sstevel@tonic-gate {
99*7c478bd9Sstevel@tonic-gate void *ptr;
100*7c478bd9Sstevel@tonic-gate
101*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
102*7c478bd9Sstevel@tonic-gate ptr = malloc(MALLOC_SIZE(size));
103*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
104*7c478bd9Sstevel@tonic-gate if (ptr == NULL)
105*7c478bd9Sstevel@tonic-gate sm_exc_raise_x(&SmHeapOutOfMemory);
106*7c478bd9Sstevel@tonic-gate return ptr;
107*7c478bd9Sstevel@tonic-gate }
108*7c478bd9Sstevel@tonic-gate
109*7c478bd9Sstevel@tonic-gate #if !SM_HEAP_CHECK
110*7c478bd9Sstevel@tonic-gate
111*7c478bd9Sstevel@tonic-gate /*
112*7c478bd9Sstevel@tonic-gate ** SM_MALLOC -- wrapper around malloc()
113*7c478bd9Sstevel@tonic-gate **
114*7c478bd9Sstevel@tonic-gate ** Parameters:
115*7c478bd9Sstevel@tonic-gate ** size -- size of requested memory.
116*7c478bd9Sstevel@tonic-gate **
117*7c478bd9Sstevel@tonic-gate ** Returns:
118*7c478bd9Sstevel@tonic-gate ** Pointer to memory region.
119*7c478bd9Sstevel@tonic-gate */
120*7c478bd9Sstevel@tonic-gate
121*7c478bd9Sstevel@tonic-gate void *
sm_malloc(size)122*7c478bd9Sstevel@tonic-gate sm_malloc(size)
123*7c478bd9Sstevel@tonic-gate size_t size;
124*7c478bd9Sstevel@tonic-gate {
125*7c478bd9Sstevel@tonic-gate void *ptr;
126*7c478bd9Sstevel@tonic-gate
127*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
128*7c478bd9Sstevel@tonic-gate ptr = malloc(MALLOC_SIZE(size));
129*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
130*7c478bd9Sstevel@tonic-gate return ptr;
131*7c478bd9Sstevel@tonic-gate }
132*7c478bd9Sstevel@tonic-gate
133*7c478bd9Sstevel@tonic-gate /*
134*7c478bd9Sstevel@tonic-gate ** SM_REALLOC -- wrapper for realloc()
135*7c478bd9Sstevel@tonic-gate **
136*7c478bd9Sstevel@tonic-gate ** Parameters:
137*7c478bd9Sstevel@tonic-gate ** ptr -- pointer to old memory area.
138*7c478bd9Sstevel@tonic-gate ** size -- size of requested memory.
139*7c478bd9Sstevel@tonic-gate **
140*7c478bd9Sstevel@tonic-gate ** Returns:
141*7c478bd9Sstevel@tonic-gate ** Pointer to new memory area, NULL on failure.
142*7c478bd9Sstevel@tonic-gate */
143*7c478bd9Sstevel@tonic-gate
144*7c478bd9Sstevel@tonic-gate void *
sm_realloc(ptr,size)145*7c478bd9Sstevel@tonic-gate sm_realloc(ptr, size)
146*7c478bd9Sstevel@tonic-gate void *ptr;
147*7c478bd9Sstevel@tonic-gate size_t size;
148*7c478bd9Sstevel@tonic-gate {
149*7c478bd9Sstevel@tonic-gate void *newptr;
150*7c478bd9Sstevel@tonic-gate
151*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
152*7c478bd9Sstevel@tonic-gate newptr = realloc(ptr, MALLOC_SIZE(size));
153*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
154*7c478bd9Sstevel@tonic-gate return newptr;
155*7c478bd9Sstevel@tonic-gate }
156*7c478bd9Sstevel@tonic-gate
157*7c478bd9Sstevel@tonic-gate /*
158*7c478bd9Sstevel@tonic-gate ** SM_REALLOC_X -- wrapper for realloc()
159*7c478bd9Sstevel@tonic-gate **
160*7c478bd9Sstevel@tonic-gate ** Parameters:
161*7c478bd9Sstevel@tonic-gate ** ptr -- pointer to old memory area.
162*7c478bd9Sstevel@tonic-gate ** size -- size of requested memory.
163*7c478bd9Sstevel@tonic-gate **
164*7c478bd9Sstevel@tonic-gate ** Returns:
165*7c478bd9Sstevel@tonic-gate ** Pointer to new memory area.
166*7c478bd9Sstevel@tonic-gate **
167*7c478bd9Sstevel@tonic-gate ** Exceptions:
168*7c478bd9Sstevel@tonic-gate ** F:sm_heap -- out of memory
169*7c478bd9Sstevel@tonic-gate */
170*7c478bd9Sstevel@tonic-gate
171*7c478bd9Sstevel@tonic-gate void *
sm_realloc_x(ptr,size)172*7c478bd9Sstevel@tonic-gate sm_realloc_x(ptr, size)
173*7c478bd9Sstevel@tonic-gate void *ptr;
174*7c478bd9Sstevel@tonic-gate size_t size;
175*7c478bd9Sstevel@tonic-gate {
176*7c478bd9Sstevel@tonic-gate void *newptr;
177*7c478bd9Sstevel@tonic-gate
178*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
179*7c478bd9Sstevel@tonic-gate newptr = realloc(ptr, MALLOC_SIZE(size));
180*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
181*7c478bd9Sstevel@tonic-gate if (newptr == NULL)
182*7c478bd9Sstevel@tonic-gate sm_exc_raise_x(&SmHeapOutOfMemory);
183*7c478bd9Sstevel@tonic-gate return newptr;
184*7c478bd9Sstevel@tonic-gate }
185*7c478bd9Sstevel@tonic-gate /*
186*7c478bd9Sstevel@tonic-gate ** SM_FREE -- wrapper around free()
187*7c478bd9Sstevel@tonic-gate **
188*7c478bd9Sstevel@tonic-gate ** Parameters:
189*7c478bd9Sstevel@tonic-gate ** ptr -- pointer to memory region.
190*7c478bd9Sstevel@tonic-gate **
191*7c478bd9Sstevel@tonic-gate ** Returns:
192*7c478bd9Sstevel@tonic-gate ** none.
193*7c478bd9Sstevel@tonic-gate */
194*7c478bd9Sstevel@tonic-gate
195*7c478bd9Sstevel@tonic-gate void
sm_free(ptr)196*7c478bd9Sstevel@tonic-gate sm_free(ptr)
197*7c478bd9Sstevel@tonic-gate void *ptr;
198*7c478bd9Sstevel@tonic-gate {
199*7c478bd9Sstevel@tonic-gate if (ptr == NULL)
200*7c478bd9Sstevel@tonic-gate return;
201*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
202*7c478bd9Sstevel@tonic-gate free(ptr);
203*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
204*7c478bd9Sstevel@tonic-gate return;
205*7c478bd9Sstevel@tonic-gate }
206*7c478bd9Sstevel@tonic-gate
207*7c478bd9Sstevel@tonic-gate #else /* !SM_HEAP_CHECK */
208*7c478bd9Sstevel@tonic-gate
209*7c478bd9Sstevel@tonic-gate /*
210*7c478bd9Sstevel@tonic-gate ** Each allocated block is assigned a "group number".
211*7c478bd9Sstevel@tonic-gate ** By default, all blocks are assigned to group #1.
212*7c478bd9Sstevel@tonic-gate ** By convention, group #0 is for memory that is never freed.
213*7c478bd9Sstevel@tonic-gate ** You can use group numbers any way you want, in order to help make
214*7c478bd9Sstevel@tonic-gate ** sense of sm_heap_report output.
215*7c478bd9Sstevel@tonic-gate */
216*7c478bd9Sstevel@tonic-gate
217*7c478bd9Sstevel@tonic-gate int SmHeapGroup = 1;
218*7c478bd9Sstevel@tonic-gate int SmHeapMaxGroup = 1;
219*7c478bd9Sstevel@tonic-gate
220*7c478bd9Sstevel@tonic-gate /*
221*7c478bd9Sstevel@tonic-gate ** Total number of bytes allocated.
222*7c478bd9Sstevel@tonic-gate ** This is only maintained if the sm_check_heap debug category is active.
223*7c478bd9Sstevel@tonic-gate */
224*7c478bd9Sstevel@tonic-gate
225*7c478bd9Sstevel@tonic-gate size_t SmHeapTotal = 0;
226*7c478bd9Sstevel@tonic-gate
227*7c478bd9Sstevel@tonic-gate /*
228*7c478bd9Sstevel@tonic-gate ** High water mark: the most that SmHeapTotal has ever been.
229*7c478bd9Sstevel@tonic-gate */
230*7c478bd9Sstevel@tonic-gate
231*7c478bd9Sstevel@tonic-gate size_t SmHeapMaxTotal = 0;
232*7c478bd9Sstevel@tonic-gate
233*7c478bd9Sstevel@tonic-gate /*
234*7c478bd9Sstevel@tonic-gate ** Maximum number of bytes that may be allocated at any one time.
235*7c478bd9Sstevel@tonic-gate ** 0 means no limit.
236*7c478bd9Sstevel@tonic-gate ** This is only honoured if sm_check_heap is active.
237*7c478bd9Sstevel@tonic-gate */
238*7c478bd9Sstevel@tonic-gate
239*7c478bd9Sstevel@tonic-gate SM_DEBUG_T SmHeapLimit = SM_DEBUG_INITIALIZER("sm_heap_limit",
240*7c478bd9Sstevel@tonic-gate "@(#)$Debug: sm_heap_limit - max # of bytes permitted in heap $");
241*7c478bd9Sstevel@tonic-gate
242*7c478bd9Sstevel@tonic-gate /*
243*7c478bd9Sstevel@tonic-gate ** This is the data structure that keeps track of all currently
244*7c478bd9Sstevel@tonic-gate ** allocated blocks of memory known to the heap package.
245*7c478bd9Sstevel@tonic-gate */
246*7c478bd9Sstevel@tonic-gate
247*7c478bd9Sstevel@tonic-gate typedef struct sm_heap_item SM_HEAP_ITEM_T;
248*7c478bd9Sstevel@tonic-gate struct sm_heap_item
249*7c478bd9Sstevel@tonic-gate {
250*7c478bd9Sstevel@tonic-gate void *hi_ptr;
251*7c478bd9Sstevel@tonic-gate size_t hi_size;
252*7c478bd9Sstevel@tonic-gate char *hi_tag;
253*7c478bd9Sstevel@tonic-gate int hi_num;
254*7c478bd9Sstevel@tonic-gate int hi_group;
255*7c478bd9Sstevel@tonic-gate SM_HEAP_ITEM_T *hi_next;
256*7c478bd9Sstevel@tonic-gate };
257*7c478bd9Sstevel@tonic-gate
258*7c478bd9Sstevel@tonic-gate #define SM_HEAP_TABLE_SIZE 256
259*7c478bd9Sstevel@tonic-gate static SM_HEAP_ITEM_T *SmHeapTable[SM_HEAP_TABLE_SIZE];
260*7c478bd9Sstevel@tonic-gate
261*7c478bd9Sstevel@tonic-gate /*
262*7c478bd9Sstevel@tonic-gate ** This is a randomly generated table
263*7c478bd9Sstevel@tonic-gate ** which contains exactly one occurrence
264*7c478bd9Sstevel@tonic-gate ** of each of the numbers between 0 and 255.
265*7c478bd9Sstevel@tonic-gate ** It is used by ptrhash.
266*7c478bd9Sstevel@tonic-gate */
267*7c478bd9Sstevel@tonic-gate
268*7c478bd9Sstevel@tonic-gate static unsigned char hashtab[SM_HEAP_TABLE_SIZE] =
269*7c478bd9Sstevel@tonic-gate {
270*7c478bd9Sstevel@tonic-gate 161, 71, 77,187, 15,229, 9,176,221,119,239, 21, 85,138,203, 86,
271*7c478bd9Sstevel@tonic-gate 102, 65, 80,199,235, 32,140, 96,224, 78,126,127,144, 0, 11,179,
272*7c478bd9Sstevel@tonic-gate 64, 30,120, 23,225,226, 33, 50,205,167,130,240,174, 99,206, 73,
273*7c478bd9Sstevel@tonic-gate 231,210,189,162, 48, 93,246, 54,213,141,135, 39, 41,192,236,193,
274*7c478bd9Sstevel@tonic-gate 157, 88, 95,104,188, 63,133,177,234,110,158,214,238,131,233, 91,
275*7c478bd9Sstevel@tonic-gate 125, 82, 94, 79, 66, 92,151, 45,252, 98, 26,183, 7,191,171,106,
276*7c478bd9Sstevel@tonic-gate 145,154,251,100,113, 5, 74, 62, 76,124, 14,217,200, 75,115,190,
277*7c478bd9Sstevel@tonic-gate 103, 28,198,196,169,219, 37,118,150, 18,152,175, 49,136, 6,142,
278*7c478bd9Sstevel@tonic-gate 89, 19,243,254, 47,137, 24,166,180, 10, 40,186,202, 46,184, 67,
279*7c478bd9Sstevel@tonic-gate 148,108,181, 81, 25,241, 13,139, 58, 38, 84,253,201, 12,116, 17,
280*7c478bd9Sstevel@tonic-gate 195, 22,112, 69,255, 43,147,222,111, 56,194,216,149,244, 42,173,
281*7c478bd9Sstevel@tonic-gate 232,220,249,105,207, 51,197,242, 72,211,208, 59,122,230,237,170,
282*7c478bd9Sstevel@tonic-gate 165, 44, 68,123,129,245,143,101, 8,209,215,247,185, 57,218, 53,
283*7c478bd9Sstevel@tonic-gate 114,121, 3,128, 4,204,212,146, 2,155, 83,250, 87, 29, 31,159,
284*7c478bd9Sstevel@tonic-gate 60, 27,107,156,227,182, 1, 61, 36,160,109, 97, 90, 20,168,132,
285*7c478bd9Sstevel@tonic-gate 223,248, 70,164, 55,172, 34, 52,163,117, 35,153,134, 16,178,228
286*7c478bd9Sstevel@tonic-gate };
287*7c478bd9Sstevel@tonic-gate
288*7c478bd9Sstevel@tonic-gate /*
289*7c478bd9Sstevel@tonic-gate ** PTRHASH -- hash a pointer value
290*7c478bd9Sstevel@tonic-gate **
291*7c478bd9Sstevel@tonic-gate ** Parameters:
292*7c478bd9Sstevel@tonic-gate ** p -- pointer.
293*7c478bd9Sstevel@tonic-gate **
294*7c478bd9Sstevel@tonic-gate ** Returns:
295*7c478bd9Sstevel@tonic-gate ** hash value.
296*7c478bd9Sstevel@tonic-gate **
297*7c478bd9Sstevel@tonic-gate ** ptrhash hashes a pointer value to a uniformly distributed random
298*7c478bd9Sstevel@tonic-gate ** number between 0 and 255.
299*7c478bd9Sstevel@tonic-gate **
300*7c478bd9Sstevel@tonic-gate ** This hash algorithm is based on Peter K. Pearson,
301*7c478bd9Sstevel@tonic-gate ** "Fast Hashing of Variable-Length Text Strings",
302*7c478bd9Sstevel@tonic-gate ** in Communications of the ACM, June 1990, vol 33 no 6.
303*7c478bd9Sstevel@tonic-gate */
304*7c478bd9Sstevel@tonic-gate
305*7c478bd9Sstevel@tonic-gate static int
ptrhash(p)306*7c478bd9Sstevel@tonic-gate ptrhash(p)
307*7c478bd9Sstevel@tonic-gate void *p;
308*7c478bd9Sstevel@tonic-gate {
309*7c478bd9Sstevel@tonic-gate int h;
310*7c478bd9Sstevel@tonic-gate
311*7c478bd9Sstevel@tonic-gate if (sizeof(void*) == 4 && sizeof(unsigned long) == 4)
312*7c478bd9Sstevel@tonic-gate {
313*7c478bd9Sstevel@tonic-gate unsigned long n = (unsigned long)p;
314*7c478bd9Sstevel@tonic-gate
315*7c478bd9Sstevel@tonic-gate h = hashtab[n & 0xFF];
316*7c478bd9Sstevel@tonic-gate h = hashtab[h ^ ((n >> 8) & 0xFF)];
317*7c478bd9Sstevel@tonic-gate h = hashtab[h ^ ((n >> 16) & 0xFF)];
318*7c478bd9Sstevel@tonic-gate h = hashtab[h ^ ((n >> 24) & 0xFF)];
319*7c478bd9Sstevel@tonic-gate }
320*7c478bd9Sstevel@tonic-gate # if 0
321*7c478bd9Sstevel@tonic-gate else if (sizeof(void*) == 8 && sizeof(unsigned long) == 8)
322*7c478bd9Sstevel@tonic-gate {
323*7c478bd9Sstevel@tonic-gate unsigned long n = (unsigned long)p;
324*7c478bd9Sstevel@tonic-gate
325*7c478bd9Sstevel@tonic-gate h = hashtab[n & 0xFF];
326*7c478bd9Sstevel@tonic-gate h = hashtab[h ^ ((n >> 8) & 0xFF)];
327*7c478bd9Sstevel@tonic-gate h = hashtab[h ^ ((n >> 16) & 0xFF)];
328*7c478bd9Sstevel@tonic-gate h = hashtab[h ^ ((n >> 24) & 0xFF)];
329*7c478bd9Sstevel@tonic-gate h = hashtab[h ^ ((n >> 32) & 0xFF)];
330*7c478bd9Sstevel@tonic-gate h = hashtab[h ^ ((n >> 40) & 0xFF)];
331*7c478bd9Sstevel@tonic-gate h = hashtab[h ^ ((n >> 48) & 0xFF)];
332*7c478bd9Sstevel@tonic-gate h = hashtab[h ^ ((n >> 56) & 0xFF)];
333*7c478bd9Sstevel@tonic-gate }
334*7c478bd9Sstevel@tonic-gate # endif /* 0 */
335*7c478bd9Sstevel@tonic-gate else
336*7c478bd9Sstevel@tonic-gate {
337*7c478bd9Sstevel@tonic-gate unsigned char *cp = (unsigned char *)&p;
338*7c478bd9Sstevel@tonic-gate int i;
339*7c478bd9Sstevel@tonic-gate
340*7c478bd9Sstevel@tonic-gate h = 0;
341*7c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof(void*); ++i)
342*7c478bd9Sstevel@tonic-gate h = hashtab[h ^ cp[i]];
343*7c478bd9Sstevel@tonic-gate }
344*7c478bd9Sstevel@tonic-gate return h;
345*7c478bd9Sstevel@tonic-gate }
346*7c478bd9Sstevel@tonic-gate
347*7c478bd9Sstevel@tonic-gate /*
348*7c478bd9Sstevel@tonic-gate ** SM_MALLOC_TAGGED -- wrapper around malloc(), debugging version.
349*7c478bd9Sstevel@tonic-gate **
350*7c478bd9Sstevel@tonic-gate ** Parameters:
351*7c478bd9Sstevel@tonic-gate ** size -- size of requested memory.
352*7c478bd9Sstevel@tonic-gate ** tag -- tag for debugging.
353*7c478bd9Sstevel@tonic-gate ** num -- additional value for debugging.
354*7c478bd9Sstevel@tonic-gate ** group -- heap group for debugging.
355*7c478bd9Sstevel@tonic-gate **
356*7c478bd9Sstevel@tonic-gate ** Returns:
357*7c478bd9Sstevel@tonic-gate ** Pointer to memory region.
358*7c478bd9Sstevel@tonic-gate */
359*7c478bd9Sstevel@tonic-gate
360*7c478bd9Sstevel@tonic-gate void *
sm_malloc_tagged(size,tag,num,group)361*7c478bd9Sstevel@tonic-gate sm_malloc_tagged(size, tag, num, group)
362*7c478bd9Sstevel@tonic-gate size_t size;
363*7c478bd9Sstevel@tonic-gate char *tag;
364*7c478bd9Sstevel@tonic-gate int num;
365*7c478bd9Sstevel@tonic-gate int group;
366*7c478bd9Sstevel@tonic-gate {
367*7c478bd9Sstevel@tonic-gate void *ptr;
368*7c478bd9Sstevel@tonic-gate
369*7c478bd9Sstevel@tonic-gate if (!HEAP_CHECK)
370*7c478bd9Sstevel@tonic-gate {
371*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
372*7c478bd9Sstevel@tonic-gate ptr = malloc(MALLOC_SIZE(size));
373*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
374*7c478bd9Sstevel@tonic-gate return ptr;
375*7c478bd9Sstevel@tonic-gate }
376*7c478bd9Sstevel@tonic-gate
377*7c478bd9Sstevel@tonic-gate if (sm_xtrap_check())
378*7c478bd9Sstevel@tonic-gate return NULL;
379*7c478bd9Sstevel@tonic-gate if (sm_debug_active(&SmHeapLimit, 1)
380*7c478bd9Sstevel@tonic-gate && sm_debug_level(&SmHeapLimit) < SmHeapTotal + size)
381*7c478bd9Sstevel@tonic-gate return NULL;
382*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
383*7c478bd9Sstevel@tonic-gate ptr = malloc(MALLOC_SIZE(size));
384*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
385*7c478bd9Sstevel@tonic-gate if (ptr != NULL && !sm_heap_register(ptr, size, tag, num, group))
386*7c478bd9Sstevel@tonic-gate {
387*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
388*7c478bd9Sstevel@tonic-gate free(ptr);
389*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
390*7c478bd9Sstevel@tonic-gate ptr = NULL;
391*7c478bd9Sstevel@tonic-gate }
392*7c478bd9Sstevel@tonic-gate SmHeapTotal += size;
393*7c478bd9Sstevel@tonic-gate if (SmHeapTotal > SmHeapMaxTotal)
394*7c478bd9Sstevel@tonic-gate SmHeapMaxTotal = SmHeapTotal;
395*7c478bd9Sstevel@tonic-gate return ptr;
396*7c478bd9Sstevel@tonic-gate }
397*7c478bd9Sstevel@tonic-gate
398*7c478bd9Sstevel@tonic-gate /*
399*7c478bd9Sstevel@tonic-gate ** SM_MALLOC_TAGGED_X -- wrapper around malloc(), debugging version.
400*7c478bd9Sstevel@tonic-gate **
401*7c478bd9Sstevel@tonic-gate ** Parameters:
402*7c478bd9Sstevel@tonic-gate ** size -- size of requested memory.
403*7c478bd9Sstevel@tonic-gate ** tag -- tag for debugging.
404*7c478bd9Sstevel@tonic-gate ** num -- additional value for debugging.
405*7c478bd9Sstevel@tonic-gate ** group -- heap group for debugging.
406*7c478bd9Sstevel@tonic-gate **
407*7c478bd9Sstevel@tonic-gate ** Returns:
408*7c478bd9Sstevel@tonic-gate ** Pointer to memory region.
409*7c478bd9Sstevel@tonic-gate **
410*7c478bd9Sstevel@tonic-gate ** Exceptions:
411*7c478bd9Sstevel@tonic-gate ** F:sm_heap -- out of memory
412*7c478bd9Sstevel@tonic-gate */
413*7c478bd9Sstevel@tonic-gate
414*7c478bd9Sstevel@tonic-gate void *
sm_malloc_tagged_x(size,tag,num,group)415*7c478bd9Sstevel@tonic-gate sm_malloc_tagged_x(size, tag, num, group)
416*7c478bd9Sstevel@tonic-gate size_t size;
417*7c478bd9Sstevel@tonic-gate char *tag;
418*7c478bd9Sstevel@tonic-gate int num;
419*7c478bd9Sstevel@tonic-gate int group;
420*7c478bd9Sstevel@tonic-gate {
421*7c478bd9Sstevel@tonic-gate void *ptr;
422*7c478bd9Sstevel@tonic-gate
423*7c478bd9Sstevel@tonic-gate if (!HEAP_CHECK)
424*7c478bd9Sstevel@tonic-gate {
425*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
426*7c478bd9Sstevel@tonic-gate ptr = malloc(MALLOC_SIZE(size));
427*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
428*7c478bd9Sstevel@tonic-gate if (ptr == NULL)
429*7c478bd9Sstevel@tonic-gate sm_exc_raise_x(&SmHeapOutOfMemory);
430*7c478bd9Sstevel@tonic-gate return ptr;
431*7c478bd9Sstevel@tonic-gate }
432*7c478bd9Sstevel@tonic-gate
433*7c478bd9Sstevel@tonic-gate sm_xtrap_raise_x(&SmHeapOutOfMemory);
434*7c478bd9Sstevel@tonic-gate if (sm_debug_active(&SmHeapLimit, 1)
435*7c478bd9Sstevel@tonic-gate && sm_debug_level(&SmHeapLimit) < SmHeapTotal + size)
436*7c478bd9Sstevel@tonic-gate {
437*7c478bd9Sstevel@tonic-gate sm_exc_raise_x(&SmHeapOutOfMemory);
438*7c478bd9Sstevel@tonic-gate }
439*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
440*7c478bd9Sstevel@tonic-gate ptr = malloc(MALLOC_SIZE(size));
441*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
442*7c478bd9Sstevel@tonic-gate if (ptr != NULL && !sm_heap_register(ptr, size, tag, num, group))
443*7c478bd9Sstevel@tonic-gate {
444*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
445*7c478bd9Sstevel@tonic-gate free(ptr);
446*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
447*7c478bd9Sstevel@tonic-gate ptr = NULL;
448*7c478bd9Sstevel@tonic-gate }
449*7c478bd9Sstevel@tonic-gate if (ptr == NULL)
450*7c478bd9Sstevel@tonic-gate sm_exc_raise_x(&SmHeapOutOfMemory);
451*7c478bd9Sstevel@tonic-gate SmHeapTotal += size;
452*7c478bd9Sstevel@tonic-gate if (SmHeapTotal > SmHeapMaxTotal)
453*7c478bd9Sstevel@tonic-gate SmHeapMaxTotal = SmHeapTotal;
454*7c478bd9Sstevel@tonic-gate return ptr;
455*7c478bd9Sstevel@tonic-gate }
456*7c478bd9Sstevel@tonic-gate
457*7c478bd9Sstevel@tonic-gate /*
458*7c478bd9Sstevel@tonic-gate ** SM_HEAP_REGISTER -- register a pointer into the heap for debugging.
459*7c478bd9Sstevel@tonic-gate **
460*7c478bd9Sstevel@tonic-gate ** Parameters:
461*7c478bd9Sstevel@tonic-gate ** ptr -- pointer to register.
462*7c478bd9Sstevel@tonic-gate ** size -- size of requested memory.
463*7c478bd9Sstevel@tonic-gate ** tag -- tag for debugging.
464*7c478bd9Sstevel@tonic-gate ** num -- additional value for debugging.
465*7c478bd9Sstevel@tonic-gate ** group -- heap group for debugging.
466*7c478bd9Sstevel@tonic-gate **
467*7c478bd9Sstevel@tonic-gate ** Returns:
468*7c478bd9Sstevel@tonic-gate ** true iff successfully registered (not yet in table).
469*7c478bd9Sstevel@tonic-gate */
470*7c478bd9Sstevel@tonic-gate
471*7c478bd9Sstevel@tonic-gate bool
sm_heap_register(ptr,size,tag,num,group)472*7c478bd9Sstevel@tonic-gate sm_heap_register(ptr, size, tag, num, group)
473*7c478bd9Sstevel@tonic-gate void *ptr;
474*7c478bd9Sstevel@tonic-gate size_t size;
475*7c478bd9Sstevel@tonic-gate char *tag;
476*7c478bd9Sstevel@tonic-gate int num;
477*7c478bd9Sstevel@tonic-gate int group;
478*7c478bd9Sstevel@tonic-gate {
479*7c478bd9Sstevel@tonic-gate int i;
480*7c478bd9Sstevel@tonic-gate SM_HEAP_ITEM_T *hi;
481*7c478bd9Sstevel@tonic-gate
482*7c478bd9Sstevel@tonic-gate if (!HEAP_CHECK)
483*7c478bd9Sstevel@tonic-gate return true;
484*7c478bd9Sstevel@tonic-gate SM_REQUIRE(ptr != NULL);
485*7c478bd9Sstevel@tonic-gate i = ptrhash(ptr);
486*7c478bd9Sstevel@tonic-gate # if SM_CHECK_REQUIRE
487*7c478bd9Sstevel@tonic-gate
488*7c478bd9Sstevel@tonic-gate /*
489*7c478bd9Sstevel@tonic-gate ** We require that ptr is not already in SmHeapTable.
490*7c478bd9Sstevel@tonic-gate */
491*7c478bd9Sstevel@tonic-gate
492*7c478bd9Sstevel@tonic-gate for (hi = SmHeapTable[i]; hi != NULL; hi = hi->hi_next)
493*7c478bd9Sstevel@tonic-gate {
494*7c478bd9Sstevel@tonic-gate if (hi->hi_ptr == ptr)
495*7c478bd9Sstevel@tonic-gate sm_abort("sm_heap_register: ptr %p is already registered (%s:%d)",
496*7c478bd9Sstevel@tonic-gate ptr, hi->hi_tag, hi->hi_num);
497*7c478bd9Sstevel@tonic-gate }
498*7c478bd9Sstevel@tonic-gate # endif /* SM_CHECK_REQUIRE */
499*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
500*7c478bd9Sstevel@tonic-gate hi = (SM_HEAP_ITEM_T *) malloc(sizeof(SM_HEAP_ITEM_T));
501*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
502*7c478bd9Sstevel@tonic-gate if (hi == NULL)
503*7c478bd9Sstevel@tonic-gate return false;
504*7c478bd9Sstevel@tonic-gate hi->hi_ptr = ptr;
505*7c478bd9Sstevel@tonic-gate hi->hi_size = size;
506*7c478bd9Sstevel@tonic-gate hi->hi_tag = tag;
507*7c478bd9Sstevel@tonic-gate hi->hi_num = num;
508*7c478bd9Sstevel@tonic-gate hi->hi_group = group;
509*7c478bd9Sstevel@tonic-gate hi->hi_next = SmHeapTable[i];
510*7c478bd9Sstevel@tonic-gate SmHeapTable[i] = hi;
511*7c478bd9Sstevel@tonic-gate return true;
512*7c478bd9Sstevel@tonic-gate }
513*7c478bd9Sstevel@tonic-gate /*
514*7c478bd9Sstevel@tonic-gate ** SM_REALLOC -- wrapper for realloc(), debugging version.
515*7c478bd9Sstevel@tonic-gate **
516*7c478bd9Sstevel@tonic-gate ** Parameters:
517*7c478bd9Sstevel@tonic-gate ** ptr -- pointer to old memory area.
518*7c478bd9Sstevel@tonic-gate ** size -- size of requested memory.
519*7c478bd9Sstevel@tonic-gate **
520*7c478bd9Sstevel@tonic-gate ** Returns:
521*7c478bd9Sstevel@tonic-gate ** Pointer to new memory area, NULL on failure.
522*7c478bd9Sstevel@tonic-gate */
523*7c478bd9Sstevel@tonic-gate
524*7c478bd9Sstevel@tonic-gate void *
sm_realloc(ptr,size)525*7c478bd9Sstevel@tonic-gate sm_realloc(ptr, size)
526*7c478bd9Sstevel@tonic-gate void *ptr;
527*7c478bd9Sstevel@tonic-gate size_t size;
528*7c478bd9Sstevel@tonic-gate {
529*7c478bd9Sstevel@tonic-gate void *newptr;
530*7c478bd9Sstevel@tonic-gate SM_HEAP_ITEM_T *hi, **hp;
531*7c478bd9Sstevel@tonic-gate
532*7c478bd9Sstevel@tonic-gate if (!HEAP_CHECK)
533*7c478bd9Sstevel@tonic-gate {
534*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
535*7c478bd9Sstevel@tonic-gate newptr = realloc(ptr, MALLOC_SIZE(size));
536*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
537*7c478bd9Sstevel@tonic-gate return newptr;
538*7c478bd9Sstevel@tonic-gate }
539*7c478bd9Sstevel@tonic-gate
540*7c478bd9Sstevel@tonic-gate if (ptr == NULL)
541*7c478bd9Sstevel@tonic-gate return sm_malloc_tagged(size, "realloc", 0, SmHeapGroup);
542*7c478bd9Sstevel@tonic-gate
543*7c478bd9Sstevel@tonic-gate for (hp = &SmHeapTable[ptrhash(ptr)]; *hp != NULL; hp = &(**hp).hi_next)
544*7c478bd9Sstevel@tonic-gate {
545*7c478bd9Sstevel@tonic-gate if ((**hp).hi_ptr == ptr)
546*7c478bd9Sstevel@tonic-gate {
547*7c478bd9Sstevel@tonic-gate if (sm_xtrap_check())
548*7c478bd9Sstevel@tonic-gate return NULL;
549*7c478bd9Sstevel@tonic-gate hi = *hp;
550*7c478bd9Sstevel@tonic-gate if (sm_debug_active(&SmHeapLimit, 1)
551*7c478bd9Sstevel@tonic-gate && sm_debug_level(&SmHeapLimit)
552*7c478bd9Sstevel@tonic-gate < SmHeapTotal - hi->hi_size + size)
553*7c478bd9Sstevel@tonic-gate {
554*7c478bd9Sstevel@tonic-gate return NULL;
555*7c478bd9Sstevel@tonic-gate }
556*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
557*7c478bd9Sstevel@tonic-gate newptr = realloc(ptr, MALLOC_SIZE(size));
558*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
559*7c478bd9Sstevel@tonic-gate if (newptr == NULL)
560*7c478bd9Sstevel@tonic-gate return NULL;
561*7c478bd9Sstevel@tonic-gate SmHeapTotal = SmHeapTotal - hi->hi_size + size;
562*7c478bd9Sstevel@tonic-gate if (SmHeapTotal > SmHeapMaxTotal)
563*7c478bd9Sstevel@tonic-gate SmHeapMaxTotal = SmHeapTotal;
564*7c478bd9Sstevel@tonic-gate *hp = hi->hi_next;
565*7c478bd9Sstevel@tonic-gate hi->hi_ptr = newptr;
566*7c478bd9Sstevel@tonic-gate hi->hi_size = size;
567*7c478bd9Sstevel@tonic-gate hp = &SmHeapTable[ptrhash(newptr)];
568*7c478bd9Sstevel@tonic-gate hi->hi_next = *hp;
569*7c478bd9Sstevel@tonic-gate *hp = hi;
570*7c478bd9Sstevel@tonic-gate return newptr;
571*7c478bd9Sstevel@tonic-gate }
572*7c478bd9Sstevel@tonic-gate }
573*7c478bd9Sstevel@tonic-gate sm_abort("sm_realloc: bad argument (%p)", ptr);
574*7c478bd9Sstevel@tonic-gate /* NOTREACHED */
575*7c478bd9Sstevel@tonic-gate return NULL; /* keep Irix compiler happy */
576*7c478bd9Sstevel@tonic-gate }
577*7c478bd9Sstevel@tonic-gate
578*7c478bd9Sstevel@tonic-gate /*
579*7c478bd9Sstevel@tonic-gate ** SM_REALLOC_X -- wrapper for realloc(), debugging version.
580*7c478bd9Sstevel@tonic-gate **
581*7c478bd9Sstevel@tonic-gate ** Parameters:
582*7c478bd9Sstevel@tonic-gate ** ptr -- pointer to old memory area.
583*7c478bd9Sstevel@tonic-gate ** size -- size of requested memory.
584*7c478bd9Sstevel@tonic-gate **
585*7c478bd9Sstevel@tonic-gate ** Returns:
586*7c478bd9Sstevel@tonic-gate ** Pointer to new memory area.
587*7c478bd9Sstevel@tonic-gate **
588*7c478bd9Sstevel@tonic-gate ** Exceptions:
589*7c478bd9Sstevel@tonic-gate ** F:sm_heap -- out of memory
590*7c478bd9Sstevel@tonic-gate */
591*7c478bd9Sstevel@tonic-gate
592*7c478bd9Sstevel@tonic-gate void *
sm_realloc_x(ptr,size)593*7c478bd9Sstevel@tonic-gate sm_realloc_x(ptr, size)
594*7c478bd9Sstevel@tonic-gate void *ptr;
595*7c478bd9Sstevel@tonic-gate size_t size;
596*7c478bd9Sstevel@tonic-gate {
597*7c478bd9Sstevel@tonic-gate void *newptr;
598*7c478bd9Sstevel@tonic-gate SM_HEAP_ITEM_T *hi, **hp;
599*7c478bd9Sstevel@tonic-gate
600*7c478bd9Sstevel@tonic-gate if (!HEAP_CHECK)
601*7c478bd9Sstevel@tonic-gate {
602*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
603*7c478bd9Sstevel@tonic-gate newptr = realloc(ptr, MALLOC_SIZE(size));
604*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
605*7c478bd9Sstevel@tonic-gate if (newptr == NULL)
606*7c478bd9Sstevel@tonic-gate sm_exc_raise_x(&SmHeapOutOfMemory);
607*7c478bd9Sstevel@tonic-gate return newptr;
608*7c478bd9Sstevel@tonic-gate }
609*7c478bd9Sstevel@tonic-gate
610*7c478bd9Sstevel@tonic-gate if (ptr == NULL)
611*7c478bd9Sstevel@tonic-gate return sm_malloc_tagged_x(size, "realloc", 0, SmHeapGroup);
612*7c478bd9Sstevel@tonic-gate
613*7c478bd9Sstevel@tonic-gate for (hp = &SmHeapTable[ptrhash(ptr)]; *hp != NULL; hp = &(**hp).hi_next)
614*7c478bd9Sstevel@tonic-gate {
615*7c478bd9Sstevel@tonic-gate if ((**hp).hi_ptr == ptr)
616*7c478bd9Sstevel@tonic-gate {
617*7c478bd9Sstevel@tonic-gate sm_xtrap_raise_x(&SmHeapOutOfMemory);
618*7c478bd9Sstevel@tonic-gate hi = *hp;
619*7c478bd9Sstevel@tonic-gate if (sm_debug_active(&SmHeapLimit, 1)
620*7c478bd9Sstevel@tonic-gate && sm_debug_level(&SmHeapLimit)
621*7c478bd9Sstevel@tonic-gate < SmHeapTotal - hi->hi_size + size)
622*7c478bd9Sstevel@tonic-gate {
623*7c478bd9Sstevel@tonic-gate sm_exc_raise_x(&SmHeapOutOfMemory);
624*7c478bd9Sstevel@tonic-gate }
625*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
626*7c478bd9Sstevel@tonic-gate newptr = realloc(ptr, MALLOC_SIZE(size));
627*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
628*7c478bd9Sstevel@tonic-gate if (newptr == NULL)
629*7c478bd9Sstevel@tonic-gate sm_exc_raise_x(&SmHeapOutOfMemory);
630*7c478bd9Sstevel@tonic-gate SmHeapTotal = SmHeapTotal - hi->hi_size + size;
631*7c478bd9Sstevel@tonic-gate if (SmHeapTotal > SmHeapMaxTotal)
632*7c478bd9Sstevel@tonic-gate SmHeapMaxTotal = SmHeapTotal;
633*7c478bd9Sstevel@tonic-gate *hp = hi->hi_next;
634*7c478bd9Sstevel@tonic-gate hi->hi_ptr = newptr;
635*7c478bd9Sstevel@tonic-gate hi->hi_size = size;
636*7c478bd9Sstevel@tonic-gate hp = &SmHeapTable[ptrhash(newptr)];
637*7c478bd9Sstevel@tonic-gate hi->hi_next = *hp;
638*7c478bd9Sstevel@tonic-gate *hp = hi;
639*7c478bd9Sstevel@tonic-gate return newptr;
640*7c478bd9Sstevel@tonic-gate }
641*7c478bd9Sstevel@tonic-gate }
642*7c478bd9Sstevel@tonic-gate sm_abort("sm_realloc_x: bad argument (%p)", ptr);
643*7c478bd9Sstevel@tonic-gate /* NOTREACHED */
644*7c478bd9Sstevel@tonic-gate return NULL; /* keep Irix compiler happy */
645*7c478bd9Sstevel@tonic-gate }
646*7c478bd9Sstevel@tonic-gate
647*7c478bd9Sstevel@tonic-gate /*
648*7c478bd9Sstevel@tonic-gate ** SM_FREE_TAGGED -- wrapper around free(), debugging version.
649*7c478bd9Sstevel@tonic-gate **
650*7c478bd9Sstevel@tonic-gate ** Parameters:
651*7c478bd9Sstevel@tonic-gate ** ptr -- pointer to memory region.
652*7c478bd9Sstevel@tonic-gate ** tag -- tag for debugging.
653*7c478bd9Sstevel@tonic-gate ** num -- additional value for debugging.
654*7c478bd9Sstevel@tonic-gate **
655*7c478bd9Sstevel@tonic-gate ** Returns:
656*7c478bd9Sstevel@tonic-gate ** none.
657*7c478bd9Sstevel@tonic-gate */
658*7c478bd9Sstevel@tonic-gate
659*7c478bd9Sstevel@tonic-gate void
sm_free_tagged(ptr,tag,num)660*7c478bd9Sstevel@tonic-gate sm_free_tagged(ptr, tag, num)
661*7c478bd9Sstevel@tonic-gate void *ptr;
662*7c478bd9Sstevel@tonic-gate char *tag;
663*7c478bd9Sstevel@tonic-gate int num;
664*7c478bd9Sstevel@tonic-gate {
665*7c478bd9Sstevel@tonic-gate SM_HEAP_ITEM_T **hp;
666*7c478bd9Sstevel@tonic-gate
667*7c478bd9Sstevel@tonic-gate if (ptr == NULL)
668*7c478bd9Sstevel@tonic-gate return;
669*7c478bd9Sstevel@tonic-gate if (!HEAP_CHECK)
670*7c478bd9Sstevel@tonic-gate {
671*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
672*7c478bd9Sstevel@tonic-gate free(ptr);
673*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
674*7c478bd9Sstevel@tonic-gate return;
675*7c478bd9Sstevel@tonic-gate }
676*7c478bd9Sstevel@tonic-gate for (hp = &SmHeapTable[ptrhash(ptr)]; *hp != NULL; hp = &(**hp).hi_next)
677*7c478bd9Sstevel@tonic-gate {
678*7c478bd9Sstevel@tonic-gate if ((**hp).hi_ptr == ptr)
679*7c478bd9Sstevel@tonic-gate {
680*7c478bd9Sstevel@tonic-gate SM_HEAP_ITEM_T *hi = *hp;
681*7c478bd9Sstevel@tonic-gate
682*7c478bd9Sstevel@tonic-gate *hp = hi->hi_next;
683*7c478bd9Sstevel@tonic-gate
684*7c478bd9Sstevel@tonic-gate /*
685*7c478bd9Sstevel@tonic-gate ** Fill the block with zeros before freeing.
686*7c478bd9Sstevel@tonic-gate ** This is intended to catch problems with
687*7c478bd9Sstevel@tonic-gate ** dangling pointers. The block is filled with
688*7c478bd9Sstevel@tonic-gate ** zeros, not with some non-zero value, because
689*7c478bd9Sstevel@tonic-gate ** it is common practice in some C code to store
690*7c478bd9Sstevel@tonic-gate ** a zero in a structure member before freeing the
691*7c478bd9Sstevel@tonic-gate ** structure, as a defense against dangling pointers.
692*7c478bd9Sstevel@tonic-gate */
693*7c478bd9Sstevel@tonic-gate
694*7c478bd9Sstevel@tonic-gate (void) memset(ptr, 0, hi->hi_size);
695*7c478bd9Sstevel@tonic-gate SmHeapTotal -= hi->hi_size;
696*7c478bd9Sstevel@tonic-gate ENTER_CRITICAL();
697*7c478bd9Sstevel@tonic-gate free(ptr);
698*7c478bd9Sstevel@tonic-gate free(hi);
699*7c478bd9Sstevel@tonic-gate LEAVE_CRITICAL();
700*7c478bd9Sstevel@tonic-gate return;
701*7c478bd9Sstevel@tonic-gate }
702*7c478bd9Sstevel@tonic-gate }
703*7c478bd9Sstevel@tonic-gate sm_abort("sm_free: bad argument (%p) (%s:%d)", ptr, tag, num);
704*7c478bd9Sstevel@tonic-gate }
705*7c478bd9Sstevel@tonic-gate
706*7c478bd9Sstevel@tonic-gate /*
707*7c478bd9Sstevel@tonic-gate ** SM_HEAP_CHECKPTR_TAGGED -- check whether ptr is a valid argument to sm_free
708*7c478bd9Sstevel@tonic-gate **
709*7c478bd9Sstevel@tonic-gate ** Parameters:
710*7c478bd9Sstevel@tonic-gate ** ptr -- pointer to memory region.
711*7c478bd9Sstevel@tonic-gate ** tag -- tag for debugging.
712*7c478bd9Sstevel@tonic-gate ** num -- additional value for debugging.
713*7c478bd9Sstevel@tonic-gate **
714*7c478bd9Sstevel@tonic-gate ** Returns:
715*7c478bd9Sstevel@tonic-gate ** none.
716*7c478bd9Sstevel@tonic-gate **
717*7c478bd9Sstevel@tonic-gate ** Side Effects:
718*7c478bd9Sstevel@tonic-gate ** aborts if check fails.
719*7c478bd9Sstevel@tonic-gate */
720*7c478bd9Sstevel@tonic-gate
721*7c478bd9Sstevel@tonic-gate void
sm_heap_checkptr_tagged(ptr,tag,num)722*7c478bd9Sstevel@tonic-gate sm_heap_checkptr_tagged(ptr, tag, num)
723*7c478bd9Sstevel@tonic-gate void *ptr;
724*7c478bd9Sstevel@tonic-gate char *tag;
725*7c478bd9Sstevel@tonic-gate int num;
726*7c478bd9Sstevel@tonic-gate {
727*7c478bd9Sstevel@tonic-gate SM_HEAP_ITEM_T *hp;
728*7c478bd9Sstevel@tonic-gate
729*7c478bd9Sstevel@tonic-gate if (!HEAP_CHECK)
730*7c478bd9Sstevel@tonic-gate return;
731*7c478bd9Sstevel@tonic-gate if (ptr == NULL)
732*7c478bd9Sstevel@tonic-gate return;
733*7c478bd9Sstevel@tonic-gate for (hp = SmHeapTable[ptrhash(ptr)]; hp != NULL; hp = hp->hi_next)
734*7c478bd9Sstevel@tonic-gate {
735*7c478bd9Sstevel@tonic-gate if (hp->hi_ptr == ptr)
736*7c478bd9Sstevel@tonic-gate return;
737*7c478bd9Sstevel@tonic-gate }
738*7c478bd9Sstevel@tonic-gate sm_abort("sm_heap_checkptr(%p): bad ptr (%s:%d)", ptr, tag, num);
739*7c478bd9Sstevel@tonic-gate }
740*7c478bd9Sstevel@tonic-gate
741*7c478bd9Sstevel@tonic-gate /*
742*7c478bd9Sstevel@tonic-gate ** SM_HEAP_REPORT -- output "map" of used heap.
743*7c478bd9Sstevel@tonic-gate **
744*7c478bd9Sstevel@tonic-gate ** Parameters:
745*7c478bd9Sstevel@tonic-gate ** stream -- the file pointer to write to.
746*7c478bd9Sstevel@tonic-gate ** verbosity -- how much info?
747*7c478bd9Sstevel@tonic-gate **
748*7c478bd9Sstevel@tonic-gate ** Returns:
749*7c478bd9Sstevel@tonic-gate ** none.
750*7c478bd9Sstevel@tonic-gate */
751*7c478bd9Sstevel@tonic-gate
752*7c478bd9Sstevel@tonic-gate void
sm_heap_report(stream,verbosity)753*7c478bd9Sstevel@tonic-gate sm_heap_report(stream, verbosity)
754*7c478bd9Sstevel@tonic-gate SM_FILE_T *stream;
755*7c478bd9Sstevel@tonic-gate int verbosity;
756*7c478bd9Sstevel@tonic-gate {
757*7c478bd9Sstevel@tonic-gate int i;
758*7c478bd9Sstevel@tonic-gate unsigned long group0total, group1total, otherstotal, grandtotal;
759*7c478bd9Sstevel@tonic-gate
760*7c478bd9Sstevel@tonic-gate if (!HEAP_CHECK || verbosity <= 0)
761*7c478bd9Sstevel@tonic-gate return;
762*7c478bd9Sstevel@tonic-gate group0total = group1total = otherstotal = grandtotal = 0;
763*7c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof(SmHeapTable) / sizeof(SmHeapTable[0]); ++i)
764*7c478bd9Sstevel@tonic-gate {
765*7c478bd9Sstevel@tonic-gate SM_HEAP_ITEM_T *hi = SmHeapTable[i];
766*7c478bd9Sstevel@tonic-gate
767*7c478bd9Sstevel@tonic-gate while (hi != NULL)
768*7c478bd9Sstevel@tonic-gate {
769*7c478bd9Sstevel@tonic-gate if (verbosity > 2
770*7c478bd9Sstevel@tonic-gate || (verbosity > 1 && hi->hi_group != 0))
771*7c478bd9Sstevel@tonic-gate {
772*7c478bd9Sstevel@tonic-gate sm_io_fprintf(stream, SM_TIME_DEFAULT,
773*7c478bd9Sstevel@tonic-gate "%4d %*lx %7lu bytes",
774*7c478bd9Sstevel@tonic-gate hi->hi_group,
775*7c478bd9Sstevel@tonic-gate (int) sizeof(void *) * 2,
776*7c478bd9Sstevel@tonic-gate (long)hi->hi_ptr,
777*7c478bd9Sstevel@tonic-gate (unsigned long)hi->hi_size);
778*7c478bd9Sstevel@tonic-gate if (hi->hi_tag != NULL)
779*7c478bd9Sstevel@tonic-gate {
780*7c478bd9Sstevel@tonic-gate sm_io_fprintf(stream, SM_TIME_DEFAULT,
781*7c478bd9Sstevel@tonic-gate " %s",
782*7c478bd9Sstevel@tonic-gate hi->hi_tag);
783*7c478bd9Sstevel@tonic-gate if (hi->hi_num)
784*7c478bd9Sstevel@tonic-gate {
785*7c478bd9Sstevel@tonic-gate sm_io_fprintf(stream,
786*7c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT,
787*7c478bd9Sstevel@tonic-gate ":%d",
788*7c478bd9Sstevel@tonic-gate hi->hi_num);
789*7c478bd9Sstevel@tonic-gate }
790*7c478bd9Sstevel@tonic-gate }
791*7c478bd9Sstevel@tonic-gate sm_io_fprintf(stream, SM_TIME_DEFAULT, "\n");
792*7c478bd9Sstevel@tonic-gate }
793*7c478bd9Sstevel@tonic-gate switch (hi->hi_group)
794*7c478bd9Sstevel@tonic-gate {
795*7c478bd9Sstevel@tonic-gate case 0:
796*7c478bd9Sstevel@tonic-gate group0total += hi->hi_size;
797*7c478bd9Sstevel@tonic-gate break;
798*7c478bd9Sstevel@tonic-gate case 1:
799*7c478bd9Sstevel@tonic-gate group1total += hi->hi_size;
800*7c478bd9Sstevel@tonic-gate break;
801*7c478bd9Sstevel@tonic-gate default:
802*7c478bd9Sstevel@tonic-gate otherstotal += hi->hi_size;
803*7c478bd9Sstevel@tonic-gate break;
804*7c478bd9Sstevel@tonic-gate }
805*7c478bd9Sstevel@tonic-gate grandtotal += hi->hi_size;
806*7c478bd9Sstevel@tonic-gate hi = hi->hi_next;
807*7c478bd9Sstevel@tonic-gate }
808*7c478bd9Sstevel@tonic-gate }
809*7c478bd9Sstevel@tonic-gate sm_io_fprintf(stream, SM_TIME_DEFAULT,
810*7c478bd9Sstevel@tonic-gate "heap max=%lu, total=%lu, ",
811*7c478bd9Sstevel@tonic-gate (unsigned long) SmHeapMaxTotal, grandtotal);
812*7c478bd9Sstevel@tonic-gate sm_io_fprintf(stream, SM_TIME_DEFAULT,
813*7c478bd9Sstevel@tonic-gate "group 0=%lu, group 1=%lu, others=%lu\n",
814*7c478bd9Sstevel@tonic-gate group0total, group1total, otherstotal);
815*7c478bd9Sstevel@tonic-gate if (grandtotal != SmHeapTotal)
816*7c478bd9Sstevel@tonic-gate {
817*7c478bd9Sstevel@tonic-gate sm_io_fprintf(stream, SM_TIME_DEFAULT,
818*7c478bd9Sstevel@tonic-gate "BUG => SmHeapTotal: got %lu, expected %lu\n",
819*7c478bd9Sstevel@tonic-gate (unsigned long) SmHeapTotal, grandtotal);
820*7c478bd9Sstevel@tonic-gate }
821*7c478bd9Sstevel@tonic-gate }
822*7c478bd9Sstevel@tonic-gate #endif /* !SM_HEAP_CHECK */
823