]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: memory: cut pool allocator in 3 layers
authorWilly Tarreau <w@1wt.eu>
Mon, 8 Dec 2014 15:35:23 +0000 (16:35 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 24 Dec 2014 22:47:31 +0000 (23:47 +0100)
pool_alloc2() used to pick the entry from the pool, fall back to
pool_refill_alloc(), and to perform the poisonning itself, which
pool_refill_alloc() was also doing. While this led to optimal
code size, it imposes memory poisonning on the buffers as well,
which is extremely slow on large buffers.

This patch cuts the allocator in 3 layers :
  - a layer to pick the first entry from the pool without falling back to
    pool_refill_alloc() : pool_get_first()
  - a layer to allocate a dirty area by falling back to pool_refill_alloc()
    but never performing the poisonning : pool_alloc_dirty()
  - pool_alloc2() which calls the latter and optionally poisons the area

No functional changes were made.

include/common/memory.h
src/memory.c

index 330d7ff51a7898fb6782be33c933ce0028710645..3a0eaf6955ef212f421a1fa5fe8d3b24dbc3d620 100644 (file)
@@ -95,27 +95,52 @@ void pool_gc2();
 void *pool_destroy2(struct pool_head *pool);
 
 /*
- * Returns a pointer to type <type> taken from the
- * pool <pool_type> or dynamically allocated. In the
- * first case, <pool_type> is updated to point to the
- * next element in the list.
+ * Returns a pointer to type <type> taken from the pool <pool_type> if
+ * available, otherwise returns NULL. No malloc() is attempted, and poisonning
+ * is never performed. The purpose is to get the fastest possible allocation.
  */
-static inline void *pool_alloc2(struct pool_head *pool)
+static inline void *pool_get_first(struct pool_head *pool)
 {
        void *p;
 
-       if ((p = pool->free_list) == NULL) {
-               p = pool_refill_alloc(pool);
-       }
-       else {
+       if ((p = pool->free_list) != NULL) {
                pool->free_list = *(void **)pool->free_list;
                pool->used++;
-               if (unlikely(mem_poison_byte))
-                       memset(p, mem_poison_byte, pool->size);
        }
        return p;
 }
 
+/*
+ * Returns a pointer to type <type> taken from the pool <pool_type> or
+ * dynamically allocated. In the first case, <pool_type> is updated to point to
+ * the next element in the list. No memory poisonning is ever performed on the
+ * returned area.
+ */
+static inline void *pool_alloc_dirty(struct pool_head *pool)
+{
+       void *p;
+
+       if ((p = pool_get_first(pool)) == NULL)
+               p = pool_refill_alloc(pool);
+
+       return p;
+}
+
+/*
+ * Returns a pointer to type <type> taken from the pool <pool_type> or
+ * dynamically allocated. In the first case, <pool_type> is updated to point to
+ * the next element in the list. Memory poisonning is performed if enabled.
+ */
+static inline void *pool_alloc2(struct pool_head *pool)
+{
+       void *p;
+
+       p = pool_alloc_dirty(pool);
+       if (p && mem_poison_byte)
+               memset(p, mem_poison_byte, pool->size);
+       return p;
+}
+
 /*
  * Puts a memory area back to the corresponding pool.
  * Items are chained directly through a pointer that
index fcd7679314f2ca9df997dd9887e9130a20a6c47c..3fbc52059413b9d6a956eeb4062be1f336c86641 100644 (file)
@@ -96,8 +96,6 @@ void *pool_refill_alloc(struct pool_head *pool)
                if (!ret)
                        return NULL;
        }
-       if (mem_poison_byte)
-               memset(ret, mem_poison_byte, pool->size);
        pool->allocated++;
        pool->used++;
        return ret;