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