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 * 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 * 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 * 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 * 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 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 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 * 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 * 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 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 * 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 * 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 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 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 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