xref: /freebsd-src/contrib/sendmail/libsm/rpool.c (revision 2fb4f839f3fc72ce2bab12f9ba4760f97f73e97f)
140266059SGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro  * Copyright (c) 2000-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: rpool.c,v 1.29 2013-11-22 20:51:43 ca Exp $")
1240266059SGregory Neil Shapiro 
1340266059SGregory Neil Shapiro /*
1440266059SGregory Neil Shapiro **  resource pools
1540266059SGregory Neil Shapiro **  For documentation, see rpool.html
1640266059SGregory Neil Shapiro */
1740266059SGregory Neil Shapiro 
1840266059SGregory Neil Shapiro #include <sm/exc.h>
1940266059SGregory Neil Shapiro #include <sm/heap.h>
2040266059SGregory Neil Shapiro #include <sm/rpool.h>
2140266059SGregory Neil Shapiro #include <sm/varargs.h>
2240266059SGregory Neil Shapiro #include <sm/conf.h>
2340266059SGregory Neil Shapiro #if _FFR_PERF_RPOOL
2440266059SGregory Neil Shapiro # include <syslog.h>
255b0945b5SGregory Neil Shapiro #endif
2640266059SGregory Neil Shapiro 
2740266059SGregory Neil Shapiro const char SmRpoolMagic[] = "sm_rpool";
2840266059SGregory Neil Shapiro 
2940266059SGregory Neil Shapiro typedef union
3040266059SGregory Neil Shapiro {
3140266059SGregory Neil Shapiro 	SM_POOLLINK_T	link;
3240266059SGregory Neil Shapiro 	char		align[SM_ALIGN_SIZE];
3340266059SGregory Neil Shapiro } SM_POOLHDR_T;
3440266059SGregory Neil Shapiro 
35b6bacd31SGregory Neil Shapiro static char	*sm_rpool_allocblock_x __P((SM_RPOOL_T *, size_t));
36b6bacd31SGregory Neil Shapiro static char	*sm_rpool_allocblock __P((SM_RPOOL_T *, size_t));
37b6bacd31SGregory Neil Shapiro 
3840266059SGregory Neil Shapiro /*
3940266059SGregory Neil Shapiro **  Tune this later
4040266059SGregory Neil Shapiro */
4140266059SGregory Neil Shapiro 
4240266059SGregory Neil Shapiro #define POOLSIZE		4096
4340266059SGregory Neil Shapiro #define BIG_OBJECT_RATIO	10
4440266059SGregory Neil Shapiro 
4540266059SGregory Neil Shapiro /*
4640266059SGregory Neil Shapiro **  SM_RPOOL_ALLOCBLOCK_X -- allocate a new block for an rpool.
4740266059SGregory Neil Shapiro **
4840266059SGregory Neil Shapiro **	Parameters:
4940266059SGregory Neil Shapiro **		rpool -- rpool to which the block should be added.
5040266059SGregory Neil Shapiro **		size -- size of block.
5140266059SGregory Neil Shapiro **
5240266059SGregory Neil Shapiro **	Returns:
5340266059SGregory Neil Shapiro **		Pointer to block.
5440266059SGregory Neil Shapiro **
5540266059SGregory Neil Shapiro **	Exceptions:
5640266059SGregory Neil Shapiro **		F:sm_heap -- out of memory
5740266059SGregory Neil Shapiro */
5840266059SGregory Neil Shapiro 
5940266059SGregory Neil Shapiro static char *
sm_rpool_allocblock_x(rpool,size)6040266059SGregory Neil Shapiro sm_rpool_allocblock_x(rpool, size)
6140266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
6240266059SGregory Neil Shapiro 	size_t size;
6340266059SGregory Neil Shapiro {
6440266059SGregory Neil Shapiro 	SM_POOLLINK_T *p;
6540266059SGregory Neil Shapiro 
6640266059SGregory Neil Shapiro 	p = sm_malloc_x(sizeof(SM_POOLHDR_T) + size);
6740266059SGregory Neil Shapiro 	p->sm_pnext = rpool->sm_pools;
6840266059SGregory Neil Shapiro 	rpool->sm_pools = p;
6940266059SGregory Neil Shapiro 	return (char*) p + sizeof(SM_POOLHDR_T);
7040266059SGregory Neil Shapiro }
7140266059SGregory Neil Shapiro 
7240266059SGregory Neil Shapiro /*
7340266059SGregory Neil Shapiro **  SM_RPOOL_ALLOCBLOCK -- allocate a new block for an rpool.
7440266059SGregory Neil Shapiro **
7540266059SGregory Neil Shapiro **	Parameters:
7640266059SGregory Neil Shapiro **		rpool -- rpool to which the block should be added.
7740266059SGregory Neil Shapiro **		size -- size of block.
7840266059SGregory Neil Shapiro **
7940266059SGregory Neil Shapiro **	Returns:
8040266059SGregory Neil Shapiro **		Pointer to block, NULL on failure.
8140266059SGregory Neil Shapiro */
8240266059SGregory Neil Shapiro 
8340266059SGregory Neil Shapiro static char *
sm_rpool_allocblock(rpool,size)8440266059SGregory Neil Shapiro sm_rpool_allocblock(rpool, size)
8540266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
8640266059SGregory Neil Shapiro 	size_t size;
8740266059SGregory Neil Shapiro {
8840266059SGregory Neil Shapiro 	SM_POOLLINK_T *p;
8940266059SGregory Neil Shapiro 
9040266059SGregory Neil Shapiro 	p = sm_malloc(sizeof(SM_POOLHDR_T) + size);
9140266059SGregory Neil Shapiro 	if (p == NULL)
9240266059SGregory Neil Shapiro 		return NULL;
9340266059SGregory Neil Shapiro 	p->sm_pnext = rpool->sm_pools;
9440266059SGregory Neil Shapiro 	rpool->sm_pools = p;
9540266059SGregory Neil Shapiro 	return (char*) p + sizeof(SM_POOLHDR_T);
9640266059SGregory Neil Shapiro }
9740266059SGregory Neil Shapiro 
9840266059SGregory Neil Shapiro /*
9940266059SGregory Neil Shapiro **  SM_RPOOL_MALLOC_TAGGED_X -- allocate memory from rpool
10040266059SGregory Neil Shapiro **
10140266059SGregory Neil Shapiro **	Parameters:
10240266059SGregory Neil Shapiro **		rpool -- rpool from which memory should be allocated;
10340266059SGregory Neil Shapiro **			can be NULL, use sm_malloc() then.
10440266059SGregory Neil Shapiro **		size -- size of block.
10540266059SGregory Neil Shapiro **		file -- filename.
10640266059SGregory Neil Shapiro **		line -- line number in file.
10740266059SGregory Neil Shapiro **		group -- heap group for debugging.
10840266059SGregory Neil Shapiro **
10940266059SGregory Neil Shapiro **	Returns:
11040266059SGregory Neil Shapiro **		Pointer to block.
11140266059SGregory Neil Shapiro **
11240266059SGregory Neil Shapiro **	Exceptions:
11340266059SGregory Neil Shapiro **		F:sm_heap -- out of memory
11440266059SGregory Neil Shapiro **
11540266059SGregory Neil Shapiro **	Notice: XXX
11640266059SGregory Neil Shapiro **		if size == 0 and the rpool is new (no memory
11740266059SGregory Neil Shapiro **		allocated yet) NULL is returned!
11840266059SGregory Neil Shapiro **		We could solve this by
11940266059SGregory Neil Shapiro **		- wasting 1 byte (size < avail)
12040266059SGregory Neil Shapiro **		- checking for rpool->sm_poolptr != NULL
12140266059SGregory Neil Shapiro **		- not asking for 0 sized buffer
12240266059SGregory Neil Shapiro */
12340266059SGregory Neil Shapiro 
12440266059SGregory Neil Shapiro void *
12540266059SGregory Neil Shapiro #if SM_HEAP_CHECK
sm_rpool_malloc_tagged_x(rpool,size,file,line,group)12640266059SGregory Neil Shapiro sm_rpool_malloc_tagged_x(rpool, size, file, line, group)
12740266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
12840266059SGregory Neil Shapiro 	size_t size;
12940266059SGregory Neil Shapiro 	char *file;
13040266059SGregory Neil Shapiro 	int line;
13140266059SGregory Neil Shapiro 	int group;
13240266059SGregory Neil Shapiro #else /* SM_HEAP_CHECK */
13340266059SGregory Neil Shapiro sm_rpool_malloc_x(rpool, size)
13440266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
13540266059SGregory Neil Shapiro 	size_t size;
13640266059SGregory Neil Shapiro #endif /* SM_HEAP_CHECK */
13740266059SGregory Neil Shapiro {
13840266059SGregory Neil Shapiro 	char *ptr;
13940266059SGregory Neil Shapiro 
14040266059SGregory Neil Shapiro 	if (rpool == NULL)
14140266059SGregory Neil Shapiro 		return sm_malloc_tagged_x(size, file, line, group);
14240266059SGregory Neil Shapiro 
14340266059SGregory Neil Shapiro 	/* Ensure that size is properly aligned. */
14440266059SGregory Neil Shapiro 	if (size & SM_ALIGN_BITS)
14540266059SGregory Neil Shapiro 		size = (size & ~SM_ALIGN_BITS) + SM_ALIGN_SIZE;
14640266059SGregory Neil Shapiro 
14740266059SGregory Neil Shapiro 	/* The common case.  This is optimized for speed. */
14840266059SGregory Neil Shapiro 	if (size <= rpool->sm_poolavail)
14940266059SGregory Neil Shapiro 	{
15040266059SGregory Neil Shapiro 		ptr = rpool->sm_poolptr;
15140266059SGregory Neil Shapiro 		rpool->sm_poolptr += size;
15240266059SGregory Neil Shapiro 		rpool->sm_poolavail -= size;
15340266059SGregory Neil Shapiro 		return ptr;
15440266059SGregory Neil Shapiro 	}
15540266059SGregory Neil Shapiro 
15640266059SGregory Neil Shapiro 	/*
15740266059SGregory Neil Shapiro 	**  The slow case: we need to call malloc.
15840266059SGregory Neil Shapiro 	**  The SM_REQUIRE assertion is deferred until now, for speed.
15940266059SGregory Neil Shapiro 	**  That's okay: we set rpool->sm_poolavail to 0 when we free an rpool,
16040266059SGregory Neil Shapiro 	**  so the common case code won't be triggered on a dangling pointer.
16140266059SGregory Neil Shapiro 	*/
16240266059SGregory Neil Shapiro 
16340266059SGregory Neil Shapiro 	SM_REQUIRE(rpool->sm_magic == SmRpoolMagic);
16440266059SGregory Neil Shapiro 
16540266059SGregory Neil Shapiro 	/*
16640266059SGregory Neil Shapiro 	**  If size > sm_poolsize, then malloc a new block especially for
16740266059SGregory Neil Shapiro 	**  this request.  Future requests will be allocated from the
16840266059SGregory Neil Shapiro 	**  current pool.
16940266059SGregory Neil Shapiro 	**
17040266059SGregory Neil Shapiro 	**  What if the current pool is mostly unallocated, and the current
17140266059SGregory Neil Shapiro 	**  request is larger than the available space, but < sm_poolsize?
17240266059SGregory Neil Shapiro 	**  If we discard the current pool, and start allocating from a new
17340266059SGregory Neil Shapiro 	**  pool, then we will be wasting a lot of space.  For this reason,
17440266059SGregory Neil Shapiro 	**  we malloc a block just for the current request if size >
17540266059SGregory Neil Shapiro 	**  sm_bigobjectsize, where sm_bigobjectsize <= sm_poolsize.
17640266059SGregory Neil Shapiro 	**  Thus, the most space that we will waste at the end of a pool
17740266059SGregory Neil Shapiro 	**  is sm_bigobjectsize - 1.
17840266059SGregory Neil Shapiro 	*/
17940266059SGregory Neil Shapiro 
18040266059SGregory Neil Shapiro 	if (size > rpool->sm_bigobjectsize)
18140266059SGregory Neil Shapiro 	{
18240266059SGregory Neil Shapiro #if _FFR_PERF_RPOOL
18340266059SGregory Neil Shapiro 		++rpool->sm_nbigblocks;
1845b0945b5SGregory Neil Shapiro #endif
18540266059SGregory Neil Shapiro 		return sm_rpool_allocblock_x(rpool, size);
18640266059SGregory Neil Shapiro 	}
18740266059SGregory Neil Shapiro 	SM_ASSERT(rpool->sm_bigobjectsize <= rpool->sm_poolsize);
18840266059SGregory Neil Shapiro 	ptr = sm_rpool_allocblock_x(rpool, rpool->sm_poolsize);
18940266059SGregory Neil Shapiro 	rpool->sm_poolptr = ptr + size;
19040266059SGregory Neil Shapiro 	rpool->sm_poolavail = rpool->sm_poolsize - size;
19140266059SGregory Neil Shapiro #if _FFR_PERF_RPOOL
19240266059SGregory Neil Shapiro 	++rpool->sm_npools;
1935b0945b5SGregory Neil Shapiro #endif
19440266059SGregory Neil Shapiro 	return ptr;
19540266059SGregory Neil Shapiro }
19640266059SGregory Neil Shapiro 
19740266059SGregory Neil Shapiro /*
19840266059SGregory Neil Shapiro **  SM_RPOOL_MALLOC_TAGGED -- allocate memory from rpool
19940266059SGregory Neil Shapiro **
20040266059SGregory Neil Shapiro **	Parameters:
20140266059SGregory Neil Shapiro **		rpool -- rpool from which memory should be allocated;
20240266059SGregory Neil Shapiro **			can be NULL, use sm_malloc() then.
20340266059SGregory Neil Shapiro **		size -- size of block.
20440266059SGregory Neil Shapiro **		file -- filename.
20540266059SGregory Neil Shapiro **		line -- line number in file.
20640266059SGregory Neil Shapiro **		group -- heap group for debugging.
20740266059SGregory Neil Shapiro **
20840266059SGregory Neil Shapiro **	Returns:
20940266059SGregory Neil Shapiro **		Pointer to block, NULL on failure.
21040266059SGregory Neil Shapiro **
21140266059SGregory Neil Shapiro **	Notice: XXX
21240266059SGregory Neil Shapiro **		if size == 0 and the rpool is new (no memory
21340266059SGregory Neil Shapiro **		allocated yet) NULL is returned!
21440266059SGregory Neil Shapiro **		We could solve this by
21540266059SGregory Neil Shapiro **		- wasting 1 byte (size < avail)
21640266059SGregory Neil Shapiro **		- checking for rpool->sm_poolptr != NULL
21740266059SGregory Neil Shapiro **		- not asking for 0 sized buffer
21840266059SGregory Neil Shapiro */
21940266059SGregory Neil Shapiro 
22040266059SGregory Neil Shapiro void *
22140266059SGregory Neil Shapiro #if SM_HEAP_CHECK
sm_rpool_malloc_tagged(rpool,size,file,line,group)22240266059SGregory Neil Shapiro sm_rpool_malloc_tagged(rpool, size, file, line, group)
22340266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
22440266059SGregory Neil Shapiro 	size_t size;
22540266059SGregory Neil Shapiro 	char *file;
22640266059SGregory Neil Shapiro 	int line;
22740266059SGregory Neil Shapiro 	int group;
22840266059SGregory Neil Shapiro #else /* SM_HEAP_CHECK */
22940266059SGregory Neil Shapiro sm_rpool_malloc(rpool, size)
23040266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
23140266059SGregory Neil Shapiro 	size_t size;
23240266059SGregory Neil Shapiro #endif /* SM_HEAP_CHECK */
23340266059SGregory Neil Shapiro {
23440266059SGregory Neil Shapiro 	char *ptr;
23540266059SGregory Neil Shapiro 
23640266059SGregory Neil Shapiro 	if (rpool == NULL)
23740266059SGregory Neil Shapiro 		return sm_malloc_tagged(size, file, line, group);
23840266059SGregory Neil Shapiro 
23940266059SGregory Neil Shapiro 	/* Ensure that size is properly aligned. */
24040266059SGregory Neil Shapiro 	if (size & SM_ALIGN_BITS)
24140266059SGregory Neil Shapiro 		size = (size & ~SM_ALIGN_BITS) + SM_ALIGN_SIZE;
24240266059SGregory Neil Shapiro 
24340266059SGregory Neil Shapiro 	/* The common case.  This is optimized for speed. */
24440266059SGregory Neil Shapiro 	if (size <= rpool->sm_poolavail)
24540266059SGregory Neil Shapiro 	{
24640266059SGregory Neil Shapiro 		ptr = rpool->sm_poolptr;
24740266059SGregory Neil Shapiro 		rpool->sm_poolptr += size;
24840266059SGregory Neil Shapiro 		rpool->sm_poolavail -= size;
24940266059SGregory Neil Shapiro 		return ptr;
25040266059SGregory Neil Shapiro 	}
25140266059SGregory Neil Shapiro 
25240266059SGregory Neil Shapiro 	/*
25340266059SGregory Neil Shapiro 	**  The slow case: we need to call malloc.
25440266059SGregory Neil Shapiro 	**  The SM_REQUIRE assertion is deferred until now, for speed.
25540266059SGregory Neil Shapiro 	**  That's okay: we set rpool->sm_poolavail to 0 when we free an rpool,
25640266059SGregory Neil Shapiro 	**  so the common case code won't be triggered on a dangling pointer.
25740266059SGregory Neil Shapiro 	*/
25840266059SGregory Neil Shapiro 
25940266059SGregory Neil Shapiro 	SM_REQUIRE(rpool->sm_magic == SmRpoolMagic);
26040266059SGregory Neil Shapiro 
26140266059SGregory Neil Shapiro 	/*
26240266059SGregory Neil Shapiro 	**  If size > sm_poolsize, then malloc a new block especially for
26340266059SGregory Neil Shapiro 	**  this request.  Future requests will be allocated from the
26440266059SGregory Neil Shapiro 	**  current pool.
26540266059SGregory Neil Shapiro 	**
26640266059SGregory Neil Shapiro 	**  What if the current pool is mostly unallocated, and the current
26740266059SGregory Neil Shapiro 	**  request is larger than the available space, but < sm_poolsize?
26840266059SGregory Neil Shapiro 	**  If we discard the current pool, and start allocating from a new
26940266059SGregory Neil Shapiro 	**  pool, then we will be wasting a lot of space.  For this reason,
27040266059SGregory Neil Shapiro 	**  we malloc a block just for the current request if size >
27140266059SGregory Neil Shapiro 	**  sm_bigobjectsize, where sm_bigobjectsize <= sm_poolsize.
27240266059SGregory Neil Shapiro 	**  Thus, the most space that we will waste at the end of a pool
27340266059SGregory Neil Shapiro 	**  is sm_bigobjectsize - 1.
27440266059SGregory Neil Shapiro 	*/
27540266059SGregory Neil Shapiro 
27640266059SGregory Neil Shapiro 	if (size > rpool->sm_bigobjectsize)
27740266059SGregory Neil Shapiro 	{
27840266059SGregory Neil Shapiro #if _FFR_PERF_RPOOL
27940266059SGregory Neil Shapiro 		++rpool->sm_nbigblocks;
2805b0945b5SGregory Neil Shapiro #endif
28140266059SGregory Neil Shapiro 		return sm_rpool_allocblock(rpool, size);
28240266059SGregory Neil Shapiro 	}
28340266059SGregory Neil Shapiro 	SM_ASSERT(rpool->sm_bigobjectsize <= rpool->sm_poolsize);
28440266059SGregory Neil Shapiro 	ptr = sm_rpool_allocblock(rpool, rpool->sm_poolsize);
28540266059SGregory Neil Shapiro 	if (ptr == NULL)
28640266059SGregory Neil Shapiro 		return NULL;
28740266059SGregory Neil Shapiro 	rpool->sm_poolptr = ptr + size;
28840266059SGregory Neil Shapiro 	rpool->sm_poolavail = rpool->sm_poolsize - size;
28940266059SGregory Neil Shapiro #if _FFR_PERF_RPOOL
29040266059SGregory Neil Shapiro 	++rpool->sm_npools;
2915b0945b5SGregory Neil Shapiro #endif
29240266059SGregory Neil Shapiro 	return ptr;
29340266059SGregory Neil Shapiro }
29440266059SGregory Neil Shapiro 
29540266059SGregory Neil Shapiro /*
29640266059SGregory Neil Shapiro **  SM_RPOOL_NEW_X -- create a new rpool.
29740266059SGregory Neil Shapiro **
29840266059SGregory Neil Shapiro **	Parameters:
29940266059SGregory Neil Shapiro **		parent -- pointer to parent rpool, can be NULL.
30040266059SGregory Neil Shapiro **
30140266059SGregory Neil Shapiro **	Returns:
30240266059SGregory Neil Shapiro **		Pointer to new rpool.
30340266059SGregory Neil Shapiro */
30440266059SGregory Neil Shapiro 
30540266059SGregory Neil Shapiro SM_RPOOL_T *
sm_rpool_new_x(parent)30640266059SGregory Neil Shapiro sm_rpool_new_x(parent)
30740266059SGregory Neil Shapiro 	SM_RPOOL_T *parent;
30840266059SGregory Neil Shapiro {
30940266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
31040266059SGregory Neil Shapiro 
31140266059SGregory Neil Shapiro 	rpool = sm_malloc_x(sizeof(SM_RPOOL_T));
31240266059SGregory Neil Shapiro 	if (parent == NULL)
31340266059SGregory Neil Shapiro 		rpool->sm_parentlink = NULL;
31440266059SGregory Neil Shapiro 	else
31540266059SGregory Neil Shapiro 	{
31640266059SGregory Neil Shapiro 		SM_TRY
31740266059SGregory Neil Shapiro 			rpool->sm_parentlink = sm_rpool_attach_x(parent,
31840266059SGregory Neil Shapiro 					(SM_RPOOL_RFREE_T) sm_rpool_free,
31940266059SGregory Neil Shapiro 					(void *) rpool);
32040266059SGregory Neil Shapiro 		SM_EXCEPT(exc, "*")
32140266059SGregory Neil Shapiro 			sm_free(rpool);
32240266059SGregory Neil Shapiro 			sm_exc_raise_x(exc);
32340266059SGregory Neil Shapiro 		SM_END_TRY
32440266059SGregory Neil Shapiro 	}
32540266059SGregory Neil Shapiro 	rpool->sm_magic = SmRpoolMagic;
32640266059SGregory Neil Shapiro 
32740266059SGregory Neil Shapiro 	rpool->sm_poolsize = POOLSIZE - sizeof(SM_POOLHDR_T);
32840266059SGregory Neil Shapiro 	rpool->sm_bigobjectsize = rpool->sm_poolsize / BIG_OBJECT_RATIO;
32940266059SGregory Neil Shapiro 	rpool->sm_poolptr = NULL;
33040266059SGregory Neil Shapiro 	rpool->sm_poolavail = 0;
33140266059SGregory Neil Shapiro 	rpool->sm_pools = NULL;
33240266059SGregory Neil Shapiro 
33340266059SGregory Neil Shapiro 	rpool->sm_rptr = NULL;
33440266059SGregory Neil Shapiro 	rpool->sm_ravail = 0;
33540266059SGregory Neil Shapiro 	rpool->sm_rlists = NULL;
33640266059SGregory Neil Shapiro #if _FFR_PERF_RPOOL
33740266059SGregory Neil Shapiro 	rpool->sm_nbigblocks = 0;
33840266059SGregory Neil Shapiro 	rpool->sm_npools = 0;
3395b0945b5SGregory Neil Shapiro #endif
34040266059SGregory Neil Shapiro 
34140266059SGregory Neil Shapiro 	return rpool;
34240266059SGregory Neil Shapiro }
34340266059SGregory Neil Shapiro 
34440266059SGregory Neil Shapiro /*
34540266059SGregory Neil Shapiro **  SM_RPOOL_SETSIZES -- set sizes for rpool.
34640266059SGregory Neil Shapiro **
34740266059SGregory Neil Shapiro **	Parameters:
34840266059SGregory Neil Shapiro **		poolsize -- size of a single rpool block.
34940266059SGregory Neil Shapiro **		bigobjectsize -- if this size is exceeded, an individual
35040266059SGregory Neil Shapiro **			block is allocated (must be less or equal poolsize).
35140266059SGregory Neil Shapiro **
35240266059SGregory Neil Shapiro **	Returns:
35340266059SGregory Neil Shapiro **		none.
35440266059SGregory Neil Shapiro */
35540266059SGregory Neil Shapiro 
35640266059SGregory Neil Shapiro void
sm_rpool_setsizes(rpool,poolsize,bigobjectsize)35740266059SGregory Neil Shapiro sm_rpool_setsizes(rpool, poolsize, bigobjectsize)
35840266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
35940266059SGregory Neil Shapiro 	size_t poolsize;
36040266059SGregory Neil Shapiro 	size_t bigobjectsize;
36140266059SGregory Neil Shapiro {
36240266059SGregory Neil Shapiro 	SM_REQUIRE(poolsize >= bigobjectsize);
36340266059SGregory Neil Shapiro 	if (poolsize == 0)
36440266059SGregory Neil Shapiro 		poolsize = POOLSIZE - sizeof(SM_POOLHDR_T);
36540266059SGregory Neil Shapiro 	if (bigobjectsize == 0)
36640266059SGregory Neil Shapiro 		bigobjectsize = poolsize / BIG_OBJECT_RATIO;
36740266059SGregory Neil Shapiro 	rpool->sm_poolsize = poolsize;
36840266059SGregory Neil Shapiro 	rpool->sm_bigobjectsize = bigobjectsize;
36940266059SGregory Neil Shapiro }
37040266059SGregory Neil Shapiro 
37140266059SGregory Neil Shapiro /*
37240266059SGregory Neil Shapiro **  SM_RPOOL_FREE -- free an rpool and release all of its resources.
37340266059SGregory Neil Shapiro **
37440266059SGregory Neil Shapiro **	Parameters:
37540266059SGregory Neil Shapiro **		rpool -- rpool to free.
37640266059SGregory Neil Shapiro **
37740266059SGregory Neil Shapiro **	Returns:
37840266059SGregory Neil Shapiro **		none.
37940266059SGregory Neil Shapiro */
38040266059SGregory Neil Shapiro 
38140266059SGregory Neil Shapiro void
sm_rpool_free(rpool)38240266059SGregory Neil Shapiro sm_rpool_free(rpool)
38340266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
38440266059SGregory Neil Shapiro {
38540266059SGregory Neil Shapiro 	SM_RLIST_T *rl, *rnext;
38640266059SGregory Neil Shapiro 	SM_RESOURCE_T *r, *rmax;
38740266059SGregory Neil Shapiro 	SM_POOLLINK_T *pp, *pnext;
38840266059SGregory Neil Shapiro 
38940266059SGregory Neil Shapiro 	if (rpool == NULL)
39040266059SGregory Neil Shapiro 		return;
39140266059SGregory Neil Shapiro 
39240266059SGregory Neil Shapiro 	/*
39340266059SGregory Neil Shapiro 	**  It's important to free the resources before the memory pools,
39440266059SGregory Neil Shapiro 	**  because the resource free functions might modify the contents
39540266059SGregory Neil Shapiro 	**  of the memory pools.
39640266059SGregory Neil Shapiro 	*/
39740266059SGregory Neil Shapiro 
39840266059SGregory Neil Shapiro 	rl = rpool->sm_rlists;
39940266059SGregory Neil Shapiro 	if (rl != NULL)
40040266059SGregory Neil Shapiro 	{
40140266059SGregory Neil Shapiro 		rmax = rpool->sm_rptr;
40240266059SGregory Neil Shapiro 		for (;;)
40340266059SGregory Neil Shapiro 		{
40440266059SGregory Neil Shapiro 			for (r = rl->sm_rvec; r < rmax; ++r)
40540266059SGregory Neil Shapiro 			{
40640266059SGregory Neil Shapiro 				if (r->sm_rfree != NULL)
40740266059SGregory Neil Shapiro 					r->sm_rfree(r->sm_rcontext);
40840266059SGregory Neil Shapiro 			}
40940266059SGregory Neil Shapiro 			rnext = rl->sm_rnext;
41040266059SGregory Neil Shapiro 			sm_free(rl);
41140266059SGregory Neil Shapiro 			if (rnext == NULL)
41240266059SGregory Neil Shapiro 				break;
41340266059SGregory Neil Shapiro 			rl = rnext;
41440266059SGregory Neil Shapiro 			rmax = &rl->sm_rvec[SM_RLIST_MAX];
41540266059SGregory Neil Shapiro 		}
41640266059SGregory Neil Shapiro 	}
41740266059SGregory Neil Shapiro 
41840266059SGregory Neil Shapiro 	/*
41940266059SGregory Neil Shapiro 	**  Now free the memory pools.
42040266059SGregory Neil Shapiro 	*/
42140266059SGregory Neil Shapiro 
42240266059SGregory Neil Shapiro 	for (pp = rpool->sm_pools; pp != NULL; pp = pnext)
42340266059SGregory Neil Shapiro 	{
42440266059SGregory Neil Shapiro 		pnext = pp->sm_pnext;
42540266059SGregory Neil Shapiro 		sm_free(pp);
42640266059SGregory Neil Shapiro 	}
42740266059SGregory Neil Shapiro 
42840266059SGregory Neil Shapiro 	/*
42940266059SGregory Neil Shapiro 	**  Disconnect rpool from its parent.
43040266059SGregory Neil Shapiro 	*/
43140266059SGregory Neil Shapiro 
43240266059SGregory Neil Shapiro 	if (rpool->sm_parentlink != NULL)
43340266059SGregory Neil Shapiro 		*rpool->sm_parentlink = NULL;
43440266059SGregory Neil Shapiro 
43540266059SGregory Neil Shapiro 	/*
43640266059SGregory Neil Shapiro 	**  Setting these fields to zero means that any future to attempt
43740266059SGregory Neil Shapiro 	**  to use the rpool after it is freed will cause an assertion failure.
43840266059SGregory Neil Shapiro 	*/
43940266059SGregory Neil Shapiro 
44040266059SGregory Neil Shapiro 	rpool->sm_magic = NULL;
44140266059SGregory Neil Shapiro 	rpool->sm_poolavail = 0;
44240266059SGregory Neil Shapiro 	rpool->sm_ravail = 0;
44340266059SGregory Neil Shapiro 
44440266059SGregory Neil Shapiro #if _FFR_PERF_RPOOL
44540266059SGregory Neil Shapiro 	if (rpool->sm_nbigblocks > 0 || rpool->sm_npools > 1)
44640266059SGregory Neil Shapiro 		syslog(LOG_NOTICE,
44740266059SGregory Neil Shapiro 			"perf: rpool=%lx, sm_nbigblocks=%d, sm_npools=%d",
44840266059SGregory Neil Shapiro 			(long) rpool, rpool->sm_nbigblocks, rpool->sm_npools);
44940266059SGregory Neil Shapiro 	rpool->sm_nbigblocks = 0;
45040266059SGregory Neil Shapiro 	rpool->sm_npools = 0;
45140266059SGregory Neil Shapiro #endif /* _FFR_PERF_RPOOL */
45240266059SGregory Neil Shapiro 	sm_free(rpool);
45340266059SGregory Neil Shapiro }
45440266059SGregory Neil Shapiro 
45540266059SGregory Neil Shapiro /*
45640266059SGregory Neil Shapiro **  SM_RPOOL_ATTACH_X -- attach a resource to an rpool.
45740266059SGregory Neil Shapiro **
45840266059SGregory Neil Shapiro **	Parameters:
45940266059SGregory Neil Shapiro **		rpool -- rpool to which resource should be attached.
46040266059SGregory Neil Shapiro **		rfree -- function to call when rpool is freed.
46140266059SGregory Neil Shapiro **		rcontext -- argument for function to call when rpool is freed.
46240266059SGregory Neil Shapiro **
46340266059SGregory Neil Shapiro **	Returns:
46440266059SGregory Neil Shapiro **		Pointer to allocated function.
46540266059SGregory Neil Shapiro **
46640266059SGregory Neil Shapiro **	Exceptions:
46740266059SGregory Neil Shapiro **		F:sm_heap -- out of memory
46840266059SGregory Neil Shapiro */
46940266059SGregory Neil Shapiro 
47040266059SGregory Neil Shapiro SM_RPOOL_ATTACH_T
sm_rpool_attach_x(rpool,rfree,rcontext)47140266059SGregory Neil Shapiro sm_rpool_attach_x(rpool, rfree, rcontext)
47240266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
47340266059SGregory Neil Shapiro 	SM_RPOOL_RFREE_T rfree;
47440266059SGregory Neil Shapiro 	void *rcontext;
47540266059SGregory Neil Shapiro {
47640266059SGregory Neil Shapiro 	SM_RLIST_T *rl;
47740266059SGregory Neil Shapiro 	SM_RPOOL_ATTACH_T a;
47840266059SGregory Neil Shapiro 
47940266059SGregory Neil Shapiro 	SM_REQUIRE_ISA(rpool, SmRpoolMagic);
48040266059SGregory Neil Shapiro 
48140266059SGregory Neil Shapiro 	if (rpool->sm_ravail == 0)
48240266059SGregory Neil Shapiro 	{
48340266059SGregory Neil Shapiro 		rl = sm_malloc_x(sizeof(SM_RLIST_T));
48440266059SGregory Neil Shapiro 		rl->sm_rnext = rpool->sm_rlists;
48540266059SGregory Neil Shapiro 		rpool->sm_rlists = rl;
48640266059SGregory Neil Shapiro 		rpool->sm_rptr = rl->sm_rvec;
48740266059SGregory Neil Shapiro 		rpool->sm_ravail = SM_RLIST_MAX;
48840266059SGregory Neil Shapiro 	}
48940266059SGregory Neil Shapiro 
49040266059SGregory Neil Shapiro 	a = &rpool->sm_rptr->sm_rfree;
49140266059SGregory Neil Shapiro 	rpool->sm_rptr->sm_rfree = rfree;
49240266059SGregory Neil Shapiro 	rpool->sm_rptr->sm_rcontext = rcontext;
49340266059SGregory Neil Shapiro 	++rpool->sm_rptr;
49440266059SGregory Neil Shapiro 	--rpool->sm_ravail;
49540266059SGregory Neil Shapiro 	return a;
49640266059SGregory Neil Shapiro }
497e92d3f3fSGregory Neil Shapiro 
498e92d3f3fSGregory Neil Shapiro #if DO_NOT_USE_STRCPY
499e92d3f3fSGregory Neil Shapiro /*
500e92d3f3fSGregory Neil Shapiro **  SM_RPOOL_STRDUP_X -- Create a copy of a C string
501e92d3f3fSGregory Neil Shapiro **
502e92d3f3fSGregory Neil Shapiro **	Parameters:
503e92d3f3fSGregory Neil Shapiro **		rpool -- rpool to use.
504e92d3f3fSGregory Neil Shapiro **		s -- the string to copy.
505e92d3f3fSGregory Neil Shapiro **
506e92d3f3fSGregory Neil Shapiro **	Returns:
507e92d3f3fSGregory Neil Shapiro **		pointer to newly allocated string.
508e92d3f3fSGregory Neil Shapiro */
509e92d3f3fSGregory Neil Shapiro 
510e92d3f3fSGregory Neil Shapiro char *
511*2fb4f839SGregory Neil Shapiro # if SM_HEAP_CHECK > 2
sm_rpool_strdup_tagged_x(rpool,s,tag,line,group)512*2fb4f839SGregory Neil Shapiro sm_rpool_strdup_tagged_x
513*2fb4f839SGregory Neil Shapiro # else
514*2fb4f839SGregory Neil Shapiro sm_rpool_strdup_x
515*2fb4f839SGregory Neil Shapiro # endif
516*2fb4f839SGregory Neil Shapiro 	(rpool, s
517*2fb4f839SGregory Neil Shapiro # if SM_HEAP_CHECK > 2
518*2fb4f839SGregory Neil Shapiro 	, tag, line, group
519*2fb4f839SGregory Neil Shapiro # endif
520*2fb4f839SGregory Neil Shapiro 	)
521e92d3f3fSGregory Neil Shapiro 	SM_RPOOL_T *rpool;
522e92d3f3fSGregory Neil Shapiro 	const char *s;
523*2fb4f839SGregory Neil Shapiro # if SM_HEAP_CHECK > 2
524*2fb4f839SGregory Neil Shapiro 	char *tag;
525*2fb4f839SGregory Neil Shapiro 	int line;
526*2fb4f839SGregory Neil Shapiro 	int group;
527*2fb4f839SGregory Neil Shapiro # else
528*2fb4f839SGregory Neil Shapiro #  define tag  "sm_rpool_strdup_x"
529*2fb4f839SGregory Neil Shapiro #  define line 1
530*2fb4f839SGregory Neil Shapiro #  define group 1
531*2fb4f839SGregory Neil Shapiro # endif
532e92d3f3fSGregory Neil Shapiro {
533e92d3f3fSGregory Neil Shapiro 	size_t l;
534e92d3f3fSGregory Neil Shapiro 	char *n;
535e92d3f3fSGregory Neil Shapiro 
536e92d3f3fSGregory Neil Shapiro 	l = strlen(s);
537e92d3f3fSGregory Neil Shapiro 	SM_ASSERT(l + 1 > l);
538*2fb4f839SGregory Neil Shapiro # if SM_HEAP_CHECK
539*2fb4f839SGregory Neil Shapiro 	n = sm_rpool_malloc_tagged_x(rpool, l + 1, tag, line, group);
540*2fb4f839SGregory Neil Shapiro # else
541e92d3f3fSGregory Neil Shapiro 	n = sm_rpool_malloc_x(rpool, l + 1);
542*2fb4f839SGregory Neil Shapiro # endif
543e92d3f3fSGregory Neil Shapiro 	sm_strlcpy(n, s, l + 1);
544e92d3f3fSGregory Neil Shapiro 	return n;
545e92d3f3fSGregory Neil Shapiro }
546*2fb4f839SGregory Neil Shapiro # if SM_HEAP_CHECK <= 2
547*2fb4f839SGregory Neil Shapiro #  undef tag
548*2fb4f839SGregory Neil Shapiro #  undef line
549*2fb4f839SGregory Neil Shapiro #  undef group
550*2fb4f839SGregory Neil Shapiro # endif
551e92d3f3fSGregory Neil Shapiro #endif /* DO_NOT_USE_STRCPY */
552