18#include "apr_private.h"
31#define APR_WANT_MEMFUNC
43#if APR_ALLOCATOR_GUARD_PAGES && !APR_ALLOCATOR_USES_MMAP
44#define APR_ALLOCATOR_USES_MMAP 1
47#if APR_ALLOCATOR_USES_MMAP
55#define REDZONE APR_ALIGN_DEFAULT(8)
57#define APR_IF_VALGRIND(x) \
58 do { if (apr_running_on_valgrind) { x; } } while (0)
62#define APR_IF_VALGRIND(x)
66#define APR_VALGRIND_NOACCESS(addr_, size_) \
67 APR_IF_VALGRIND(VALGRIND_MAKE_MEM_NOACCESS(addr_, size_))
68#define APR_VALGRIND_UNDEFINED(addr_, size_) \
69 APR_IF_VALGRIND(VALGRIND_MAKE_MEM_UNDEFINED(addr_, size_))
72#if APR_POOL_CONCURRENCY_CHECK && !APR_HAS_THREADS
73#error pool-concurrency-check does not make sense without threads
85#define MIN_ALLOC (2 * BOUNDARY_SIZE)
88#if APR_ALLOCATOR_USES_MMAP && defined(_SC_PAGESIZE)
91#define BOUNDARY_INDEX boundary_index
92#define BOUNDARY_SIZE boundary_size
94#define BOUNDARY_INDEX 12
95#define BOUNDARY_SIZE (1 << BOUNDARY_INDEX)
98#if APR_ALLOCATOR_GUARD_PAGES
99#if defined(_SC_PAGESIZE)
100#define GUARDPAGE_SIZE boundary_size
102#error Cannot determine page size
105#define GUARDPAGE_SIZE 0
115#define TIMEOUT_USECS 3000000
116#define TIMEOUT_INTERVAL 46875
156#define SIZEOF_ALLOCATOR_T APR_ALIGN_DEFAULT(sizeof(apr_allocator_t))
203 for (index = 0; index <
MAX_INDEX; index++) {
205 while ((node = *ref) !=
NULL) {
207#if APR_ALLOCATOR_USES_MMAP
331 while (*ref ==
NULL &&
i < max_index) {
336 if ((node = *ref) !=
NULL) {
342 if ((*ref = node->
next) ==
NULL &&
i >= max_index) {
347 while (*ref ==
NULL && max_index);
374 while ((node = *ref) !=
NULL && index > node->
index)
395#if APR_ALLOCATOR_GUARD_PAGES
398#elif APR_ALLOCATOR_USES_MMAP
406#if APR_ALLOCATOR_GUARD_PAGES
430 apr_size_t max_free_index, current_free_index;
449 && index + 1 > current_free_index) {
450 node->
next = freelist;
458 && index > max_index) {
462 if (current_free_index >= index + 1)
463 current_free_index -= index + 1;
465 current_free_index = 0;
473 if (current_free_index >= index + 1)
474 current_free_index -= index + 1;
476 current_free_index = 0;
478 }
while ((node = next) !=
NULL);
485 while (freelist !=
NULL) {
487 freelist = node->
next;
488#if APR_ALLOCATOR_USES_MMAP
515#define APR_POOL_DEBUG_GENERAL 0x01
516#define APR_POOL_DEBUG_VERBOSE 0x02
517#define APR_POOL_DEBUG_LIFETIME 0x04
518#define APR_POOL_DEBUG_OWNER 0x08
519#define APR_POOL_DEBUG_VERBOSE_ALLOC 0x10
521#define APR_POOL_DEBUG_VERBOSE_ALL (APR_POOL_DEBUG_VERBOSE \
522 | APR_POOL_DEBUG_VERBOSE_ALLOC)
552#define SIZEOF_DEBUG_NODE_T APR_ALIGN_DEFAULT(sizeof(debug_node_t))
598#if APR_POOL_CONCURRENCY_CHECK
608#define SIZEOF_POOL_T APR_ALIGN_DEFAULT(sizeof(apr_pool_t))
622#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
659#if APR_ALLOCATOR_USES_MMAP && defined(_SC_PAGESIZE)
728#define list_insert(node, point) do { \
729 node->ref = point->ref; \
731 node->next = point; \
732 point->ref = &node->next; \
736#define list_remove(node) do { \
737 *node->ref = node->next; \
738 node->next->ref = node->ref; \
742#define node_free_space(node_) ((apr_size_t)(node_->endp - node_->first_avail))
748#if APR_POOL_CONCURRENCY_CHECK
750static const char *
const in_use_string[] = {
"idle",
"in use",
"destroyed" };
754 fprintf(
stderr,
"pool concurrency check: pool %p(%s), thread cur %lx "
755 "in use by %lx, state %s -> %s \n",
757 (
unsigned long)
pool->in_use_by,
959 if (active->
next == active) {
966 active->
next = active;
1226#define APR_PSPRINTF_MIN_STRINGSIZE 32
1241 size = cur_len << 1;
1282 if (
ps->got_a_new_node) {
1287 ps->got_a_new_node = 1;
1309 while (
ps->vbuff.curpos -
ps->node->first_avail <
len) {
1310 if (
ps->vbuff.endpos -
ps->node->first_avail >=
len)
1311 ps->vbuff.curpos =
ps->node->first_avail +
len;
1313 ps->vbuff.curpos =
ps->vbuff.endpos;
1320 if (
ps->vbuff.curpos !=
ps->node->first_avail)
1322 ps->vbuff.curpos -
ps->node->first_avail);
1323 if (
ps->vbuff.curpos ==
ps->vbuff.endpos) {
1343 ps.vbuff.curpos =
ps.node->first_avail;
1346 ps.vbuff.endpos =
ps.node->endp - 1;
1347 ps.got_a_new_node = 0;
1353 if (
ps.node->first_avail ==
ps.node->endp) {
1361 if (!
ps.got_a_new_node) {
1364 ps.node->endp -
ps.vbuff.curpos);
1372 *
ps.vbuff.curpos++ =
'\0';
1376 strp =
ps.node->first_avail;
1381 if (
ps.node->endp !=
ps.vbuff.curpos)
1383 ps.node->endp -
ps.vbuff.curpos);
1390 strp =
ps.node->first_avail;
1393 size =
ps.vbuff.curpos -
ps.node->first_avail;
1395 ps.node->first_avail +=
size;
1403 if (!
ps.got_a_new_node) {
1443 if (
ps.got_a_new_node) {
1526#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
1540 "(%10lu/%10lu/%10lu) "
1557 pool->stat_alloc,
pool->stat_total_alloc,
pool->stat_clear);
1584#if (APR_POOL_DEBUG & APR_POOL_DEBUG_LIFETIME)
1616#if (APR_POOL_DEBUG & APR_POOL_DEBUG_LIFETIME)
1618#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
1620 __FILE__ ":apr_pool_integrity check [lifetime]", 0);
1629#if (APR_POOL_DEBUG & APR_POOL_DEBUG_OWNER)
1632#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
1634 __FILE__ ":apr_pool_integrity check [owner]", 0);
1655#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
1663#if APR_ALLOCATOR_USES_MMAP && defined(_SC_PAGESIZE)
1692#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
1716 "] ACTION (SIZE /POOL SIZE /TOTAL SIZE) "
1717 "POOL \"TAG\" <__FILE__:__LINE__> PARENT (ALLOCS/TOTAL ALLOCS/CLEARS)\n");
1744#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
1788 pool->stat_total_alloc++;
1802#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALLOC)
1819#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALLOC)
1831#define POOL_POISON_BYTE 'A'
1875 for (index = 0; index <
node->
index; index++) {
1877 (
char *)
node->
endp[index] - (
char *)
node->beginp[index]);
1885 pool->stat_alloc = 0;
1888#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE)
1910#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE)
1920 if (mutex !=
pool->mutex) {
1967#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
1969 __FILE__ ":apr_pool_destroy abort on joined", 0);
1982#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE)
2077#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE)
2156#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE)
2187 ps->vbuff.endpos =
ps->mem +
ps->size - 1;
2201 ps.vbuff.curpos =
ps.mem;
2204 ps.vbuff.endpos =
ps.mem +
ps.size - 1;
2213 *
ps.vbuff.curpos++ =
'\0';
2263 for (index = 0; index <
node->
index; index++) {
2296 for (index = 0; index <
node->
index; index++) {
2530 if (!
c || !
c->plain_cleanup_fn || !
c->child_cleanup_fn) {
2560 if (!
c || !
c->plain_cleanup_fn) {
2584 || (
c->next &&
c ==
c->next->next)
2585 || (
c->next &&
c->next->next &&
c ==
c->next->next->next)) {
2609 || (
c->next &&
c ==
c->next->next)
2610 || (
c->next &&
c->next->next &&
c ==
c->next->next->next)) {
2666 (*
c->plain_cleanup_fn)((
void *)
c->data);
2671#if !defined(WIN32) && !defined(OS2)
2679 (*
c->child_cleanup_fn)((
void *)
c->data);
2911#undef apr_pool_clear
2919#undef apr_pool_destroy
2927#undef apr_pool_create_ex
2943#undef apr_pool_create_core_ex
2956#undef apr_pool_create_unmanaged_ex
const char apr_size_t len
APR Internal Memory Allocation.
APR Environment functions.
APR Miscellaneous library routines.
APR general purpose library routines.
#define APR_IF_VALGRIND(x)
#define APR_PSPRINTF_MIN_STRINGSIZE
static int psprintf_flush(apr_vformatter_buff_t *vbuff)
#define SIZEOF_ALLOCATOR_T
static APR_INLINE void pool_concurrency_set_destroyed(apr_pool_t *pool)
static APR_INLINE void allocator_unlock(apr_allocator_t *allocator)
#define APR_VALGRIND_UNDEFINED(addr_, size_)
#define list_insert(node, point)
static void cleanup_pool_for_exec(apr_pool_t *p)
static APR_INLINE void allocator_free(apr_allocator_t *allocator, apr_memnode_t *node)
static void run_child_cleanups(cleanup_t **cref)
static APR_INLINE void allocator_lock(apr_allocator_t *allocator)
static APR_INLINE void pool_concurrency_set_idle(apr_pool_t *pool)
static APR_INLINE apr_size_t allocator_align(apr_size_t in_size)
static apr_allocator_t * global_allocator
static APR_INLINE apr_memnode_t * allocator_alloc(apr_allocator_t *allocator, apr_size_t in_size)
static void free_proc_chain(struct process_chain *procs)
static apr_pool_t * global_pool
#define APR_VALGRIND_NOACCESS(addr_, size_)
#define list_remove(node)
static apr_byte_t apr_pools_initialized
static void run_cleanups(cleanup_t **c)
static APR_INLINE void pool_concurrency_set_used(apr_pool_t *pool)
static APR_INLINE void pool_concurrency_init(apr_pool_t *pool)
#define node_free_space(node_)
APR Portability Routines.
APR Thread Mutex Routines.
APR Standard Headers Support.
apr_status_t apr_atomic_init(apr_pool_t *p)
apr_uint32_t apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t swap, apr_uint32_t cmp)
int apr_os_thread_equal(apr_os_thread_t tid1, apr_os_thread_t tid2)
const char server_rec server_rec ** ps
#define APR_CHILD_NOTDONE
apr_bucket apr_bucket_brigade * a
apr_pool_t const char apr_dbd_t const char ** error
apr_pool_t apr_dbd_t apr_dbd_results_t ** res
const apr_xml_elem int apr_array_header_t int const char apr_size_t * psize
#define apr_pool_join(a, b)
#define apr_pool_lock(pool, lock)
#define APR_ALLOCATOR_MAX_FREE_UNLIMITED
#define APR_MEMNODE_T_SIZE
const char int apr_pool_t * pool
const char apr_int32_t flag
void const char apr_status_t(* cleanup)(void *))
#define APR_ALIGN(size, boundary)
#define APR_ALIGN_DEFAULT(size)
#define APR_HASH_KEY_STRING
apr_vformatter_buff_t const char * fmt
apr_vformatter_buff_t * c
apr_vformatter_buff_t const char va_list ap
APR_DECLARE_NONSTD(void) apr_terminate(void)
int(* apr_abortfunc_t)(int retcode)
apr_abortfunc_t apr_allocator_t * allocator
apr_abortfunc_t apr_allocator_t const char * file_line
#define apr_pcalloc(p, size)
apr_pool_t apr_abortfunc_t abort_fn
apr_os_thread_t apr_os_thread_current()
apr_size_t current_free_index
apr_size_t max_free_index
apr_allocator_t * allocator
cleanup_t * free_cleanups
struct process_chain * subprocesses
apr_status_t(* child_cleanup_fn)(void *data)
apr_status_t(* plain_cleanup_fn)(void *data)
apr_kill_conditions_e kill_how
struct process_chain * next
apr_byte_t got_a_new_node
apr_vformatter_buff_t vbuff