/*
* Copyright (c) 2000-2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
** resource pools
** For documentation, see rpool.html
*/
#if _FFR_PERF_RPOOL
# include <syslog.h>
#endif /* _FFR_PERF_RPOOL */
typedef union
{
} SM_POOLHDR_T;
/*
** Tune this later
*/
/*
** SM_RPOOL_ALLOCBLOCK_X -- allocate a new block for an rpool.
**
** Parameters:
** rpool -- rpool to which the block should be added.
** size -- size of block.
**
** Returns:
** Pointer to block.
**
** Exceptions:
** F:sm_heap -- out of memory
*/
static char *
{
SM_POOLLINK_T *p;
return (char*) p + sizeof(SM_POOLHDR_T);
}
/*
** SM_RPOOL_ALLOCBLOCK -- allocate a new block for an rpool.
**
** Parameters:
** rpool -- rpool to which the block should be added.
** size -- size of block.
**
** Returns:
** Pointer to block, NULL on failure.
*/
static char *
{
SM_POOLLINK_T *p;
if (p == NULL)
return NULL;
return (char*) p + sizeof(SM_POOLHDR_T);
}
/*
** SM_RPOOL_MALLOC_TAGGED_X -- allocate memory from rpool
**
** Parameters:
** rpool -- rpool from which memory should be allocated;
** can be NULL, use sm_malloc() then.
** size -- size of block.
** file -- filename.
** line -- line number in file.
** group -- heap group for debugging.
**
** Returns:
** Pointer to block.
**
** Exceptions:
** F:sm_heap -- out of memory
**
** Notice: XXX
** if size == 0 and the rpool is new (no memory
** allocated yet) NULL is returned!
** We could solve this by
** - wasting 1 byte (size < avail)
** - checking for rpool->sm_poolptr != NULL
** - not asking for 0 sized buffer
*/
void *
#if SM_HEAP_CHECK
char *file;
int line;
int group;
#else /* SM_HEAP_CHECK */
#endif /* SM_HEAP_CHECK */
{
char *ptr;
/* Ensure that size is properly aligned. */
if (size & SM_ALIGN_BITS)
/* The common case. This is optimized for speed. */
{
return ptr;
}
/*
** The slow case: we need to call malloc.
** The SM_REQUIRE assertion is deferred until now, for speed.
** That's okay: we set rpool->sm_poolavail to 0 when we free an rpool,
** so the common case code won't be triggered on a dangling pointer.
*/
/*
** If size > sm_poolsize, then malloc a new block especially for
** this request. Future requests will be allocated from the
** current pool.
**
** What if the current pool is mostly unallocated, and the current
** request is larger than the available space, but < sm_poolsize?
** If we discard the current pool, and start allocating from a new
** pool, then we will be wasting a lot of space. For this reason,
** we malloc a block just for the current request if size >
** sm_bigobjectsize, where sm_bigobjectsize <= sm_poolsize.
** Thus, the most space that we will waste at the end of a pool
** is sm_bigobjectsize - 1.
*/
{
#if _FFR_PERF_RPOOL
++rpool->sm_nbigblocks;
#endif /* _FFR_PERF_RPOOL */
}
#if _FFR_PERF_RPOOL
#endif /* _FFR_PERF_RPOOL */
return ptr;
}
/*
** SM_RPOOL_MALLOC_TAGGED -- allocate memory from rpool
**
** Parameters:
** rpool -- rpool from which memory should be allocated;
** can be NULL, use sm_malloc() then.
** size -- size of block.
** file -- filename.
** line -- line number in file.
** group -- heap group for debugging.
**
** Returns:
** Pointer to block, NULL on failure.
**
** Notice: XXX
** if size == 0 and the rpool is new (no memory
** allocated yet) NULL is returned!
** We could solve this by
** - wasting 1 byte (size < avail)
** - checking for rpool->sm_poolptr != NULL
** - not asking for 0 sized buffer
*/
void *
#if SM_HEAP_CHECK
char *file;
int line;
int group;
#else /* SM_HEAP_CHECK */
#endif /* SM_HEAP_CHECK */
{
char *ptr;
/* Ensure that size is properly aligned. */
if (size & SM_ALIGN_BITS)
/* The common case. This is optimized for speed. */
{
return ptr;
}
/*
** The slow case: we need to call malloc.
** The SM_REQUIRE assertion is deferred until now, for speed.
** That's okay: we set rpool->sm_poolavail to 0 when we free an rpool,
** so the common case code won't be triggered on a dangling pointer.
*/
/*
** If size > sm_poolsize, then malloc a new block especially for
** this request. Future requests will be allocated from the
** current pool.
**
** What if the current pool is mostly unallocated, and the current
** request is larger than the available space, but < sm_poolsize?
** If we discard the current pool, and start allocating from a new
** pool, then we will be wasting a lot of space. For this reason,
** we malloc a block just for the current request if size >
** sm_bigobjectsize, where sm_bigobjectsize <= sm_poolsize.
** Thus, the most space that we will waste at the end of a pool
** is sm_bigobjectsize - 1.
*/
{
#if _FFR_PERF_RPOOL
++rpool->sm_nbigblocks;
#endif /* _FFR_PERF_RPOOL */
}
return NULL;
#if _FFR_PERF_RPOOL
#endif /* _FFR_PERF_RPOOL */
return ptr;
}
/*
** SM_RPOOL_NEW_X -- create a new rpool.
**
** Parameters:
** parent -- pointer to parent rpool, can be NULL.
**
** Returns:
** Pointer to new rpool.
*/
{
else
{
(void *) rpool);
}
rpool->sm_poolavail = 0;
#if _FFR_PERF_RPOOL
rpool->sm_nbigblocks = 0;
#endif /* _FFR_PERF_RPOOL */
return rpool;
}
/*
** SM_RPOOL_SETSIZES -- set sizes for rpool.
**
** Parameters:
** poolsize -- size of a single rpool block.
** bigobjectsize -- if this size is exceeded, an individual
** block is allocated (must be less or equal poolsize).
**
** Returns:
** none.
*/
void
{
if (poolsize == 0)
if (bigobjectsize == 0)
}
/*
** SM_RPOOL_FREE -- free an rpool and release all of its resources.
**
** Parameters:
** rpool -- rpool to free.
**
** Returns:
** none.
*/
void
{
return;
/*
** It's important to free the resources before the memory pools,
** because the resource free functions might modify the contents
** of the memory pools.
*/
{
for (;;)
{
{
r->sm_rfree(r->sm_rcontext);
}
break;
}
}
/*
** Now free the memory pools.
*/
{
}
/*
** Disconnect rpool from its parent.
*/
/*
** Setting these fields to zero means that any future to attempt
** to use the rpool after it is freed will cause an assertion failure.
*/
rpool->sm_poolavail = 0;
#if _FFR_PERF_RPOOL
"perf: rpool=%lx, sm_nbigblocks=%d, sm_npools=%d",
rpool->sm_nbigblocks = 0;
#endif /* _FFR_PERF_RPOOL */
}
/*
** SM_RPOOL_ATTACH_X -- attach a resource to an rpool.
**
** Parameters:
** rpool -- rpool to which resource should be attached.
** rfree -- function to call when rpool is freed.
** rcontext -- argument for function to call when rpool is freed.
**
** Returns:
** Pointer to allocated function.
**
** Exceptions:
** F:sm_heap -- out of memory
*/
void *rcontext;
{
{
}
return a;
}
/*
** SM_RPOOL_STRDUP_X -- Create a copy of a C string
**
** Parameters:
** rpool -- rpool to use.
** s -- the string to copy.
**
** Returns:
** pointer to newly allocated string.
*/
char *
const char *s;
{
size_t l;
char *n;
l = strlen(s);
SM_ASSERT(l + 1 > l);
sm_strlcpy(n, s, l + 1);
return n;
}
#endif /* DO_NOT_USE_STRCPY */