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