]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: pools: add an alignment property
authorWilly Tarreau <w@1wt.eu>
Tue, 5 Aug 2025 16:03:09 +0000 (18:03 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 6 Aug 2025 17:20:36 +0000 (19:20 +0200)
This will be used to declare aligned pools. For now it's not used,
but it's properly set from the various registrations that compose
a pool, and rounded up to the next power of 2, with a minimum of
sizeof(void*).

The alignment is returned in the "show pools" part that indicates
the entry size. E.g. "(56 bytes/8)" means 56 bytes, aligned by 8.

include/haproxy/pool-t.h
src/pool.c

index 52765a62747f1d50f013b8bd51b985dabe7e2c22..883d4d5bccd7f5f65841b7e8434cb7f63d17ebd3 100644 (file)
@@ -128,6 +128,7 @@ struct pool_head {
        unsigned int minavail;  /* how many chunks are expected to be used */
        unsigned int size;      /* chunk size */
        unsigned int flags;     /* MEM_F_* */
+       unsigned int align;     /* alignment size */
        unsigned int users;     /* number of pools sharing this zone */
        unsigned int alloc_sz;  /* allocated size (includes hidden fields) */
        unsigned int sum_size;  /* sum of all registered users' size */
index 3275bcb9bab6d914bae62b4bf89cf8a1f1b3a475..cafc51094321c1e9958bd63ca569fbeb87fa19bb 100644 (file)
@@ -318,13 +318,16 @@ struct pool_head *create_pool_with_loc(const char *name, unsigned int size, unsi
 }
 
 /* create a pool from a pool registration. All configuration is taken from
- * there.
+ * there. The alignment will automatically be raised to sizeof(void*) or the
+ * next power of two so that it's always possible to lazily pass alignof() or
+ * sizeof(). Alignments are always respected when merging pools.
  */
 struct pool_head *create_pool_from_reg(const char *name, struct pool_registration *reg)
 {
        unsigned int extra_mark, extra_caller, extra;
        unsigned int flags = reg->flags;
        unsigned int size = reg->size;
+       unsigned int alignment = reg->align;
        struct pool_head *pool = NULL;
        struct pool_head *entry;
        struct list *start;
@@ -332,6 +335,21 @@ struct pool_head *create_pool_from_reg(const char *name, struct pool_registratio
        unsigned int best_diff;
        int thr __maybe_unused;
 
+       /* extend alignment if needed */
+       if (alignment < sizeof(void*))
+               alignment = sizeof(void*);
+       else if (alignment & (alignment - 1)) {
+               /* not power of two! round up to next power of two by filling
+                * all LSB in O(log(log(N))) then increment the result.
+                */
+               int shift = 1;
+               do {
+                       alignment |= alignment >> shift;
+                       shift *= 2;
+               } while (alignment & (alignment + 1));
+               alignment++;
+       }
+
        extra_mark = (pool_debugging & POOL_DBG_TAG) ? POOL_EXTRA_MARK : 0;
        extra_caller = (pool_debugging & POOL_DBG_CALLER) ? POOL_EXTRA_CALLER : 0;
        extra = extra_mark + extra_caller;
@@ -427,6 +445,7 @@ struct pool_head *create_pool_from_reg(const char *name, struct pool_registratio
                        strlcpy2(pool->name, name, sizeof(pool->name));
                pool->alloc_sz = size + extra;
                pool->size = size;
+               pool->align = alignment;
                pool->flags = flags;
                LIST_APPEND(start, &pool->list);
                LIST_INIT(&pool->regs);
@@ -446,6 +465,8 @@ struct pool_head *create_pool_from_reg(const char *name, struct pool_registratio
                        pool->size = size;
                        pool->alloc_sz = size + extra;
                }
+               if (alignment > pool->align)
+                       pool->align = alignment;
                DPRINTF(stderr, "Sharing %s with %s\n", name, pool->name);
        }
 
@@ -1310,10 +1331,10 @@ void dump_pools_to_trash(int how, int max, const char *pfx)
        chunk_appendf(&trash, ". Use SIGQUIT to flush them.\n");
 
        for (i = 0; i < nbpools && i < max; i++) {
-               chunk_appendf(&trash, "  - Pool %s (%lu bytes) : %lu allocated (%lu bytes), %lu used"
+               chunk_appendf(&trash, "  - Pool %s (%u bytes/%u) : %lu allocated (%lu bytes), %lu used"
                              " (~%lu by thread caches)"
                              ", needed_avg %lu, %lu failures, %u users, @%p%s\n",
-                             pool_info[i].entry->name, (ulong)pool_info[i].entry->size,
+                             pool_info[i].entry->name, pool_info[i].entry->size, pool_info[i].entry->align,
                              pool_info[i].alloc_items, pool_info[i].alloc_bytes,
                              pool_info[i].used_items, pool_info[i].cached_items,
                              pool_info[i].need_avg, pool_info[i].failed_items,