⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 apr_pools.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 5 页
字号:
    *newpool = pool;    return APR_SUCCESS;}/* * "Print" functions *//* * apr_psprintf is implemented by writing directly into the current * block of the pool, starting right at first_avail.  If there's * insufficient room, then a new block is allocated and the earlier * output is copied over.  The new block isn't linked into the pool * until all the output is done. * * Note that this is completely safe because nothing else can * allocate in this apr_pool_t while apr_psprintf is running.  alarms are * blocked, and the only thing outside of apr_pools.c that's invoked * is apr_vformatter -- which was purposefully written to be * self-contained with no callouts. */struct psprintf_data {    apr_vformatter_buff_t vbuff;    apr_memnode_t   *node;    apr_pool_t      *pool;    apr_byte_t       got_a_new_node;    apr_memnode_t   *free;};#define APR_PSPRINTF_MIN_STRINGSIZE 32static int psprintf_flush(apr_vformatter_buff_t *vbuff){    struct psprintf_data *ps = (struct psprintf_data *)vbuff;    apr_memnode_t *node, *active;    apr_size_t cur_len, size;    char *strp;    apr_pool_t *pool;    apr_size_t free_index;    pool = ps->pool;    active = ps->node;    strp = ps->vbuff.curpos;    cur_len = strp - active->first_avail;    size = cur_len << 1;    /* Make sure that we don't try to use a block that has less     * than APR_PSPRINTF_MIN_STRINGSIZE bytes left in it.  This     * also catches the case where size == 0, which would result     * in reusing a block that can't even hold the NUL byte.     */    if (size < APR_PSPRINTF_MIN_STRINGSIZE)        size = APR_PSPRINTF_MIN_STRINGSIZE;    node = active->next;    if (!ps->got_a_new_node && size <= node_free_space(node)) {        list_remove(node);        list_insert(node, active);        node->free_index = 0;        pool->active = node;        free_index = (APR_ALIGN(active->endp - active->first_avail + 1,                                BOUNDARY_SIZE) - BOUNDARY_SIZE) >> BOUNDARY_INDEX;        active->free_index = (APR_UINT32_TRUNC_CAST)free_index;        node = active->next;        if (free_index < node->free_index) {            do {                node = node->next;            }            while (free_index < node->free_index);            list_remove(active);            list_insert(active, node);        }        node = pool->active;    }    else {        if ((node = allocator_alloc(pool->allocator, size)) == NULL)            return -1;        if (ps->got_a_new_node) {            active->next = ps->free;            ps->free = active;        }        ps->got_a_new_node = 1;    }    memcpy(node->first_avail, active->first_avail, cur_len);    ps->node = node;    ps->vbuff.curpos = node->first_avail + cur_len;    ps->vbuff.endpos = node->endp - 1; /* Save a byte for NUL terminator */    return 0;}APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap){    struct psprintf_data ps;    char *strp;    apr_size_t size;    apr_memnode_t *active, *node;    apr_size_t free_index;    ps.node = active = pool->active;    ps.pool = pool;    ps.vbuff.curpos  = ps.node->first_avail;    /* Save a byte for the NUL terminator */    ps.vbuff.endpos = ps.node->endp - 1;    ps.got_a_new_node = 0;    ps.free = NULL;    /* Make sure that the first node passed to apr_vformatter has at least     * room to hold the NUL terminator.     */    if (ps.node->first_avail == ps.node->endp) {        if (psprintf_flush(&ps.vbuff) == -1) {            if (pool->abort_fn) {                pool->abort_fn(APR_ENOMEM);            }            return NULL;        }    }    if (apr_vformatter(psprintf_flush, &ps.vbuff, fmt, ap) == -1) {        if (pool->abort_fn)            pool->abort_fn(APR_ENOMEM);        return NULL;    }    strp = ps.vbuff.curpos;    *strp++ = '\0';    size = strp - ps.node->first_avail;    size = APR_ALIGN_DEFAULT(size);    strp = ps.node->first_avail;    ps.node->first_avail += size;    if (ps.free)        allocator_free(pool->allocator, ps.free);    /*     * Link the node in if it's a new one     */    if (!ps.got_a_new_node)        return strp;    active = pool->active;    node = ps.node;    node->free_index = 0;    list_insert(node, active);    pool->active = node;    free_index = (APR_ALIGN(active->endp - active->first_avail + 1,                            BOUNDARY_SIZE) - BOUNDARY_SIZE) >> BOUNDARY_INDEX;    active->free_index = (APR_UINT32_TRUNC_CAST)free_index;    node = active->next;    if (free_index >= node->free_index)        return strp;    do {        node = node->next;    }    while (free_index < node->free_index);    list_remove(active);    list_insert(active, node);    return strp;}#else /* APR_POOL_DEBUG *//* * Debug helper functions *//* * Walk the pool tree rooted at pool, depth first.  When fn returns * anything other than 0, abort the traversal and return the value * returned by fn. */static int apr_pool_walk_tree(apr_pool_t *pool,                              int (*fn)(apr_pool_t *pool, void *data),                              void *data){    int rv;    apr_pool_t *child;    rv = fn(pool, data);    if (rv)        return rv;#if APR_HAS_THREADS    if (pool->mutex) {        apr_thread_mutex_lock(pool->mutex);                        }#endif /* APR_HAS_THREADS */    child = pool->child;    while (child) {        rv = apr_pool_walk_tree(child, fn, data);        if (rv)            break;        child = child->sibling;    }#if APR_HAS_THREADS    if (pool->mutex) {        apr_thread_mutex_unlock(pool->mutex);    }#endif /* APR_HAS_THREADS */    return rv;}#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)static void apr_pool_log_event(apr_pool_t *pool, const char *event,                               const char *file_line, int deref){    if (file_stderr) {        if (deref) {            apr_file_printf(file_stderr,                "POOL DEBUG: "                "[%lu"#if APR_HAS_THREADS                "/%lu"#endif /* APR_HAS_THREADS */                "] "                "%7s "                "(%10lu/%10lu/%10lu) "                "0x%pp \"%s\" "                "<%s> "                "(%u/%u/%u) "                "\n",                (unsigned long)getpid(),#if APR_HAS_THREADS                (unsigned long)apr_os_thread_current(),#endif /* APR_HAS_THREADS */                event,                (unsigned long)apr_pool_num_bytes(pool, 0),                (unsigned long)apr_pool_num_bytes(pool, 1),                (unsigned long)apr_pool_num_bytes(global_pool, 1),                pool, pool->tag,                file_line,                pool->stat_alloc, pool->stat_total_alloc, pool->stat_clear);        }        else {            apr_file_printf(file_stderr,                "POOL DEBUG: "                "[%lu"#if APR_HAS_THREADS                "/%lu"#endif /* APR_HAS_THREADS */                "] "                "%7s "                "                                   "                "0x%pp "                "<%s> "                "\n",                (unsigned long)getpid(),#if APR_HAS_THREADS                (unsigned long)apr_os_thread_current(),#endif /* APR_HAS_THREADS */                event,                pool,                file_line);        }    }}#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */#if (APR_POOL_DEBUG & APR_POOL_DEBUG_LIFETIME)static int pool_is_child_of(apr_pool_t *parent, void *data){    apr_pool_t *pool = (apr_pool_t *)data;    return (pool == parent);}static int apr_pool_is_child_of(apr_pool_t *pool, apr_pool_t *parent){    if (parent == NULL)        return 0;    return apr_pool_walk_tree(parent, pool_is_child_of, pool);}#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_LIFETIME) */static void apr_pool_check_integrity(apr_pool_t *pool){    /* Rule of thumb: use of the global pool is always     * ok, since the only user is apr_pools.c.  Unless     * people have searched for the top level parent and     * started to use that...     */    if (pool == global_pool || global_pool == NULL)        return;    /* Lifetime     * This basically checks to see if the pool being used is still     * a relative to the global pool.  If not it was previously     * destroyed, in which case we abort().     */#if (APR_POOL_DEBUG & APR_POOL_DEBUG_LIFETIME)    if (!apr_pool_is_child_of(pool, global_pool)) {#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)        apr_pool_log_event(pool, "LIFE",                           __FILE__ ":apr_pool_integrity check", 0);#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */        abort();    }#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_LIFETIME) */#if (APR_POOL_DEBUG & APR_POOL_DEBUG_OWNER)#if APR_HAS_THREADS    if (!apr_os_thread_equal(pool->owner, apr_os_thread_current())) {#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)        apr_pool_log_event(pool, "THREAD",                           __FILE__ ":apr_pool_integrity check", 0);#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */        abort();    }#endif /* APR_HAS_THREADS */#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_OWNER) */}/* * Initialization (debug) */APR_DECLARE(apr_status_t) apr_pool_initialize(void){    apr_status_t rv;#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)    char *logpath;    apr_file_t *debug_log = NULL;#endif    if (apr_pools_initialized++)        return APR_SUCCESS;    /* Since the debug code works a bit differently then the     * regular pools code, we ask for a lock here.  The regular     * pools code has got this lock embedded in the global     * allocator, a concept unknown to debug mode.     */    if ((rv = apr_pool_create_ex(&global_pool, NULL, NULL,                                 NULL)) != APR_SUCCESS) {        return rv;    }    apr_pool_tag(global_pool, "APR global pool");    apr_pools_initialized = 1;    /* This has to happen here because mutexes might be backed by     * atomics.  It used to be snug and safe in apr_initialize().     */    if ((rv = apr_atomic_init(global_pool)) != APR_SUCCESS) {        return rv;    }#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)    rv = apr_env_get(&logpath, "APR_POOL_DEBUG_LOG", global_pool);    /* Don't pass file_stderr directly to apr_file_open() here, since     * apr_file_open() can call back to apr_pool_log_event() and that     * may attempt to use then then non-NULL but partially set up file     * object. */    if (rv == APR_SUCCESS) {        apr_file_open(&debug_log, logpath, APR_APPEND|APR_WRITE|APR_CREATE,                      APR_OS_DEFAULT, global_pool);    }    else {        apr_file_open_stderr(&debug_log, global_pool);    }    /* debug_log is now a file handle. */    file_stderr = debug_log;    if (file_stderr) {        apr_file_printf(file_stderr,            "POOL DEBUG: [PID"#if APR_HAS_THREADS            "/TID"#endif /* APR_HAS_THREADS */            "] ACTION  (SIZE      /POOL SIZE /TOTAL SIZE) "            "POOL       \"TAG\" <__FILE__:__LINE__> (ALLOCS/TOTAL ALLOCS/CLEARS)\n");        apr_pool_log_event(global_pool, "GLOBAL", __FILE__ ":apr_pool_initialize", 0);    }#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */    return APR_SUCCESS;}APR_DECLARE(void) apr_pool_terminate(void){    if (!apr_pools_initialized)        return;    if (--apr_pools_initialized)        return;    apr_pool_destroy(global_pool); /* This will also destroy the mutex */    global_pool = NULL;#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)    file_stderr = NULL;#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */}/* * Memory allocation (debug) */static void *pool_alloc(apr_pool_t *pool, apr_size_t size){    debug_node_t *node;    void *mem;    if ((mem = malloc(size)) == NULL) {        if (pool->abort_fn)            pool->abort_fn(APR_ENOMEM);        return NULL;    }    node = pool->nodes;    if (node == NULL || node->index == 64) {        if ((node = malloc(SIZEOF_DEBUG_NODE_T)) == NULL) {            if (pool->abort_fn)                pool->abort_fn(APR_ENOMEM);            return NULL;        }        memset(node, 0, SIZEOF_DEBUG_NODE_T);        node->next = pool->nodes;        pool->nodes = node;        node->index = 0;    }    node->beginp[node->index] = mem;    node->endp[node->index] = (char *)mem + size;    node->index++;    pool->stat_alloc++;    pool->stat_total_alloc++;    return mem;}APR_DECLARE(void *) apr_palloc_debug(apr_pool_t *pool, apr_size_t size,                                     const char *file_line){    void *mem;    apr_pool_check_integrity(pool);    mem = pool_alloc(pool, size);#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALLOC)    apr_pool_log_event(pool, "PALLOC", file_line, 1);#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALLOC) */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -