140266059SGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro * Copyright (c) 2000-2001, 2004 Proofpoint, Inc. and its suppliers.
340266059SGregory Neil Shapiro * All rights reserved.
440266059SGregory Neil Shapiro *
540266059SGregory Neil Shapiro * By using this file, you agree to the terms and conditions set
640266059SGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of
740266059SGregory Neil Shapiro * the sendmail distribution.
840266059SGregory Neil Shapiro */
940266059SGregory Neil Shapiro
1040266059SGregory Neil Shapiro #include <sm/gen.h>
114313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: heap.c,v 1.52 2013-11-22 20:51:43 ca Exp $")
1240266059SGregory Neil Shapiro
1340266059SGregory Neil Shapiro /*
1440266059SGregory Neil Shapiro ** debugging memory allocation package
1540266059SGregory Neil Shapiro ** See heap.html for documentation.
1640266059SGregory Neil Shapiro */
1740266059SGregory Neil Shapiro
1840266059SGregory Neil Shapiro #include <string.h>
1940266059SGregory Neil Shapiro
2040266059SGregory Neil Shapiro #include <sm/assert.h>
2140266059SGregory Neil Shapiro #include <sm/debug.h>
2240266059SGregory Neil Shapiro #include <sm/exc.h>
2340266059SGregory Neil Shapiro #include <sm/heap.h>
2440266059SGregory Neil Shapiro #include <sm/io.h>
2540266059SGregory Neil Shapiro #include <sm/signal.h>
2640266059SGregory Neil Shapiro #include <sm/xtrap.h>
2740266059SGregory Neil Shapiro
28*2fb4f839SGregory Neil Shapiro #if SM_HEAP_CHECK
29*2fb4f839SGregory Neil Shapiro # include <unistd.h>
30*2fb4f839SGregory Neil Shapiro # include <sm/types.h>
31*2fb4f839SGregory Neil Shapiro # include <sm/time.h>
32*2fb4f839SGregory Neil Shapiro # include <time.h>
33*2fb4f839SGregory Neil Shapiro #endif
34*2fb4f839SGregory Neil Shapiro
3540266059SGregory Neil Shapiro /* undef all macro versions of the "functions" so they can be specified here */
3640266059SGregory Neil Shapiro #undef sm_malloc
3740266059SGregory Neil Shapiro #undef sm_malloc_x
3840266059SGregory Neil Shapiro #undef sm_malloc_tagged
3940266059SGregory Neil Shapiro #undef sm_malloc_tagged_x
4040266059SGregory Neil Shapiro #undef sm_free
4140266059SGregory Neil Shapiro #undef sm_free_tagged
4240266059SGregory Neil Shapiro #undef sm_realloc
4340266059SGregory Neil Shapiro #if SM_HEAP_CHECK
4440266059SGregory Neil Shapiro # undef sm_heap_register
4540266059SGregory Neil Shapiro # undef sm_heap_checkptr
4640266059SGregory Neil Shapiro # undef sm_heap_report
4740266059SGregory Neil Shapiro #endif /* SM_HEAP_CHECK */
4840266059SGregory Neil Shapiro
4940266059SGregory Neil Shapiro #if SM_HEAP_CHECK
5040266059SGregory Neil Shapiro SM_DEBUG_T SmHeapCheck = SM_DEBUG_INITIALIZER("sm_check_heap",
5140266059SGregory Neil Shapiro "@(#)$Debug: sm_check_heap - check sm_malloc, sm_realloc, sm_free calls $");
5240266059SGregory Neil Shapiro # define HEAP_CHECK sm_debug_active(&SmHeapCheck, 1)
53b6bacd31SGregory Neil Shapiro static int ptrhash __P((void *p));
5440266059SGregory Neil Shapiro #endif /* SM_HEAP_CHECK */
5540266059SGregory Neil Shapiro
5640266059SGregory Neil Shapiro const SM_EXC_TYPE_T SmHeapOutOfMemoryType =
5740266059SGregory Neil Shapiro {
5840266059SGregory Neil Shapiro SmExcTypeMagic,
5940266059SGregory Neil Shapiro "F:sm.heap",
6040266059SGregory Neil Shapiro "",
6140266059SGregory Neil Shapiro sm_etype_printf,
6240266059SGregory Neil Shapiro "out of memory",
6340266059SGregory Neil Shapiro };
6440266059SGregory Neil Shapiro
6540266059SGregory Neil Shapiro SM_EXC_T SmHeapOutOfMemory = SM_EXC_INITIALIZER(&SmHeapOutOfMemoryType, NULL);
6640266059SGregory Neil Shapiro
6740266059SGregory Neil Shapiro
6840266059SGregory Neil Shapiro /*
6940266059SGregory Neil Shapiro ** The behaviour of malloc with size==0 is platform dependent (it
7040266059SGregory Neil Shapiro ** says so in the C standard): it can return NULL or non-NULL. We
7140266059SGregory Neil Shapiro ** don't want sm_malloc_x(0) to raise an exception on some platforms
7240266059SGregory Neil Shapiro ** but not others, so this case requires special handling. We've got
7340266059SGregory Neil Shapiro ** two choices: "size = 1" or "return NULL". We use the former in the
7440266059SGregory Neil Shapiro ** following.
7540266059SGregory Neil Shapiro ** If we had something like autoconf we could figure out the
7640266059SGregory Neil Shapiro ** behaviour of the platform and either use this hack or just
7740266059SGregory Neil Shapiro ** use size.
7840266059SGregory Neil Shapiro */
7940266059SGregory Neil Shapiro
8040266059SGregory Neil Shapiro #define MALLOC_SIZE(size) ((size) == 0 ? 1 : (size))
8140266059SGregory Neil Shapiro
8240266059SGregory Neil Shapiro /*
8340266059SGregory Neil Shapiro ** SM_MALLOC_X -- wrapper around malloc(), raises an exception on error.
8440266059SGregory Neil Shapiro **
8540266059SGregory Neil Shapiro ** Parameters:
8640266059SGregory Neil Shapiro ** size -- size of requested memory.
8740266059SGregory Neil Shapiro **
8840266059SGregory Neil Shapiro ** Returns:
8940266059SGregory Neil Shapiro ** Pointer to memory region.
9040266059SGregory Neil Shapiro **
9140266059SGregory Neil Shapiro ** Note:
9240266059SGregory Neil Shapiro ** sm_malloc_x only gets called from source files in which heap
9340266059SGregory Neil Shapiro ** debugging is disabled at compile time. Otherwise, a call to
9440266059SGregory Neil Shapiro ** sm_malloc_x is macro expanded to a call to sm_malloc_tagged_x.
9540266059SGregory Neil Shapiro **
9640266059SGregory Neil Shapiro ** Exceptions:
9740266059SGregory Neil Shapiro ** F:sm_heap -- out of memory
9840266059SGregory Neil Shapiro */
9940266059SGregory Neil Shapiro
10040266059SGregory Neil Shapiro void *
sm_malloc_x(size)10140266059SGregory Neil Shapiro sm_malloc_x(size)
10240266059SGregory Neil Shapiro size_t size;
10340266059SGregory Neil Shapiro {
10440266059SGregory Neil Shapiro void *ptr;
10540266059SGregory Neil Shapiro
10640266059SGregory Neil Shapiro ENTER_CRITICAL();
10740266059SGregory Neil Shapiro ptr = malloc(MALLOC_SIZE(size));
10840266059SGregory Neil Shapiro LEAVE_CRITICAL();
10940266059SGregory Neil Shapiro if (ptr == NULL)
11040266059SGregory Neil Shapiro sm_exc_raise_x(&SmHeapOutOfMemory);
11140266059SGregory Neil Shapiro return ptr;
11240266059SGregory Neil Shapiro }
11340266059SGregory Neil Shapiro
11440266059SGregory Neil Shapiro #if !SM_HEAP_CHECK
11540266059SGregory Neil Shapiro
11640266059SGregory Neil Shapiro /*
11740266059SGregory Neil Shapiro ** SM_MALLOC -- wrapper around malloc()
11840266059SGregory Neil Shapiro **
11940266059SGregory Neil Shapiro ** Parameters:
12040266059SGregory Neil Shapiro ** size -- size of requested memory.
12140266059SGregory Neil Shapiro **
12240266059SGregory Neil Shapiro ** Returns:
12340266059SGregory Neil Shapiro ** Pointer to memory region.
12440266059SGregory Neil Shapiro */
12540266059SGregory Neil Shapiro
12640266059SGregory Neil Shapiro void *
sm_malloc(size)12740266059SGregory Neil Shapiro sm_malloc(size)
12840266059SGregory Neil Shapiro size_t size;
12940266059SGregory Neil Shapiro {
13040266059SGregory Neil Shapiro void *ptr;
13140266059SGregory Neil Shapiro
13240266059SGregory Neil Shapiro ENTER_CRITICAL();
13340266059SGregory Neil Shapiro ptr = malloc(MALLOC_SIZE(size));
13440266059SGregory Neil Shapiro LEAVE_CRITICAL();
13540266059SGregory Neil Shapiro return ptr;
13640266059SGregory Neil Shapiro }
13740266059SGregory Neil Shapiro
13840266059SGregory Neil Shapiro /*
13940266059SGregory Neil Shapiro ** SM_REALLOC -- wrapper for realloc()
14040266059SGregory Neil Shapiro **
14140266059SGregory Neil Shapiro ** Parameters:
14240266059SGregory Neil Shapiro ** ptr -- pointer to old memory area.
14340266059SGregory Neil Shapiro ** size -- size of requested memory.
14440266059SGregory Neil Shapiro **
14540266059SGregory Neil Shapiro ** Returns:
14640266059SGregory Neil Shapiro ** Pointer to new memory area, NULL on failure.
14740266059SGregory Neil Shapiro */
14840266059SGregory Neil Shapiro
14940266059SGregory Neil Shapiro void *
sm_realloc(ptr,size)15040266059SGregory Neil Shapiro sm_realloc(ptr, size)
15140266059SGregory Neil Shapiro void *ptr;
15240266059SGregory Neil Shapiro size_t size;
15340266059SGregory Neil Shapiro {
15440266059SGregory Neil Shapiro void *newptr;
15540266059SGregory Neil Shapiro
15640266059SGregory Neil Shapiro ENTER_CRITICAL();
15740266059SGregory Neil Shapiro newptr = realloc(ptr, MALLOC_SIZE(size));
15840266059SGregory Neil Shapiro LEAVE_CRITICAL();
15940266059SGregory Neil Shapiro return newptr;
16040266059SGregory Neil Shapiro }
16140266059SGregory Neil Shapiro
16240266059SGregory Neil Shapiro /*
16340266059SGregory Neil Shapiro ** SM_REALLOC_X -- wrapper for realloc()
16440266059SGregory Neil Shapiro **
16540266059SGregory Neil Shapiro ** Parameters:
16640266059SGregory Neil Shapiro ** ptr -- pointer to old memory area.
16740266059SGregory Neil Shapiro ** size -- size of requested memory.
16840266059SGregory Neil Shapiro **
16940266059SGregory Neil Shapiro ** Returns:
17040266059SGregory Neil Shapiro ** Pointer to new memory area.
17140266059SGregory Neil Shapiro **
17240266059SGregory Neil Shapiro ** Exceptions:
17340266059SGregory Neil Shapiro ** F:sm_heap -- out of memory
17440266059SGregory Neil Shapiro */
17540266059SGregory Neil Shapiro
17640266059SGregory Neil Shapiro void *
sm_realloc_x(ptr,size)17740266059SGregory Neil Shapiro sm_realloc_x(ptr, size)
17840266059SGregory Neil Shapiro void *ptr;
17940266059SGregory Neil Shapiro size_t size;
18040266059SGregory Neil Shapiro {
18140266059SGregory Neil Shapiro void *newptr;
18240266059SGregory Neil Shapiro
18340266059SGregory Neil Shapiro ENTER_CRITICAL();
18440266059SGregory Neil Shapiro newptr = realloc(ptr, MALLOC_SIZE(size));
18540266059SGregory Neil Shapiro LEAVE_CRITICAL();
18640266059SGregory Neil Shapiro if (newptr == NULL)
18740266059SGregory Neil Shapiro sm_exc_raise_x(&SmHeapOutOfMemory);
18840266059SGregory Neil Shapiro return newptr;
18940266059SGregory Neil Shapiro }
19040266059SGregory Neil Shapiro /*
19140266059SGregory Neil Shapiro ** SM_FREE -- wrapper around free()
19240266059SGregory Neil Shapiro **
19340266059SGregory Neil Shapiro ** Parameters:
19440266059SGregory Neil Shapiro ** ptr -- pointer to memory region.
19540266059SGregory Neil Shapiro **
19640266059SGregory Neil Shapiro ** Returns:
19740266059SGregory Neil Shapiro ** none.
19840266059SGregory Neil Shapiro */
19940266059SGregory Neil Shapiro
20040266059SGregory Neil Shapiro void
sm_free(ptr)20140266059SGregory Neil Shapiro sm_free(ptr)
20240266059SGregory Neil Shapiro void *ptr;
20340266059SGregory Neil Shapiro {
20440266059SGregory Neil Shapiro if (ptr == NULL)
20540266059SGregory Neil Shapiro return;
20640266059SGregory Neil Shapiro ENTER_CRITICAL();
20740266059SGregory Neil Shapiro free(ptr);
20840266059SGregory Neil Shapiro LEAVE_CRITICAL();
20940266059SGregory Neil Shapiro return;
21040266059SGregory Neil Shapiro }
21140266059SGregory Neil Shapiro
21240266059SGregory Neil Shapiro #else /* !SM_HEAP_CHECK */
21340266059SGregory Neil Shapiro
21440266059SGregory Neil Shapiro /*
21540266059SGregory Neil Shapiro ** Each allocated block is assigned a "group number".
21640266059SGregory Neil Shapiro ** By default, all blocks are assigned to group #1.
21740266059SGregory Neil Shapiro ** By convention, group #0 is for memory that is never freed.
21840266059SGregory Neil Shapiro ** You can use group numbers any way you want, in order to help make
21940266059SGregory Neil Shapiro ** sense of sm_heap_report output.
22040266059SGregory Neil Shapiro */
22140266059SGregory Neil Shapiro
22240266059SGregory Neil Shapiro int SmHeapGroup = 1;
22340266059SGregory Neil Shapiro int SmHeapMaxGroup = 1;
22440266059SGregory Neil Shapiro
22540266059SGregory Neil Shapiro /*
22640266059SGregory Neil Shapiro ** Total number of bytes allocated.
22740266059SGregory Neil Shapiro ** This is only maintained if the sm_check_heap debug category is active.
22840266059SGregory Neil Shapiro */
22940266059SGregory Neil Shapiro
23040266059SGregory Neil Shapiro size_t SmHeapTotal = 0;
23140266059SGregory Neil Shapiro
23240266059SGregory Neil Shapiro /*
23340266059SGregory Neil Shapiro ** High water mark: the most that SmHeapTotal has ever been.
23440266059SGregory Neil Shapiro */
23540266059SGregory Neil Shapiro
23640266059SGregory Neil Shapiro size_t SmHeapMaxTotal = 0;
23740266059SGregory Neil Shapiro
23840266059SGregory Neil Shapiro /*
23940266059SGregory Neil Shapiro ** Maximum number of bytes that may be allocated at any one time.
24040266059SGregory Neil Shapiro ** 0 means no limit.
24140266059SGregory Neil Shapiro ** This is only honoured if sm_check_heap is active.
24240266059SGregory Neil Shapiro */
24340266059SGregory Neil Shapiro
24440266059SGregory Neil Shapiro SM_DEBUG_T SmHeapLimit = SM_DEBUG_INITIALIZER("sm_heap_limit",
24540266059SGregory Neil Shapiro "@(#)$Debug: sm_heap_limit - max # of bytes permitted in heap $");
24640266059SGregory Neil Shapiro
24740266059SGregory Neil Shapiro /*
24840266059SGregory Neil Shapiro ** This is the data structure that keeps track of all currently
24940266059SGregory Neil Shapiro ** allocated blocks of memory known to the heap package.
25040266059SGregory Neil Shapiro */
25140266059SGregory Neil Shapiro
25240266059SGregory Neil Shapiro typedef struct sm_heap_item SM_HEAP_ITEM_T;
25340266059SGregory Neil Shapiro struct sm_heap_item
25440266059SGregory Neil Shapiro {
25540266059SGregory Neil Shapiro void *hi_ptr;
25640266059SGregory Neil Shapiro size_t hi_size;
25740266059SGregory Neil Shapiro char *hi_tag;
25840266059SGregory Neil Shapiro int hi_num;
25940266059SGregory Neil Shapiro int hi_group;
26040266059SGregory Neil Shapiro SM_HEAP_ITEM_T *hi_next;
26140266059SGregory Neil Shapiro };
26240266059SGregory Neil Shapiro
26340266059SGregory Neil Shapiro #define SM_HEAP_TABLE_SIZE 256
26440266059SGregory Neil Shapiro static SM_HEAP_ITEM_T *SmHeapTable[SM_HEAP_TABLE_SIZE];
26540266059SGregory Neil Shapiro
26640266059SGregory Neil Shapiro /*
26740266059SGregory Neil Shapiro ** This is a randomly generated table
26840266059SGregory Neil Shapiro ** which contains exactly one occurrence
26940266059SGregory Neil Shapiro ** of each of the numbers between 0 and 255.
27040266059SGregory Neil Shapiro ** It is used by ptrhash.
27140266059SGregory Neil Shapiro */
27240266059SGregory Neil Shapiro
27340266059SGregory Neil Shapiro static unsigned char hashtab[SM_HEAP_TABLE_SIZE] =
27440266059SGregory Neil Shapiro {
27540266059SGregory Neil Shapiro 161, 71, 77,187, 15,229, 9,176,221,119,239, 21, 85,138,203, 86,
27640266059SGregory Neil Shapiro 102, 65, 80,199,235, 32,140, 96,224, 78,126,127,144, 0, 11,179,
27740266059SGregory Neil Shapiro 64, 30,120, 23,225,226, 33, 50,205,167,130,240,174, 99,206, 73,
27840266059SGregory Neil Shapiro 231,210,189,162, 48, 93,246, 54,213,141,135, 39, 41,192,236,193,
27940266059SGregory Neil Shapiro 157, 88, 95,104,188, 63,133,177,234,110,158,214,238,131,233, 91,
28040266059SGregory Neil Shapiro 125, 82, 94, 79, 66, 92,151, 45,252, 98, 26,183, 7,191,171,106,
28140266059SGregory Neil Shapiro 145,154,251,100,113, 5, 74, 62, 76,124, 14,217,200, 75,115,190,
28240266059SGregory Neil Shapiro 103, 28,198,196,169,219, 37,118,150, 18,152,175, 49,136, 6,142,
28340266059SGregory Neil Shapiro 89, 19,243,254, 47,137, 24,166,180, 10, 40,186,202, 46,184, 67,
28440266059SGregory Neil Shapiro 148,108,181, 81, 25,241, 13,139, 58, 38, 84,253,201, 12,116, 17,
28540266059SGregory Neil Shapiro 195, 22,112, 69,255, 43,147,222,111, 56,194,216,149,244, 42,173,
28640266059SGregory Neil Shapiro 232,220,249,105,207, 51,197,242, 72,211,208, 59,122,230,237,170,
28740266059SGregory Neil Shapiro 165, 44, 68,123,129,245,143,101, 8,209,215,247,185, 57,218, 53,
28840266059SGregory Neil Shapiro 114,121, 3,128, 4,204,212,146, 2,155, 83,250, 87, 29, 31,159,
28940266059SGregory Neil Shapiro 60, 27,107,156,227,182, 1, 61, 36,160,109, 97, 90, 20,168,132,
29040266059SGregory Neil Shapiro 223,248, 70,164, 55,172, 34, 52,163,117, 35,153,134, 16,178,228
29140266059SGregory Neil Shapiro };
29240266059SGregory Neil Shapiro
29340266059SGregory Neil Shapiro /*
29440266059SGregory Neil Shapiro ** PTRHASH -- hash a pointer value
29540266059SGregory Neil Shapiro **
29640266059SGregory Neil Shapiro ** Parameters:
29740266059SGregory Neil Shapiro ** p -- pointer.
29840266059SGregory Neil Shapiro **
29940266059SGregory Neil Shapiro ** Returns:
30040266059SGregory Neil Shapiro ** hash value.
30140266059SGregory Neil Shapiro **
30240266059SGregory Neil Shapiro ** ptrhash hashes a pointer value to a uniformly distributed random
30340266059SGregory Neil Shapiro ** number between 0 and 255.
30440266059SGregory Neil Shapiro **
30540266059SGregory Neil Shapiro ** This hash algorithm is based on Peter K. Pearson,
30640266059SGregory Neil Shapiro ** "Fast Hashing of Variable-Length Text Strings",
30740266059SGregory Neil Shapiro ** in Communications of the ACM, June 1990, vol 33 no 6.
30840266059SGregory Neil Shapiro */
30940266059SGregory Neil Shapiro
31040266059SGregory Neil Shapiro static int
ptrhash(p)31140266059SGregory Neil Shapiro ptrhash(p)
31240266059SGregory Neil Shapiro void *p;
31340266059SGregory Neil Shapiro {
31440266059SGregory Neil Shapiro int h;
31540266059SGregory Neil Shapiro
31640266059SGregory Neil Shapiro if (sizeof(void*) == 4 && sizeof(unsigned long) == 4)
31740266059SGregory Neil Shapiro {
31840266059SGregory Neil Shapiro unsigned long n = (unsigned long)p;
31940266059SGregory Neil Shapiro
32040266059SGregory Neil Shapiro h = hashtab[n & 0xFF];
32140266059SGregory Neil Shapiro h = hashtab[h ^ ((n >> 8) & 0xFF)];
32240266059SGregory Neil Shapiro h = hashtab[h ^ ((n >> 16) & 0xFF)];
32340266059SGregory Neil Shapiro h = hashtab[h ^ ((n >> 24) & 0xFF)];
32440266059SGregory Neil Shapiro }
32540266059SGregory Neil Shapiro # if 0
32640266059SGregory Neil Shapiro else if (sizeof(void*) == 8 && sizeof(unsigned long) == 8)
32740266059SGregory Neil Shapiro {
32840266059SGregory Neil Shapiro unsigned long n = (unsigned long)p;
32940266059SGregory Neil Shapiro
33040266059SGregory Neil Shapiro h = hashtab[n & 0xFF];
33140266059SGregory Neil Shapiro h = hashtab[h ^ ((n >> 8) & 0xFF)];
33240266059SGregory Neil Shapiro h = hashtab[h ^ ((n >> 16) & 0xFF)];
33340266059SGregory Neil Shapiro h = hashtab[h ^ ((n >> 24) & 0xFF)];
33440266059SGregory Neil Shapiro h = hashtab[h ^ ((n >> 32) & 0xFF)];
33540266059SGregory Neil Shapiro h = hashtab[h ^ ((n >> 40) & 0xFF)];
33640266059SGregory Neil Shapiro h = hashtab[h ^ ((n >> 48) & 0xFF)];
33740266059SGregory Neil Shapiro h = hashtab[h ^ ((n >> 56) & 0xFF)];
33840266059SGregory Neil Shapiro }
33940266059SGregory Neil Shapiro # endif /* 0 */
34040266059SGregory Neil Shapiro else
34140266059SGregory Neil Shapiro {
34240266059SGregory Neil Shapiro unsigned char *cp = (unsigned char *)&p;
34340266059SGregory Neil Shapiro int i;
34440266059SGregory Neil Shapiro
34540266059SGregory Neil Shapiro h = 0;
34640266059SGregory Neil Shapiro for (i = 0; i < sizeof(void*); ++i)
34740266059SGregory Neil Shapiro h = hashtab[h ^ cp[i]];
34840266059SGregory Neil Shapiro }
34940266059SGregory Neil Shapiro return h;
35040266059SGregory Neil Shapiro }
35140266059SGregory Neil Shapiro
35240266059SGregory Neil Shapiro /*
35340266059SGregory Neil Shapiro ** SM_MALLOC_TAGGED -- wrapper around malloc(), debugging version.
35440266059SGregory Neil Shapiro **
35540266059SGregory Neil Shapiro ** Parameters:
35640266059SGregory Neil Shapiro ** size -- size of requested memory.
35740266059SGregory Neil Shapiro ** tag -- tag for debugging.
35840266059SGregory Neil Shapiro ** num -- additional value for debugging.
35940266059SGregory Neil Shapiro ** group -- heap group for debugging.
36040266059SGregory Neil Shapiro **
36140266059SGregory Neil Shapiro ** Returns:
36240266059SGregory Neil Shapiro ** Pointer to memory region.
36340266059SGregory Neil Shapiro */
36440266059SGregory Neil Shapiro
36540266059SGregory Neil Shapiro void *
sm_malloc_tagged(size,tag,num,group)36640266059SGregory Neil Shapiro sm_malloc_tagged(size, tag, num, group)
36740266059SGregory Neil Shapiro size_t size;
36840266059SGregory Neil Shapiro char *tag;
36940266059SGregory Neil Shapiro int num;
37040266059SGregory Neil Shapiro int group;
37140266059SGregory Neil Shapiro {
37240266059SGregory Neil Shapiro void *ptr;
37340266059SGregory Neil Shapiro
37440266059SGregory Neil Shapiro if (!HEAP_CHECK)
37540266059SGregory Neil Shapiro {
37640266059SGregory Neil Shapiro ENTER_CRITICAL();
37740266059SGregory Neil Shapiro ptr = malloc(MALLOC_SIZE(size));
37840266059SGregory Neil Shapiro LEAVE_CRITICAL();
37940266059SGregory Neil Shapiro return ptr;
38040266059SGregory Neil Shapiro }
38140266059SGregory Neil Shapiro
38240266059SGregory Neil Shapiro if (sm_xtrap_check())
38340266059SGregory Neil Shapiro return NULL;
38440266059SGregory Neil Shapiro if (sm_debug_active(&SmHeapLimit, 1)
38540266059SGregory Neil Shapiro && sm_debug_level(&SmHeapLimit) < SmHeapTotal + size)
38640266059SGregory Neil Shapiro return NULL;
38740266059SGregory Neil Shapiro ENTER_CRITICAL();
38840266059SGregory Neil Shapiro ptr = malloc(MALLOC_SIZE(size));
38940266059SGregory Neil Shapiro LEAVE_CRITICAL();
39040266059SGregory Neil Shapiro if (ptr != NULL && !sm_heap_register(ptr, size, tag, num, group))
39140266059SGregory Neil Shapiro {
39240266059SGregory Neil Shapiro ENTER_CRITICAL();
39340266059SGregory Neil Shapiro free(ptr);
39440266059SGregory Neil Shapiro LEAVE_CRITICAL();
39540266059SGregory Neil Shapiro ptr = NULL;
39640266059SGregory Neil Shapiro }
39740266059SGregory Neil Shapiro SmHeapTotal += size;
39840266059SGregory Neil Shapiro if (SmHeapTotal > SmHeapMaxTotal)
39940266059SGregory Neil Shapiro SmHeapMaxTotal = SmHeapTotal;
40040266059SGregory Neil Shapiro return ptr;
40140266059SGregory Neil Shapiro }
40240266059SGregory Neil Shapiro
40340266059SGregory Neil Shapiro /*
40440266059SGregory Neil Shapiro ** SM_MALLOC_TAGGED_X -- wrapper around malloc(), debugging version.
40540266059SGregory Neil Shapiro **
40640266059SGregory Neil Shapiro ** Parameters:
40740266059SGregory Neil Shapiro ** size -- size of requested memory.
40840266059SGregory Neil Shapiro ** tag -- tag for debugging.
40940266059SGregory Neil Shapiro ** num -- additional value for debugging.
41040266059SGregory Neil Shapiro ** group -- heap group for debugging.
41140266059SGregory Neil Shapiro **
41240266059SGregory Neil Shapiro ** Returns:
41340266059SGregory Neil Shapiro ** Pointer to memory region.
41440266059SGregory Neil Shapiro **
41540266059SGregory Neil Shapiro ** Exceptions:
41640266059SGregory Neil Shapiro ** F:sm_heap -- out of memory
41740266059SGregory Neil Shapiro */
41840266059SGregory Neil Shapiro
41940266059SGregory Neil Shapiro void *
sm_malloc_tagged_x(size,tag,num,group)42040266059SGregory Neil Shapiro sm_malloc_tagged_x(size, tag, num, group)
42140266059SGregory Neil Shapiro size_t size;
42240266059SGregory Neil Shapiro char *tag;
42340266059SGregory Neil Shapiro int num;
42440266059SGregory Neil Shapiro int group;
42540266059SGregory Neil Shapiro {
42640266059SGregory Neil Shapiro void *ptr;
42740266059SGregory Neil Shapiro
42840266059SGregory Neil Shapiro if (!HEAP_CHECK)
42940266059SGregory Neil Shapiro {
43040266059SGregory Neil Shapiro ENTER_CRITICAL();
43140266059SGregory Neil Shapiro ptr = malloc(MALLOC_SIZE(size));
43240266059SGregory Neil Shapiro LEAVE_CRITICAL();
43340266059SGregory Neil Shapiro if (ptr == NULL)
43440266059SGregory Neil Shapiro sm_exc_raise_x(&SmHeapOutOfMemory);
43540266059SGregory Neil Shapiro return ptr;
43640266059SGregory Neil Shapiro }
43740266059SGregory Neil Shapiro
43840266059SGregory Neil Shapiro sm_xtrap_raise_x(&SmHeapOutOfMemory);
43940266059SGregory Neil Shapiro if (sm_debug_active(&SmHeapLimit, 1)
44040266059SGregory Neil Shapiro && sm_debug_level(&SmHeapLimit) < SmHeapTotal + size)
44140266059SGregory Neil Shapiro {
44240266059SGregory Neil Shapiro sm_exc_raise_x(&SmHeapOutOfMemory);
44340266059SGregory Neil Shapiro }
44440266059SGregory Neil Shapiro ENTER_CRITICAL();
44540266059SGregory Neil Shapiro ptr = malloc(MALLOC_SIZE(size));
44640266059SGregory Neil Shapiro LEAVE_CRITICAL();
44740266059SGregory Neil Shapiro if (ptr != NULL && !sm_heap_register(ptr, size, tag, num, group))
44840266059SGregory Neil Shapiro {
44940266059SGregory Neil Shapiro ENTER_CRITICAL();
45040266059SGregory Neil Shapiro free(ptr);
45140266059SGregory Neil Shapiro LEAVE_CRITICAL();
45240266059SGregory Neil Shapiro ptr = NULL;
45340266059SGregory Neil Shapiro }
45440266059SGregory Neil Shapiro if (ptr == NULL)
45540266059SGregory Neil Shapiro sm_exc_raise_x(&SmHeapOutOfMemory);
45640266059SGregory Neil Shapiro SmHeapTotal += size;
45740266059SGregory Neil Shapiro if (SmHeapTotal > SmHeapMaxTotal)
45840266059SGregory Neil Shapiro SmHeapMaxTotal = SmHeapTotal;
45940266059SGregory Neil Shapiro return ptr;
46040266059SGregory Neil Shapiro }
46140266059SGregory Neil Shapiro
46240266059SGregory Neil Shapiro /*
46340266059SGregory Neil Shapiro ** SM_HEAP_REGISTER -- register a pointer into the heap for debugging.
46440266059SGregory Neil Shapiro **
46540266059SGregory Neil Shapiro ** Parameters:
46640266059SGregory Neil Shapiro ** ptr -- pointer to register.
46740266059SGregory Neil Shapiro ** size -- size of requested memory.
468*2fb4f839SGregory Neil Shapiro ** tag -- tag for debugging (this is NOT copied!)
46940266059SGregory Neil Shapiro ** num -- additional value for debugging.
47040266059SGregory Neil Shapiro ** group -- heap group for debugging.
47140266059SGregory Neil Shapiro **
47240266059SGregory Neil Shapiro ** Returns:
47340266059SGregory Neil Shapiro ** true iff successfully registered (not yet in table).
47440266059SGregory Neil Shapiro */
47540266059SGregory Neil Shapiro
47640266059SGregory Neil Shapiro bool
sm_heap_register(ptr,size,tag,num,group)47740266059SGregory Neil Shapiro sm_heap_register(ptr, size, tag, num, group)
47840266059SGregory Neil Shapiro void *ptr;
47940266059SGregory Neil Shapiro size_t size;
48040266059SGregory Neil Shapiro char *tag;
48140266059SGregory Neil Shapiro int num;
48240266059SGregory Neil Shapiro int group;
48340266059SGregory Neil Shapiro {
48440266059SGregory Neil Shapiro int i;
48540266059SGregory Neil Shapiro SM_HEAP_ITEM_T *hi;
48640266059SGregory Neil Shapiro
48740266059SGregory Neil Shapiro if (!HEAP_CHECK)
48840266059SGregory Neil Shapiro return true;
48940266059SGregory Neil Shapiro SM_REQUIRE(ptr != NULL);
49040266059SGregory Neil Shapiro i = ptrhash(ptr);
49140266059SGregory Neil Shapiro # if SM_CHECK_REQUIRE
49240266059SGregory Neil Shapiro
49340266059SGregory Neil Shapiro /*
49440266059SGregory Neil Shapiro ** We require that ptr is not already in SmHeapTable.
49540266059SGregory Neil Shapiro */
49640266059SGregory Neil Shapiro
49740266059SGregory Neil Shapiro for (hi = SmHeapTable[i]; hi != NULL; hi = hi->hi_next)
49840266059SGregory Neil Shapiro {
49940266059SGregory Neil Shapiro if (hi->hi_ptr == ptr)
50040266059SGregory Neil Shapiro sm_abort("sm_heap_register: ptr %p is already registered (%s:%d)",
50140266059SGregory Neil Shapiro ptr, hi->hi_tag, hi->hi_num);
50240266059SGregory Neil Shapiro }
50340266059SGregory Neil Shapiro # endif /* SM_CHECK_REQUIRE */
50440266059SGregory Neil Shapiro ENTER_CRITICAL();
50540266059SGregory Neil Shapiro hi = (SM_HEAP_ITEM_T *) malloc(sizeof(SM_HEAP_ITEM_T));
50640266059SGregory Neil Shapiro LEAVE_CRITICAL();
50740266059SGregory Neil Shapiro if (hi == NULL)
50840266059SGregory Neil Shapiro return false;
50940266059SGregory Neil Shapiro hi->hi_ptr = ptr;
51040266059SGregory Neil Shapiro hi->hi_size = size;
51140266059SGregory Neil Shapiro hi->hi_tag = tag;
51240266059SGregory Neil Shapiro hi->hi_num = num;
51340266059SGregory Neil Shapiro hi->hi_group = group;
51440266059SGregory Neil Shapiro hi->hi_next = SmHeapTable[i];
51540266059SGregory Neil Shapiro SmHeapTable[i] = hi;
51640266059SGregory Neil Shapiro return true;
51740266059SGregory Neil Shapiro }
51840266059SGregory Neil Shapiro /*
51940266059SGregory Neil Shapiro ** SM_REALLOC -- wrapper for realloc(), debugging version.
52040266059SGregory Neil Shapiro **
52140266059SGregory Neil Shapiro ** Parameters:
52240266059SGregory Neil Shapiro ** ptr -- pointer to old memory area.
52340266059SGregory Neil Shapiro ** size -- size of requested memory.
52440266059SGregory Neil Shapiro **
52540266059SGregory Neil Shapiro ** Returns:
52640266059SGregory Neil Shapiro ** Pointer to new memory area, NULL on failure.
52740266059SGregory Neil Shapiro */
52840266059SGregory Neil Shapiro
52940266059SGregory Neil Shapiro void *
sm_realloc(ptr,size)53040266059SGregory Neil Shapiro sm_realloc(ptr, size)
53140266059SGregory Neil Shapiro void *ptr;
53240266059SGregory Neil Shapiro size_t size;
53340266059SGregory Neil Shapiro {
53440266059SGregory Neil Shapiro void *newptr;
53540266059SGregory Neil Shapiro SM_HEAP_ITEM_T *hi, **hp;
53640266059SGregory Neil Shapiro
53740266059SGregory Neil Shapiro if (!HEAP_CHECK)
53840266059SGregory Neil Shapiro {
53940266059SGregory Neil Shapiro ENTER_CRITICAL();
54040266059SGregory Neil Shapiro newptr = realloc(ptr, MALLOC_SIZE(size));
54140266059SGregory Neil Shapiro LEAVE_CRITICAL();
54240266059SGregory Neil Shapiro return newptr;
54340266059SGregory Neil Shapiro }
54440266059SGregory Neil Shapiro
54540266059SGregory Neil Shapiro if (ptr == NULL)
54640266059SGregory Neil Shapiro return sm_malloc_tagged(size, "realloc", 0, SmHeapGroup);
54740266059SGregory Neil Shapiro
54840266059SGregory Neil Shapiro for (hp = &SmHeapTable[ptrhash(ptr)]; *hp != NULL; hp = &(**hp).hi_next)
54940266059SGregory Neil Shapiro {
55040266059SGregory Neil Shapiro if ((**hp).hi_ptr == ptr)
55140266059SGregory Neil Shapiro {
55240266059SGregory Neil Shapiro if (sm_xtrap_check())
55340266059SGregory Neil Shapiro return NULL;
55440266059SGregory Neil Shapiro hi = *hp;
55540266059SGregory Neil Shapiro if (sm_debug_active(&SmHeapLimit, 1)
55640266059SGregory Neil Shapiro && sm_debug_level(&SmHeapLimit)
55740266059SGregory Neil Shapiro < SmHeapTotal - hi->hi_size + size)
55840266059SGregory Neil Shapiro {
55940266059SGregory Neil Shapiro return NULL;
56040266059SGregory Neil Shapiro }
56140266059SGregory Neil Shapiro ENTER_CRITICAL();
56240266059SGregory Neil Shapiro newptr = realloc(ptr, MALLOC_SIZE(size));
56340266059SGregory Neil Shapiro LEAVE_CRITICAL();
56440266059SGregory Neil Shapiro if (newptr == NULL)
56540266059SGregory Neil Shapiro return NULL;
56640266059SGregory Neil Shapiro SmHeapTotal = SmHeapTotal - hi->hi_size + size;
56740266059SGregory Neil Shapiro if (SmHeapTotal > SmHeapMaxTotal)
56840266059SGregory Neil Shapiro SmHeapMaxTotal = SmHeapTotal;
56940266059SGregory Neil Shapiro *hp = hi->hi_next;
57040266059SGregory Neil Shapiro hi->hi_ptr = newptr;
57140266059SGregory Neil Shapiro hi->hi_size = size;
57240266059SGregory Neil Shapiro hp = &SmHeapTable[ptrhash(newptr)];
57340266059SGregory Neil Shapiro hi->hi_next = *hp;
57440266059SGregory Neil Shapiro *hp = hi;
57540266059SGregory Neil Shapiro return newptr;
57640266059SGregory Neil Shapiro }
57740266059SGregory Neil Shapiro }
57840266059SGregory Neil Shapiro sm_abort("sm_realloc: bad argument (%p)", ptr);
57940266059SGregory Neil Shapiro /* NOTREACHED */
58040266059SGregory Neil Shapiro return NULL; /* keep Irix compiler happy */
58140266059SGregory Neil Shapiro }
58240266059SGregory Neil Shapiro
58340266059SGregory Neil Shapiro /*
58440266059SGregory Neil Shapiro ** SM_REALLOC_X -- wrapper for realloc(), debugging version.
58540266059SGregory Neil Shapiro **
58640266059SGregory Neil Shapiro ** Parameters:
58740266059SGregory Neil Shapiro ** ptr -- pointer to old memory area.
58840266059SGregory Neil Shapiro ** size -- size of requested memory.
58940266059SGregory Neil Shapiro **
59040266059SGregory Neil Shapiro ** Returns:
59140266059SGregory Neil Shapiro ** Pointer to new memory area.
59240266059SGregory Neil Shapiro **
59340266059SGregory Neil Shapiro ** Exceptions:
59440266059SGregory Neil Shapiro ** F:sm_heap -- out of memory
59540266059SGregory Neil Shapiro */
59640266059SGregory Neil Shapiro
59740266059SGregory Neil Shapiro void *
sm_realloc_x(ptr,size)59840266059SGregory Neil Shapiro sm_realloc_x(ptr, size)
59940266059SGregory Neil Shapiro void *ptr;
60040266059SGregory Neil Shapiro size_t size;
60140266059SGregory Neil Shapiro {
60240266059SGregory Neil Shapiro void *newptr;
60340266059SGregory Neil Shapiro SM_HEAP_ITEM_T *hi, **hp;
60440266059SGregory Neil Shapiro
60540266059SGregory Neil Shapiro if (!HEAP_CHECK)
60640266059SGregory Neil Shapiro {
60740266059SGregory Neil Shapiro ENTER_CRITICAL();
60840266059SGregory Neil Shapiro newptr = realloc(ptr, MALLOC_SIZE(size));
60940266059SGregory Neil Shapiro LEAVE_CRITICAL();
61040266059SGregory Neil Shapiro if (newptr == NULL)
61140266059SGregory Neil Shapiro sm_exc_raise_x(&SmHeapOutOfMemory);
61240266059SGregory Neil Shapiro return newptr;
61340266059SGregory Neil Shapiro }
61440266059SGregory Neil Shapiro
61540266059SGregory Neil Shapiro if (ptr == NULL)
61640266059SGregory Neil Shapiro return sm_malloc_tagged_x(size, "realloc", 0, SmHeapGroup);
61740266059SGregory Neil Shapiro
61840266059SGregory Neil Shapiro for (hp = &SmHeapTable[ptrhash(ptr)]; *hp != NULL; hp = &(**hp).hi_next)
61940266059SGregory Neil Shapiro {
62040266059SGregory Neil Shapiro if ((**hp).hi_ptr == ptr)
62140266059SGregory Neil Shapiro {
62240266059SGregory Neil Shapiro sm_xtrap_raise_x(&SmHeapOutOfMemory);
62340266059SGregory Neil Shapiro hi = *hp;
62440266059SGregory Neil Shapiro if (sm_debug_active(&SmHeapLimit, 1)
62540266059SGregory Neil Shapiro && sm_debug_level(&SmHeapLimit)
62640266059SGregory Neil Shapiro < SmHeapTotal - hi->hi_size + size)
62740266059SGregory Neil Shapiro {
62840266059SGregory Neil Shapiro sm_exc_raise_x(&SmHeapOutOfMemory);
62940266059SGregory Neil Shapiro }
63040266059SGregory Neil Shapiro ENTER_CRITICAL();
63140266059SGregory Neil Shapiro newptr = realloc(ptr, MALLOC_SIZE(size));
63240266059SGregory Neil Shapiro LEAVE_CRITICAL();
63340266059SGregory Neil Shapiro if (newptr == NULL)
63440266059SGregory Neil Shapiro sm_exc_raise_x(&SmHeapOutOfMemory);
63540266059SGregory Neil Shapiro SmHeapTotal = SmHeapTotal - hi->hi_size + size;
63640266059SGregory Neil Shapiro if (SmHeapTotal > SmHeapMaxTotal)
63740266059SGregory Neil Shapiro SmHeapMaxTotal = SmHeapTotal;
63840266059SGregory Neil Shapiro *hp = hi->hi_next;
63940266059SGregory Neil Shapiro hi->hi_ptr = newptr;
64040266059SGregory Neil Shapiro hi->hi_size = size;
64140266059SGregory Neil Shapiro hp = &SmHeapTable[ptrhash(newptr)];
64240266059SGregory Neil Shapiro hi->hi_next = *hp;
64340266059SGregory Neil Shapiro *hp = hi;
64440266059SGregory Neil Shapiro return newptr;
64540266059SGregory Neil Shapiro }
64640266059SGregory Neil Shapiro }
64740266059SGregory Neil Shapiro sm_abort("sm_realloc_x: bad argument (%p)", ptr);
64840266059SGregory Neil Shapiro /* NOTREACHED */
64940266059SGregory Neil Shapiro return NULL; /* keep Irix compiler happy */
65040266059SGregory Neil Shapiro }
65140266059SGregory Neil Shapiro
65240266059SGregory Neil Shapiro /*
65340266059SGregory Neil Shapiro ** SM_FREE_TAGGED -- wrapper around free(), debugging version.
65440266059SGregory Neil Shapiro **
65540266059SGregory Neil Shapiro ** Parameters:
65640266059SGregory Neil Shapiro ** ptr -- pointer to memory region.
65740266059SGregory Neil Shapiro ** tag -- tag for debugging.
65840266059SGregory Neil Shapiro ** num -- additional value for debugging.
65940266059SGregory Neil Shapiro **
66040266059SGregory Neil Shapiro ** Returns:
66140266059SGregory Neil Shapiro ** none.
66240266059SGregory Neil Shapiro */
66340266059SGregory Neil Shapiro
66440266059SGregory Neil Shapiro void
sm_free_tagged(ptr,tag,num)66540266059SGregory Neil Shapiro sm_free_tagged(ptr, tag, num)
66640266059SGregory Neil Shapiro void *ptr;
66740266059SGregory Neil Shapiro char *tag;
66840266059SGregory Neil Shapiro int num;
66940266059SGregory Neil Shapiro {
67040266059SGregory Neil Shapiro SM_HEAP_ITEM_T **hp;
67140266059SGregory Neil Shapiro
67240266059SGregory Neil Shapiro if (ptr == NULL)
67340266059SGregory Neil Shapiro return;
67440266059SGregory Neil Shapiro if (!HEAP_CHECK)
67540266059SGregory Neil Shapiro {
67640266059SGregory Neil Shapiro ENTER_CRITICAL();
67740266059SGregory Neil Shapiro free(ptr);
67840266059SGregory Neil Shapiro LEAVE_CRITICAL();
67940266059SGregory Neil Shapiro return;
68040266059SGregory Neil Shapiro }
68140266059SGregory Neil Shapiro for (hp = &SmHeapTable[ptrhash(ptr)]; *hp != NULL; hp = &(**hp).hi_next)
68240266059SGregory Neil Shapiro {
68340266059SGregory Neil Shapiro if ((**hp).hi_ptr == ptr)
68440266059SGregory Neil Shapiro {
68540266059SGregory Neil Shapiro SM_HEAP_ITEM_T *hi = *hp;
68640266059SGregory Neil Shapiro
68740266059SGregory Neil Shapiro *hp = hi->hi_next;
68840266059SGregory Neil Shapiro
68940266059SGregory Neil Shapiro /*
69040266059SGregory Neil Shapiro ** Fill the block with zeros before freeing.
69140266059SGregory Neil Shapiro ** This is intended to catch problems with
69240266059SGregory Neil Shapiro ** dangling pointers. The block is filled with
69340266059SGregory Neil Shapiro ** zeros, not with some non-zero value, because
69440266059SGregory Neil Shapiro ** it is common practice in some C code to store
69540266059SGregory Neil Shapiro ** a zero in a structure member before freeing the
69640266059SGregory Neil Shapiro ** structure, as a defense against dangling pointers.
69740266059SGregory Neil Shapiro */
69840266059SGregory Neil Shapiro
69940266059SGregory Neil Shapiro (void) memset(ptr, 0, hi->hi_size);
70040266059SGregory Neil Shapiro SmHeapTotal -= hi->hi_size;
70140266059SGregory Neil Shapiro ENTER_CRITICAL();
70240266059SGregory Neil Shapiro free(ptr);
70340266059SGregory Neil Shapiro free(hi);
70440266059SGregory Neil Shapiro LEAVE_CRITICAL();
70540266059SGregory Neil Shapiro return;
70640266059SGregory Neil Shapiro }
70740266059SGregory Neil Shapiro }
70840266059SGregory Neil Shapiro sm_abort("sm_free: bad argument (%p) (%s:%d)", ptr, tag, num);
70940266059SGregory Neil Shapiro }
71040266059SGregory Neil Shapiro
71140266059SGregory Neil Shapiro /*
71240266059SGregory Neil Shapiro ** SM_HEAP_CHECKPTR_TAGGED -- check whether ptr is a valid argument to sm_free
71340266059SGregory Neil Shapiro **
71440266059SGregory Neil Shapiro ** Parameters:
71540266059SGregory Neil Shapiro ** ptr -- pointer to memory region.
71640266059SGregory Neil Shapiro ** tag -- tag for debugging.
71740266059SGregory Neil Shapiro ** num -- additional value for debugging.
71840266059SGregory Neil Shapiro **
71940266059SGregory Neil Shapiro ** Returns:
72040266059SGregory Neil Shapiro ** none.
72140266059SGregory Neil Shapiro **
72240266059SGregory Neil Shapiro ** Side Effects:
72340266059SGregory Neil Shapiro ** aborts if check fails.
72440266059SGregory Neil Shapiro */
72540266059SGregory Neil Shapiro
72640266059SGregory Neil Shapiro void
sm_heap_checkptr_tagged(ptr,tag,num)72740266059SGregory Neil Shapiro sm_heap_checkptr_tagged(ptr, tag, num)
72840266059SGregory Neil Shapiro void *ptr;
72940266059SGregory Neil Shapiro char *tag;
73040266059SGregory Neil Shapiro int num;
73140266059SGregory Neil Shapiro {
73240266059SGregory Neil Shapiro SM_HEAP_ITEM_T *hp;
73340266059SGregory Neil Shapiro
73440266059SGregory Neil Shapiro if (!HEAP_CHECK)
73540266059SGregory Neil Shapiro return;
73640266059SGregory Neil Shapiro if (ptr == NULL)
73740266059SGregory Neil Shapiro return;
73840266059SGregory Neil Shapiro for (hp = SmHeapTable[ptrhash(ptr)]; hp != NULL; hp = hp->hi_next)
73940266059SGregory Neil Shapiro {
74040266059SGregory Neil Shapiro if (hp->hi_ptr == ptr)
74140266059SGregory Neil Shapiro return;
74240266059SGregory Neil Shapiro }
74340266059SGregory Neil Shapiro sm_abort("sm_heap_checkptr(%p): bad ptr (%s:%d)", ptr, tag, num);
74440266059SGregory Neil Shapiro }
74540266059SGregory Neil Shapiro
74640266059SGregory Neil Shapiro /*
74740266059SGregory Neil Shapiro ** SM_HEAP_REPORT -- output "map" of used heap.
74840266059SGregory Neil Shapiro **
74940266059SGregory Neil Shapiro ** Parameters:
75040266059SGregory Neil Shapiro ** stream -- the file pointer to write to.
75140266059SGregory Neil Shapiro ** verbosity -- how much info?
75240266059SGregory Neil Shapiro **
75340266059SGregory Neil Shapiro ** Returns:
75440266059SGregory Neil Shapiro ** none.
75540266059SGregory Neil Shapiro */
75640266059SGregory Neil Shapiro
75740266059SGregory Neil Shapiro void
sm_heap_report(stream,verbosity)75840266059SGregory Neil Shapiro sm_heap_report(stream, verbosity)
75940266059SGregory Neil Shapiro SM_FILE_T *stream;
76040266059SGregory Neil Shapiro int verbosity;
76140266059SGregory Neil Shapiro {
76240266059SGregory Neil Shapiro int i;
76340266059SGregory Neil Shapiro unsigned long group0total, group1total, otherstotal, grandtotal;
764*2fb4f839SGregory Neil Shapiro static char str[32] = "[1900-00-00/00:00:00] ";
765*2fb4f839SGregory Neil Shapiro struct tm *tmp;
766*2fb4f839SGregory Neil Shapiro time_t currt;
76740266059SGregory Neil Shapiro
76840266059SGregory Neil Shapiro if (!HEAP_CHECK || verbosity <= 0)
76940266059SGregory Neil Shapiro return;
77040266059SGregory Neil Shapiro group0total = group1total = otherstotal = grandtotal = 0;
77140266059SGregory Neil Shapiro for (i = 0; i < sizeof(SmHeapTable) / sizeof(SmHeapTable[0]); ++i)
77240266059SGregory Neil Shapiro {
77340266059SGregory Neil Shapiro SM_HEAP_ITEM_T *hi = SmHeapTable[i];
77440266059SGregory Neil Shapiro
77540266059SGregory Neil Shapiro while (hi != NULL)
77640266059SGregory Neil Shapiro {
77740266059SGregory Neil Shapiro if (verbosity > 2
77840266059SGregory Neil Shapiro || (verbosity > 1 && hi->hi_group != 0))
77940266059SGregory Neil Shapiro {
78040266059SGregory Neil Shapiro sm_io_fprintf(stream, SM_TIME_DEFAULT,
78140266059SGregory Neil Shapiro "%4d %*lx %7lu bytes",
78240266059SGregory Neil Shapiro hi->hi_group,
78340266059SGregory Neil Shapiro (int) sizeof(void *) * 2,
78440266059SGregory Neil Shapiro (long)hi->hi_ptr,
78540266059SGregory Neil Shapiro (unsigned long)hi->hi_size);
78640266059SGregory Neil Shapiro if (hi->hi_tag != NULL)
78740266059SGregory Neil Shapiro {
78840266059SGregory Neil Shapiro sm_io_fprintf(stream, SM_TIME_DEFAULT,
78940266059SGregory Neil Shapiro " %s",
79040266059SGregory Neil Shapiro hi->hi_tag);
79140266059SGregory Neil Shapiro if (hi->hi_num)
79240266059SGregory Neil Shapiro {
79340266059SGregory Neil Shapiro sm_io_fprintf(stream,
79440266059SGregory Neil Shapiro SM_TIME_DEFAULT,
79540266059SGregory Neil Shapiro ":%d",
79640266059SGregory Neil Shapiro hi->hi_num);
79740266059SGregory Neil Shapiro }
79840266059SGregory Neil Shapiro }
79940266059SGregory Neil Shapiro sm_io_fprintf(stream, SM_TIME_DEFAULT, "\n");
80040266059SGregory Neil Shapiro }
80140266059SGregory Neil Shapiro switch (hi->hi_group)
80240266059SGregory Neil Shapiro {
80340266059SGregory Neil Shapiro case 0:
80440266059SGregory Neil Shapiro group0total += hi->hi_size;
80540266059SGregory Neil Shapiro break;
80640266059SGregory Neil Shapiro case 1:
80740266059SGregory Neil Shapiro group1total += hi->hi_size;
80840266059SGregory Neil Shapiro break;
80940266059SGregory Neil Shapiro default:
81040266059SGregory Neil Shapiro otherstotal += hi->hi_size;
81140266059SGregory Neil Shapiro break;
81240266059SGregory Neil Shapiro }
81340266059SGregory Neil Shapiro grandtotal += hi->hi_size;
81440266059SGregory Neil Shapiro hi = hi->hi_next;
81540266059SGregory Neil Shapiro }
81640266059SGregory Neil Shapiro }
817*2fb4f839SGregory Neil Shapiro
818*2fb4f839SGregory Neil Shapiro currt = time((time_t *)0);
819*2fb4f839SGregory Neil Shapiro tmp = localtime(&currt);
820*2fb4f839SGregory Neil Shapiro snprintf(str, sizeof(str), "[%d-%02d-%02d/%02d:%02d:%02d] ",
821*2fb4f839SGregory Neil Shapiro 1900 + tmp->tm_year, /* HACK */
822*2fb4f839SGregory Neil Shapiro tmp->tm_mon + 1,
823*2fb4f839SGregory Neil Shapiro tmp->tm_mday,
824*2fb4f839SGregory Neil Shapiro tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
82540266059SGregory Neil Shapiro sm_io_fprintf(stream, SM_TIME_DEFAULT,
826*2fb4f839SGregory Neil Shapiro "pid=%ld time=%s\nheap max=%lu, total=%lu, group 0=%lu, group 1=%lu, others=%lu\n",
827*2fb4f839SGregory Neil Shapiro (long) getpid(), str,
828*2fb4f839SGregory Neil Shapiro (unsigned long) SmHeapMaxTotal, grandtotal,
82940266059SGregory Neil Shapiro group0total, group1total, otherstotal);
83040266059SGregory Neil Shapiro if (grandtotal != SmHeapTotal)
83140266059SGregory Neil Shapiro {
83240266059SGregory Neil Shapiro sm_io_fprintf(stream, SM_TIME_DEFAULT,
83340266059SGregory Neil Shapiro "BUG => SmHeapTotal: got %lu, expected %lu\n",
83440266059SGregory Neil Shapiro (unsigned long) SmHeapTotal, grandtotal);
83540266059SGregory Neil Shapiro }
83640266059SGregory Neil Shapiro }
83740266059SGregory Neil Shapiro #endif /* !SM_HEAP_CHECK */
838