You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Sander Striker <st...@apache.org> on 2002/03/05 10:02:55 UTC

[PATCH] First cut at factoring out the pools allocator

Hi,

Below a patch to apr and a patch to httpd
to factor out the allocator from pools.  It
is only the first cut, so crucial details
like documentation are missing.

I'd like some feedback on the general idea
though.

Hopefully this helps when implementing the
bucket allocator.


Sander

Two patches inline, one new apr file attached
which should go into include/.

The apr stuff.

Index: include/apr_pools.h
===================================================================
RCS file: /home/cvs/apr/include/apr_pools.h,v
retrieving revision 1.78
diff -u -r1.78 apr_pools.h
--- include/apr_pools.h	9 Feb 2002 14:08:39 -0000	1.78
+++ include/apr_pools.h	2 Mar 2002 17:46:26 -0000
@@ -86,6 +86,11 @@
 #define APR_WANT_MEMFUNC
 #include "apr_want.h"
 
+/** The fundamental pool type */
+typedef struct apr_pool_t apr_pool_t;
+
+#include "apr_allocator.h"
+
 /**
  * Pool debug levels
  *
@@ -127,14 +132,12 @@
 #else
 #define APR_POOL_DEBUG 0
 #endif
-    
+
 #define APR_POOL_STRINGIZE(x) APR_POOL__STRINGIZE(x)
 #define APR_POOL__STRINGIZE(x) #x
 #define APR_POOL__FILE_LINE__ __FILE__ ":" APR_POOL_STRINGIZE(__LINE__)
-    
-    
-/** The fundamental pool type */
-typedef struct apr_pool_t apr_pool_t;
+
+
 
 /** A function that is called when allocation fails. */
 typedef int (*apr_abortfunc_t)(int retcode);
@@ -193,7 +196,7 @@
 APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool,
                                              apr_pool_t *parent,
                                              apr_abortfunc_t abort_fn,
-                                             apr_uint32_t flags);
+                                             apr_allocator_t *allocator);
 
 /**
  * Debug version of apr_pool_create_ex.
@@ -214,7 +217,7 @@
 APR_DECLARE(apr_status_t) apr_pool_create_ex_debug(apr_pool_t **newpool,
                                                    apr_pool_t *parent,
                                                    apr_abortfunc_t abort_fn,
-                                                   apr_uint32_t flags,
+                                                   apr_allocator_t *allocator,
                                                    const char *file_line);
 
 #if APR_POOL_DEBUG
Index: memory/unix/apr_pools.c
===================================================================
RCS file: /home/cvs/apr/memory/unix/apr_pools.c,v
retrieving revision 1.155
diff -u -r1.155 apr_pools.c
--- memory/unix/apr_pools.c	2 Mar 2002 09:26:07 -0000	1.155
+++ memory/unix/apr_pools.c	2 Mar 2002 17:46:31 -0000
@@ -59,6 +59,7 @@
 #include "apr_strings.h"
 #include "apr_general.h"
 #include "apr_pools.h"
+#include "apr_allocator.h"
 #include "apr_lib.h"
 #include "apr_thread_mutex.h"
 #include "apr_hash.h"
@@ -76,17 +77,17 @@
 
 
 /*
- * Debug level
+ * XXX: Memory node struct, move to private header file
  */
+struct apr_memnode_t {
+    apr_memnode_t *next;
+    apr_uint32_t   index;
+    char          *first_avail;
+    char          *endp;
+};
 
-#define APR_POOL_DEBUG_GENERAL  0x01
-#define APR_POOL_DEBUG_VERBOSE  0x02
-#define APR_POOL_DEBUG_LIFETIME 0x04
-#define APR_POOL_DEBUG_OWNER    0x08
-#define APR_POOL_DEBUG_VERBOSE_ALLOC 0x10
+#define SIZEOF_MEMNODE_T APR_ALIGN_DEFAULT(sizeof(apr_memnode_t))
 
-#define APR_POOL_DEBUG_VERBOSE_ALL (APR_POOL_DEBUG_VERBOSE \
-                                    | APR_POOL_DEBUG_VERBOSE_ALLOC)
 
 /*
  * Magic numbers
@@ -100,199 +101,94 @@
 
 
 /*
- * Structures
+ * Allocator
  */
-
-typedef struct cleanup_t cleanup_t;
-
-#if !APR_POOL_DEBUG
-typedef struct allocator_t allocator_t;
-typedef struct node_t node_t;
-
-struct node_t {
-    node_t      *next;
-    apr_uint32_t index;
-    char        *first_avail;
-    char        *endp;
-};
-
-struct allocator_t {
+struct apr_allocator_t {
     apr_uint32_t        max_index;
 #if APR_HAS_THREADS
     apr_thread_mutex_t *mutex;
 #endif /* APR_HAS_THREADS */
     apr_pool_t         *owner;
-    node_t             *free[MAX_INDEX];
-};
-
-#define SIZEOF_NODE_T       APR_ALIGN_DEFAULT(sizeof(node_t))
-#define SIZEOF_ALLOCATOR_T  APR_ALIGN_DEFAULT(sizeof(allocator_t))
-
-#else /* APR_POOL_DEBUG */
-
-typedef struct debug_node_t debug_node_t;
-
-struct debug_node_t {
-    debug_node_t *next;
-    apr_uint32_t  index;
-    void         *beginp[64];
-    void         *endp[64];
-};
-
-#define SIZEOF_DEBUG_NODE_T APR_ALIGN_DEFAULT(sizeof(debug_node_t))
-
-#endif /* APR_POOL_DEBUG */
-
-/* The ref field in the apr_pool_t struct holds a
- * pointer to the pointer referencing this pool.
- * It is used for parent, child, sibling management.
- * Look at apr_pool_create_ex() and apr_pool_destroy()
- * to see how it is used.
- */
-struct apr_pool_t {
-    apr_pool_t           *parent;
-    apr_pool_t           *child;
-    apr_pool_t           *sibling;
-    apr_pool_t          **ref;
-    cleanup_t            *cleanups;
-    struct process_chain *subprocesses;
-    apr_abortfunc_t       abort_fn;
-    apr_hash_t           *user_data;
-    const char           *tag;
-
-#if !APR_POOL_DEBUG
-    allocator_t          *allocator;
-    node_t               *active;
-    node_t               *self; /* The node containing the pool itself */
-    char                 *self_first_avail;
-
-#else /* APR_POOL_DEBUG */
-    debug_node_t         *nodes;
-    const char           *file_line;
-    apr_uint32_t          creation_flags;
-    unsigned int          stat_alloc;
-    unsigned int          stat_total_alloc;
-    unsigned int          stat_clear;
-#if APR_HAS_THREADS
-    apr_os_thread_t       owner;
-    apr_thread_mutex_t   *mutex;
-#endif /* APR_HAS_THREADS */
-#endif /* APR_POOL_DEBUG */
-#ifdef NETWARE
-    apr_os_proc_t         owner_proc;
-#endif /* defined(NETWARE) */
-};
-
-#define SIZEOF_POOL_T       APR_ALIGN_DEFAULT(sizeof(apr_pool_t))
-
-
-/*
- * Variables
- */
-
-static apr_byte_t   apr_pools_initialized = 0;
-static apr_pool_t  *global_pool = NULL;
-
-#if !APR_POOL_DEBUG
-static allocator_t  global_allocator = {
-    0,          /* max_index */
-#if APR_HAS_THREADS
-    NULL,       /* mutex */
-#endif /* APR_HAS_THREADS */
-    NULL,       /* owner */
-    { NULL }    /* free[0] */
+    apr_memnode_t      *free[MAX_INDEX];
 };
-#endif /* !APR_POOL_DEBUG */
-
-#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
-static apr_file_t *file_stderr = NULL;
-#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */
-
-/*
- * Local functions
- */
 
-static void run_cleanups(cleanup_t *c);
-static void run_child_cleanups(cleanup_t *c);
-static void free_proc_chain(struct process_chain *procs);
+#define SIZEOF_ALLOCATOR_T  APR_ALIGN_DEFAULT(sizeof(apr_allocator_t))
 
 
-#if !APR_POOL_DEBUG
 /*
- * Initialization
+ * Allocator
  */
 
-APR_DECLARE(apr_status_t) apr_pool_initialize(void)
+APR_DECLARE(apr_status_t) apr_allocator_create(apr_allocator_t **allocator)
 {
-    apr_status_t rv;
+    apr_allocator_t *new_allocator;
 
-    if (apr_pools_initialized++)
-        return APR_SUCCESS;
+    *allocator = NULL;
 
-    memset(&global_allocator, 0, sizeof(global_allocator));
+    if ((new_allocator = malloc(SIZEOF_ALLOCATOR_T)) == NULL)
+        return APR_ENOMEM;
 
-    if ((rv = apr_pool_create_ex(&global_pool, NULL, NULL, APR_POOL_FDEFAULT)) != APR_SUCCESS) {
-        return rv;
-    }
+    memset(new_allocator, 0, SIZEOF_ALLOCATOR_T);
 
-#if APR_HAS_THREADS
-    if ((rv = apr_thread_mutex_create(&global_allocator.mutex,
-                  APR_THREAD_MUTEX_DEFAULT, global_pool)) != APR_SUCCESS) {
-        return rv;
-    }
-#endif /* APR_HAS_THREADS */
-
-    global_allocator.owner = global_pool;
-    apr_pools_initialized = 1;
+    *allocator = new_allocator;
 
     return APR_SUCCESS;
 }
 
-APR_DECLARE(void) apr_pool_terminate(void)
+APR_DECLARE(void) apr_allocator_destroy(apr_allocator_t *allocator)
 {
-    if (!apr_pools_initialized)
-        return;
+    apr_uint32_t index;
+    apr_memnode_t *node, **ref;
 
-    apr_pools_initialized = 0;
+    for (index = 0; index < MAX_INDEX; index++) {
+        ref = &allocator->free[index];
+        while ((node = *ref) != NULL) {
+            *ref = node->next;
+            free(node);
+        }
+    }
 
-    apr_pool_destroy(global_pool); /* This will also destroy the mutex */
-    global_pool = NULL;
+    free(allocator);
+}
 
-    memset(&global_allocator, 0, sizeof(global_allocator));
+#if APR_HAS_THREADS
+APR_INLINE
+APR_DECLARE(void) apr_allocator_set_mutex(apr_allocator_t *allocator,
+                                          apr_thread_mutex_t *mutex)
+{
+    allocator->mutex = mutex;
 }
 
-#ifdef NETWARE
-void netware_pool_proc_cleanup ()
+APR_INLINE
+APR_DECLARE(apr_thread_mutex_t *) apr_allocator_get_mutex(
+                                      apr_allocator_t *allocator)
 {
-    apr_pool_t *pool = global_pool->child;
-    apr_os_proc_t owner_proc = (apr_os_proc_t)getnlmhandle();
+    return allocator->mutex;
+}
+#endif /* APR_HAS_THREADS */
 
-    while (pool) {
-        if (pool->owner_proc == owner_proc) {
-            apr_pool_destroy (pool);
-            pool = global_pool->child;
-        }
-        else {
-            pool = pool->sibling;
-        }
-    }
-    return;
+APR_DECLARE(void) apr_allocator_set_owner(apr_allocator_t *allocator,
+                                          apr_pool_t *pool)
+{
+    allocator->owner = pool;
 }
-#endif /* defined(NETWARE) */
 
-/*
- * Memory allocation
- */
+APR_DECLARE(apr_pool_t *) apr_allocator_get_owner(apr_allocator_t *allocator)
+{
+    return allocator->owner;
+}
 
-static APR_INLINE node_t *node_malloc(allocator_t *allocator, apr_size_t size)
+APR_INLINE
+APR_DECLARE(apr_memnode_t *) apr_allocator_alloc(apr_allocator_t *allocator,
+                                                 apr_size_t size)
 {
-    node_t *node, **ref;
+    apr_memnode_t *node, **ref;
     apr_uint32_t i, index, max_index;
 
     /* Round up the block size to the next boundary, but always
      * allocate at least a certain size (MIN_ALLOC).
      */
-    size = APR_ALIGN(size + SIZEOF_NODE_T, BOUNDARY_SIZE);
+    size = APR_ALIGN(size + SIZEOF_MEMNODE_T, BOUNDARY_SIZE);
     if (size < MIN_ALLOC)
         size = MIN_ALLOC;
 
@@ -350,7 +246,7 @@
 #endif /* APR_HAS_THREADS */
 
             node->next = NULL;
-            node->first_avail = (char *)node + SIZEOF_NODE_T;
+            node->first_avail = (char *)node + SIZEOF_MEMNODE_T;
 
             return node;
         }
@@ -386,7 +282,7 @@
 #endif /* APR_HAS_THREADS */
 
             node->next = NULL;
-            node->first_avail = (char *)node + SIZEOF_NODE_T;
+            node->first_avail = (char *)node + SIZEOF_MEMNODE_T;
 
             return node;
         }
@@ -405,15 +301,16 @@
 
     node->next = NULL;
     node->index = index;
-    node->first_avail = (char *)node + SIZEOF_NODE_T;
+    node->first_avail = (char *)node + SIZEOF_MEMNODE_T;
     node->endp = (char *)node + size;
 
     return node;
 }
 
-static APR_INLINE void node_free(allocator_t *allocator, node_t *node)
+APR_INLINE
+APR_DECLARE(void) apr_allocator_free(apr_allocator_t *allocator, apr_memnode_t *node)
 {
-    node_t *next;
+    apr_memnode_t *next;
     apr_uint32_t index, max_index;
 
 #if APR_HAS_THREADS
@@ -457,9 +354,192 @@
 #endif /* APR_HAS_THREADS */
 }
 
+
+/*
+ * Debug level
+ */
+
+#define APR_POOL_DEBUG_GENERAL  0x01
+#define APR_POOL_DEBUG_VERBOSE  0x02
+#define APR_POOL_DEBUG_LIFETIME 0x04
+#define APR_POOL_DEBUG_OWNER    0x08
+#define APR_POOL_DEBUG_VERBOSE_ALLOC 0x10
+
+#define APR_POOL_DEBUG_VERBOSE_ALL (APR_POOL_DEBUG_VERBOSE \
+                                    | APR_POOL_DEBUG_VERBOSE_ALLOC)
+
+
+/*
+ * Structures
+ */
+
+typedef struct cleanup_t cleanup_t;
+
+#if APR_POOL_DEBUG
+
+typedef struct debug_node_t debug_node_t;
+
+struct debug_node_t {
+    debug_node_t *next;
+    apr_uint32_t  index;
+    void         *beginp[64];
+    void         *endp[64];
+};
+
+#define SIZEOF_DEBUG_NODE_T APR_ALIGN_DEFAULT(sizeof(debug_node_t))
+
+#endif /* APR_POOL_DEBUG */
+
+/* The ref field in the apr_pool_t struct holds a
+ * pointer to the pointer referencing this pool.
+ * It is used for parent, child, sibling management.
+ * Look at apr_pool_create_ex() and apr_pool_destroy()
+ * to see how it is used.
+ */
+struct apr_pool_t {
+    apr_pool_t           *parent;
+    apr_pool_t           *child;
+    apr_pool_t           *sibling;
+    apr_pool_t          **ref;
+    cleanup_t            *cleanups;
+    struct process_chain *subprocesses;
+    apr_abortfunc_t       abort_fn;
+    apr_hash_t           *user_data;
+    const char           *tag;
+
+#if !APR_POOL_DEBUG
+    apr_allocator_t      *allocator;
+    apr_memnode_t        *active;
+    apr_memnode_t        *self; /* The node containing the pool itself */
+    char                 *self_first_avail;
+
+#else /* APR_POOL_DEBUG */
+    debug_node_t         *nodes;
+    const char           *file_line;
+    apr_uint32_t          creation_flags;
+    unsigned int          stat_alloc;
+    unsigned int          stat_total_alloc;
+    unsigned int          stat_clear;
+#if APR_HAS_THREADS
+    apr_os_thread_t       owner;
+    apr_thread_mutex_t   *mutex;
+#endif /* APR_HAS_THREADS */
+#endif /* APR_POOL_DEBUG */
+#ifdef NETWARE
+    apr_os_proc_t         owner_proc;
+#endif /* defined(NETWARE) */
+};
+
+#define SIZEOF_POOL_T       APR_ALIGN_DEFAULT(sizeof(apr_pool_t))
+
+
+/*
+ * Variables
+ */
+
+static apr_byte_t   apr_pools_initialized = 0;
+static apr_pool_t  *global_pool = NULL;
+
+#if !APR_POOL_DEBUG
+static apr_allocator_t *global_allocator = NULL;
+#endif /* !APR_POOL_DEBUG */
+
+#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL)
+static apr_file_t *file_stderr = NULL;
+#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */
+
+/*
+ * Local functions
+ */
+
+static void run_cleanups(cleanup_t *c);
+static void run_child_cleanups(cleanup_t *c);
+static void free_proc_chain(struct process_chain *procs);
+
+
+#if !APR_POOL_DEBUG
+/*
+ * Initialization
+ */
+
+APR_DECLARE(apr_status_t) apr_pool_initialize(void)
+{
+    apr_status_t rv;
+
+    if (apr_pools_initialized++)
+        return APR_SUCCESS;
+
+    if ((rv = apr_allocator_create(&global_allocator)) != APR_SUCCESS) {
+        apr_pools_initialized = 0;
+        return rv;
+    }
+
+    if ((rv = apr_pool_create_ex(&global_pool, NULL, NULL,
+                                 global_allocator)) != APR_SUCCESS) {
+        apr_allocator_destroy(global_allocator);
+        global_allocator = NULL;
+        apr_pools_initialized = 0;
+        return rv;
+    }
+
+#if APR_HAS_THREADS
+    {
+        apr_thread_mutex_t *mutex;
+
+        if ((rv = apr_thread_mutex_create(&mutex,
+                                          APR_THREAD_MUTEX_DEFAULT,
+                                          global_pool)) != APR_SUCCESS) {
+            return rv;
+        }
+
+        apr_allocator_set_mutex(global_allocator, mutex);
+    }
+#endif /* APR_HAS_THREADS */
+
+    apr_allocator_set_owner(global_allocator, global_pool);
+
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(void) apr_pool_terminate(void)
+{
+    if (!apr_pools_initialized)
+        return;
+
+    apr_pools_initialized = 0;
+
+    apr_pool_destroy(global_pool); /* This will also destroy the mutex */
+    global_pool = NULL;
+
+    global_allocator = NULL;
+}
+
+#ifdef NETWARE
+void netware_pool_proc_cleanup ()
+{
+    apr_pool_t *pool = global_pool->child;
+    apr_os_proc_t owner_proc = (apr_os_proc_t)getnlmhandle();
+
+    while (pool) {
+        if (pool->owner_proc == owner_proc) {
+            apr_pool_destroy (pool);
+            pool = global_pool->child;
+        }
+        else {
+            pool = pool->sibling;
+        }
+    }
+    return;
+}
+#endif /* defined(NETWARE) */
+
+/*
+ * Memory allocation
+ */
+
 APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t size)
 {
-    node_t *active, *node;
+    apr_memnode_t *active, *node;
     void *mem;
     char *endp;
 
@@ -475,7 +555,7 @@
         return mem;
     }
 
-    if ((node = node_malloc(pool->allocator, size)) == NULL) {
+    if ((node = apr_allocator_alloc(pool->allocator, size)) == NULL) {
         if (pool->abort_fn)
             pool->abort_fn(APR_ENOMEM);
 
@@ -509,7 +589,7 @@
 
 APR_DECLARE(void) apr_pool_clear(apr_pool_t *pool)
 {
-    node_t *active;
+    apr_memnode_t *active;
 
     /* Destroy the subpools.  The subpools will detach themselves from
      * this pool thus this loop is safe and easy.
@@ -537,15 +617,14 @@
     if (active->next == NULL)
         return;
 
-    node_free(pool->allocator, active->next);
+    apr_allocator_free(pool->allocator, active->next);
     active->next = NULL;
 }
 
 APR_DECLARE(void) apr_pool_destroy(apr_pool_t *pool)
 {
-    node_t *node, *active, **ref;
-    allocator_t *allocator;
-    apr_uint32_t index;
+    apr_memnode_t *active;
+    apr_allocator_t *allocator;
 
     /* Destroy the subpools.  The subpools will detach themselve from
      * this pool thus this loop is safe and easy.
@@ -564,7 +643,7 @@
 #if APR_HAS_THREADS
         apr_thread_mutex_t *mutex;
 
-        if ((mutex = pool->parent->allocator->mutex) != NULL)
+        if ((mutex = apr_allocator_get_mutex(pool->parent->allocator)) != NULL)
             apr_thread_mutex_lock(mutex);
 #endif /* APR_HAS_THREADS */
 
@@ -583,43 +662,28 @@
     allocator = pool->allocator;
     active = pool->self;
 
+    /* Free all the nodes in the pool (including the node holding the
+     * pool struct), by giving them back to the allocator.
+     */
+    apr_allocator_free(allocator, active);
+
     /* If this pool happens to be the owner of the allocator, free
      * everything in the allocator (that includes the pool struct
      * and the allocator).  Don't worry about destroying the optional mutex
      * in the allocator, it will have been destroyed by the cleanup function.
      */
-    if (allocator->owner == pool) {
-        for (index = 0; index < MAX_INDEX; index++) {
-            ref = &allocator->free[index];
-            while ((node = *ref) != NULL) {
-                *ref = node->next;
-                free(node);
-            }
-        }
-
-        ref = &active;
-        while ((node = *ref) != NULL) {
-            *ref = node->next;
-            free(node);
-        }
-
-        return;
+    if (apr_allocator_get_owner(allocator) == pool) {
+        apr_allocator_destroy(allocator);
     }
-
-    /* Free all the nodes in the pool (including the node holding the
-     * pool struct), by giving them back to the allocator.
-     */
-    node_free(allocator, active);
 }
 
 APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool,
                                              apr_pool_t *parent,
                                              apr_abortfunc_t abort_fn,
-                                             apr_uint32_t flags)
+                                             apr_allocator_t *allocator)
 {
     apr_pool_t *pool;
-    node_t *node;
-    allocator_t *allocator, *new_allocator;
+    apr_memnode_t *node;
 
     *newpool = NULL;
 
@@ -629,56 +693,27 @@
     if (!abort_fn && parent)
         abort_fn = parent->abort_fn;
 
-    allocator = parent ? parent->allocator : &global_allocator;
-    if ((node = node_malloc(allocator, MIN_ALLOC - SIZEOF_NODE_T)) == NULL) {
+    if (allocator == NULL)
+        allocator = parent->allocator;
+
+    if ((node = apr_allocator_alloc(allocator, MIN_ALLOC - SIZEOF_MEMNODE_T)) == NULL) {
         if (abort_fn)
             abort_fn(APR_ENOMEM);
 
         return APR_ENOMEM;
     }
 
-    if ((flags & APR_POOL_FNEW_ALLOCATOR) == APR_POOL_FNEW_ALLOCATOR) {
-        new_allocator = (allocator_t *)node->first_avail;
-        pool = (apr_pool_t *)((char *)new_allocator + SIZEOF_ALLOCATOR_T);
-        node->first_avail = pool->self_first_avail = (char *)pool + SIZEOF_POOL_T;
-
-        memset(new_allocator, 0, SIZEOF_ALLOCATOR_T);
-        new_allocator->owner = pool;
-
-        pool->allocator = new_allocator;
-        pool->active = pool->self = node;
-        pool->abort_fn = abort_fn;
-        pool->child = NULL;
-        pool->cleanups = NULL;
-        pool->subprocesses = NULL;
-        pool->user_data = NULL;
-        pool->tag = NULL;
-
-#if APR_HAS_THREADS
-        if ((flags & APR_POOL_FLOCK) == APR_POOL_FLOCK) {
-            apr_status_t rv;
-
-            if ((rv = apr_thread_mutex_create(&allocator->mutex,
-                    APR_THREAD_MUTEX_DEFAULT, pool)) != APR_SUCCESS) {
-                node_free(allocator, node);
-                return rv;
-            }
-        }
-#endif /* APR_HAS_THREADS */
-    }
-    else {
-        pool = (apr_pool_t *)node->first_avail;
-        node->first_avail = pool->self_first_avail = (char *)pool + SIZEOF_POOL_T;
+    pool = (apr_pool_t *)node->first_avail;
+    node->first_avail = pool->self_first_avail = (char *)pool + SIZEOF_POOL_T;
 
-        pool->allocator = allocator;
-        pool->active = pool->self = node;
-        pool->abort_fn = abort_fn;
-        pool->child = NULL;
-        pool->cleanups = NULL;
-        pool->subprocesses = NULL;
-        pool->user_data = NULL;
-        pool->tag = NULL;
-    }
+    pool->allocator = allocator;
+    pool->active = pool->self = node;
+    pool->abort_fn = abort_fn;
+    pool->child = NULL;
+    pool->cleanups = NULL;
+    pool->subprocesses = NULL;
+    pool->user_data = NULL;
+    pool->tag = NULL;
 
 #ifdef NETWARE
     pool->owner_proc = (apr_os_proc_t)getnlmhandle();
@@ -686,9 +721,12 @@
 
     if ((pool->parent = parent) != NULL) {
 #if APR_HAS_THREADS
-        if (allocator->mutex)
-            apr_thread_mutex_lock(allocator->mutex);
+        apr_thread_mutex_t *mutex;
+
+        if ((mutex = apr_allocator_get_mutex(allocator)) != NULL)
+            apr_thread_mutex_lock(mutex);
 #endif /* APR_HAS_THREADS */
+
         if ((pool->sibling = parent->child) != NULL)
             pool->sibling->ref = &pool->sibling;
 
@@ -696,8 +734,8 @@
         pool->ref = &parent->child;
 
 #if APR_HAS_THREADS
-        if (allocator->mutex)
-            apr_thread_mutex_unlock(allocator->mutex);
+        if (mutex)
+            apr_thread_mutex_unlock(mutex);
 #endif /* APR_HAS_THREADS */
     }
     else {
@@ -731,26 +769,26 @@
 
 struct psprintf_data {
     apr_vformatter_buff_t vbuff;
-    node_t               *node;
-    allocator_t          *allocator;
-    apr_byte_t            got_a_new_node;
-    node_t               *free;
+    apr_memnode_t   *node;
+    apr_allocator_t *allocator;
+    apr_byte_t       got_a_new_node;
+    apr_memnode_t   *free;
 };
 
 static int psprintf_flush(apr_vformatter_buff_t *vbuff)
 {
     struct psprintf_data *ps = (struct psprintf_data *)vbuff;
-    node_t *node, *active;
+    apr_memnode_t *node, *active;
     apr_size_t cur_len;
     char *strp;
-    allocator_t *allocator;
+    apr_allocator_t *allocator;
 
     allocator = ps->allocator;
     node = ps->node;
     strp = ps->vbuff.curpos;
     cur_len = strp - node->first_avail;
 
-    if ((active = node_malloc(allocator, cur_len << 1)) == NULL)
+    if ((active = apr_allocator_alloc(allocator, cur_len << 1)) == NULL)
         return -1;
 
     memcpy(active->first_avail, node->first_avail, cur_len);
@@ -773,7 +811,7 @@
     struct psprintf_data ps;
     char *strp;
     apr_size_t size;
-    node_t *active;
+    apr_memnode_t *active;
 
     ps.node = active = pool->active;
     ps.allocator = pool->allocator;
@@ -807,7 +845,7 @@
     }
 
     if (ps.free)
-        node_free(ps.allocator, ps.free);
+        apr_allocator_free(ps.allocator, ps.free);
 
     return strp;
 }
@@ -1831,10 +1869,10 @@
 APR_DECLARE(apr_status_t) apr_pool_create_ex_debug(apr_pool_t **newpool,
                                                    apr_pool_t *parent,
                                                    apr_abortfunc_t abort_fn,
-                                                   apr_uint32_t flags,
+                                                   apr_allocator_t *allocator,
                                                    const char *file_line)
 {
-    return apr_pool_create_ex(newpool, parent, abort_fn, flags);
+    return apr_pool_create_ex(newpool, parent, abort_fn, allocator);
 }
 
 #else /* APR_POOL_DEBUG */


The httpd stuff.

Index: server/mpm/beos/beos.c
===================================================================
RCS file: /home/cvspublic/httpd-2.0/server/mpm/beos/beos.c,v
retrieving revision 1.85
diff -u -r1.85 beos.c
--- server/mpm/beos/beos.c	21 Feb 2002 18:52:28 -0000	1.85
+++ server/mpm/beos/beos.c	4 Mar 2002 14:02:57 -0000
@@ -359,6 +359,7 @@
     proc_info * ti = dummy;
     int child_slot = ti->slot;
     apr_pool_t *tpool = ti->tpool;
+    apr_allocator_t *allocator;
     apr_socket_t *csd = NULL;
     apr_pool_t *ptrans;		/* Pool for per-transaction stuff */
     apr_socket_t *sd = NULL;
@@ -378,7 +379,10 @@
     sigfillset(&sig_mask);
     sigprocmask(SIG_BLOCK, &sig_mask, NULL);
 
-    apr_pool_create_ex(&ptrans, tpool, NULL, APR_POOL_FNEW_ALLOCATOR);
+    apr_allocator_create(&allocator);
+    apr_pool_create_ex(&ptrans, tpool, NULL, allocator);
+    apr_allocator_set_owner(ptrans);
+
     apr_pool_tag(ptrans, "transaction");
 
     apr_lock_acquire(worker_thread_count_mutex);
Index: server/mpm/netware/mpm_netware.c
===================================================================
RCS file: /home/cvspublic/httpd-2.0/server/mpm/netware/mpm_netware.c,v
retrieving revision 1.34
diff -u -r1.34 mpm_netware.c
--- server/mpm/netware/mpm_netware.c	15 Feb 2002 20:48:19 -0000	1.34
+++ server/mpm/netware/mpm_netware.c	4 Mar 2002 14:03:03 -0000
@@ -351,6 +351,7 @@
     ap_listen_rec *lr;
     ap_listen_rec *last_lr = NULL;
     apr_pool_t *ptrans;
+    apr_allocator_t *allocator;
     conn_rec *current_conn;
     apr_status_t stat = APR_EINIT;
     int worker_num_arg = (int)arg;
@@ -368,7 +369,10 @@
     tv.tv_sec = 1;
     tv.tv_usec = 0;
 
-    apr_pool_create_ex(&ptrans, NULL, NULL, APR_POOL_FNEW_ALLOCATOR);
+    apr_allocator_create(&allocator);
+    apr_pool_create_ex(&ptrans, NULL, NULL, allocator);
+    apr_allocator_set_owner(allocator, ptrans);
+
     apr_pool_tag(ptrans, "transaction");
 
     apr_thread_mutex_lock(worker_thread_count_mutex);
Index: server/mpm/prefork/prefork.c
===================================================================
RCS file: /home/cvspublic/httpd-2.0/server/mpm/prefork/prefork.c,v
retrieving revision 1.246
diff -u -r1.246 prefork.c
--- server/mpm/prefork/prefork.c	21 Feb 2002 18:52:28 -0000	1.246
+++ server/mpm/prefork/prefork.c	4 Mar 2002 14:03:10 -0000
@@ -518,6 +518,7 @@
 static void child_main(int child_num_arg)
 {
     apr_pool_t *ptrans;
+    apr_allocator_t *allocator;
     conn_rec *current_conn;
     apr_status_t status = APR_EINIT;
     int i;
@@ -537,7 +538,9 @@
     /* Get a sub context for global allocations in this child, so that
      * we can have cleanups occur when the child exits.
      */
-    apr_pool_create_ex(&pchild, pconf, NULL, APR_POOL_FNEW_ALLOCATOR);
+    apr_allocator_create(&allocator);
+    apr_pool_create_ex(&pchild, pconf, NULL, allocator);
+    apr_allocator_set_owner(allocator, pchild);
 
     apr_pool_create(&ptrans, pchild);
     apr_pool_tag(ptrans, "transaction");
Index: server/mpm/worker/worker.c
===================================================================
RCS file: /home/cvspublic/httpd-2.0/server/mpm/worker/worker.c,v
retrieving revision 1.81
diff -u -r1.81 worker.c
--- server/mpm/worker/worker.c	24 Feb 2002 20:53:26 -0000	1.81
+++ server/mpm/worker/worker.c	4 Mar 2002 14:03:20 -0000
@@ -672,7 +672,11 @@
         if (!workers_may_exit) {
             /* create a new transaction pool for each accepted socket */
             if (recycled_pool == NULL) {
-                apr_pool_create_ex(&ptrans, NULL, NULL, APR_POOL_FNEW_ALLOCATOR);
+                apr_allocator_t *allocator;
+
+                apr_allocator_create(&allocator);
+                apr_pool_create_ex(&ptrans, NULL, NULL, allocator);
+                apr_allocator_set_owner(allocator, ptrans);
             }
             else {
                 ptrans = recycled_pool;

RE: [PATCH] First cut at factoring out the pools allocator

Posted by Sander Striker <st...@apache.org>.
> From: Brian Pane [mailto:brian.pane@cnet.com]
> Sent: 13 March 2002 15:59

> Justin Erenkrantz wrote:
> 
> >On Tue, Mar 05, 2002 at 10:02:55AM +0100, Sander Striker wrote:
> >
> >>Hi,
> >>
> >>Below a patch to apr and a patch to httpd
> >>to factor out the allocator from pools.  It
> >>is only the first cut, so crucial details
> >>like documentation are missing.
> >>
> >>I'd like some feedback on the general idea
> >>though.
> >>
> >>Hopefully this helps when implementing the
> >>bucket allocator.
> >>
> >
> >+1.  I like the API.  Brian's suggestion is goodness, but shouldn't
> >stop this from going in.
> >
> 
> +1.  I think we'll need to implement my suggestion (a variant
> of the allocation function that reserves space for the internal
> header struct but still stays within 8KB) in support of the
> bucket free lists, but that that's a simple, additive change
> that we can put in later--so +1 on committing Sander's new
> allocator API now.

Ok, I'll try and get it in tonight.

I'm not entirely sure we need the extra allocation function though,
but we can decide on that later.

Sander

RE: [PATCH] First cut at factoring out the pools allocator

Posted by Sander Striker <st...@apache.org>.
> From: Brian Pane [mailto:brian.pane@cnet.com]
> Sent: 13 March 2002 15:59

> Justin Erenkrantz wrote:
> 
> >On Tue, Mar 05, 2002 at 10:02:55AM +0100, Sander Striker wrote:
> >
> >>Hi,
> >>
> >>Below a patch to apr and a patch to httpd
> >>to factor out the allocator from pools.  It
> >>is only the first cut, so crucial details
> >>like documentation are missing.
> >>
> >>I'd like some feedback on the general idea
> >>though.
> >>
> >>Hopefully this helps when implementing the
> >>bucket allocator.
> >>
> >
> >+1.  I like the API.  Brian's suggestion is goodness, but shouldn't
> >stop this from going in.
> >
> 
> +1.  I think we'll need to implement my suggestion (a variant
> of the allocation function that reserves space for the internal
> header struct but still stays within 8KB) in support of the
> bucket free lists, but that that's a simple, additive change
> that we can put in later--so +1 on committing Sander's new
> allocator API now.

Ok, I'll try and get it in tonight.

I'm not entirely sure we need the extra allocation function though,
but we can decide on that later.

Sander

Re: [PATCH] First cut at factoring out the pools allocator

Posted by Brian Pane <br...@cnet.com>.
Justin Erenkrantz wrote:

>On Tue, Mar 05, 2002 at 10:02:55AM +0100, Sander Striker wrote:
>
>>Hi,
>>
>>Below a patch to apr and a patch to httpd
>>to factor out the allocator from pools.  It
>>is only the first cut, so crucial details
>>like documentation are missing.
>>
>>I'd like some feedback on the general idea
>>though.
>>
>>Hopefully this helps when implementing the
>>bucket allocator.
>>
>
>+1.  I like the API.  Brian's suggestion is goodness, but shouldn't
>stop this from going in.
>

+1.  I think we'll need to implement my suggestion (a variant
of the allocation function that reserves space for the internal
header struct but still stays within 8KB) in support of the
bucket free lists, but that that's a simple, additive change
that we can put in later--so +1 on committing Sander's new
allocator API now.

--Brian




Re: [PATCH] First cut at factoring out the pools allocator

Posted by Brian Pane <br...@cnet.com>.
Justin Erenkrantz wrote:

>On Tue, Mar 05, 2002 at 10:02:55AM +0100, Sander Striker wrote:
>
>>Hi,
>>
>>Below a patch to apr and a patch to httpd
>>to factor out the allocator from pools.  It
>>is only the first cut, so crucial details
>>like documentation are missing.
>>
>>I'd like some feedback on the general idea
>>though.
>>
>>Hopefully this helps when implementing the
>>bucket allocator.
>>
>
>+1.  I like the API.  Brian's suggestion is goodness, but shouldn't
>stop this from going in.
>

+1.  I think we'll need to implement my suggestion (a variant
of the allocation function that reserves space for the internal
header struct but still stays within 8KB) in support of the
bucket free lists, but that that's a simple, additive change
that we can put in later--so +1 on committing Sander's new
allocator API now.

--Brian




Re: [PATCH] First cut at factoring out the pools allocator

Posted by Justin Erenkrantz <je...@ebuilt.com>.
On Tue, Mar 05, 2002 at 10:02:55AM +0100, Sander Striker wrote:
> Hi,
> 
> Below a patch to apr and a patch to httpd
> to factor out the allocator from pools.  It
> is only the first cut, so crucial details
> like documentation are missing.
> 
> I'd like some feedback on the general idea
> though.
> 
> Hopefully this helps when implementing the
> bucket allocator.

+1.  I like the API.  Brian's suggestion is goodness, but shouldn't
stop this from going in.

Two slight implementation problems:

- apr_thread_mutex.h is now a dependency of apr_allocator.h.  That
  means it can't use APR_POOL_DECLARE_ACCESSOR since apr_pools.h
  requires this file.  So, I just expanded the declaration in
  apr_thread_mutex.h.  I'll leave it up to you how to resolve this
  (either expand it there or move the DECLARE macro somewhere else).
  I think if we put a big XXX in that file and expand it, we should
  be okay for now.  (Perhaps with a note near the POOL_DECLARE
  definition that apr_thread_mutex.h is a special exception.)

- I think APR_POOL_DEBUG isn't working.  Namely the
  apr_pool_create_ex prototype is wrong.

And, I think the API is fine considering that this gives the
bucket code a chance to use it.  So, please commit at your
earliest chance.  =)  -- justin


Re: [PATCH] First cut at factoring out the pools allocator

Posted by Brian Pane <bp...@pacbell.net>.
Sander Striker wrote:

>Hi,
>
>Below a patch to apr and a patch to httpd
>to factor out the allocator from pools.  It
>is only the first cut, so crucial details
>like documentation are missing.
>
>I'd like some feedback on the general idea
>though.
>
>Hopefully this helps when implementing the
>bucket allocator.
>

The only additional thing that I think this API
needs is a way to say "give me a block in which
the total size--including all of the allocator's
internal block header structures--is X."

The idea here is to allow things like the bucket
freelist code to alloc:
  8KB - sizeof(allocator headers)
so that the entire structure fits in two memory
pages.

The API could look something like this:

APR_DECLARE(apr_memnode_t *) apr_allocator_alloc2(apr_allocator_t 
*allocator,
                                                  apr_size_t target_size,
                                                  apr_size_t *actual_size);

where "target_size" is an upper bound on the number
of bytes you want and "actual_size" is how many bytes
you actually get to work with (equal to target_size
minus the space devoted to the allocator's internal
block header structs).

--Brian






Re: [PATCH] First cut at factoring out the pools allocator

Posted by Justin Erenkrantz <je...@ebuilt.com>.
On Tue, Mar 05, 2002 at 10:02:55AM +0100, Sander Striker wrote:
> Hi,
> 
> Below a patch to apr and a patch to httpd
> to factor out the allocator from pools.  It
> is only the first cut, so crucial details
> like documentation are missing.
> 
> I'd like some feedback on the general idea
> though.
> 
> Hopefully this helps when implementing the
> bucket allocator.

+1.  I like the API.  Brian's suggestion is goodness, but shouldn't
stop this from going in.

Two slight implementation problems:

- apr_thread_mutex.h is now a dependency of apr_allocator.h.  That
  means it can't use APR_POOL_DECLARE_ACCESSOR since apr_pools.h
  requires this file.  So, I just expanded the declaration in
  apr_thread_mutex.h.  I'll leave it up to you how to resolve this
  (either expand it there or move the DECLARE macro somewhere else).
  I think if we put a big XXX in that file and expand it, we should
  be okay for now.  (Perhaps with a note near the POOL_DECLARE
  definition that apr_thread_mutex.h is a special exception.)

- I think APR_POOL_DEBUG isn't working.  Namely the
  apr_pool_create_ex prototype is wrong.

And, I think the API is fine considering that this gives the
bucket code a chance to use it.  So, please commit at your
earliest chance.  =)  -- justin