]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: ring: support creating a ring from a linear area
authorWilly Tarreau <w@1wt.eu>
Fri, 12 Aug 2022 05:50:43 +0000 (07:50 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 12 Aug 2022 09:18:46 +0000 (11:18 +0200)
Instead of allocating two parts, one for the ring struct itself and
one for the storage area, ring_make_from_area() will arrange the two
inside the same memory area, with the storage starting immediately
after the struct. This will allow to store a complete ring state in
shared memory areas for example.

include/haproxy/ring.h
src/ring.c

index 9e87407c68e7e61aa83d4038f27ee197718eea7c..bab18c679177d21373b166be548b139b35f48b37 100644 (file)
@@ -29,6 +29,7 @@
 struct appctx;
 
 struct ring *ring_new(size_t size);
+struct ring *ring_make_from_area(void *area, size_t size);
 void ring_init(struct ring *ring, void* area, size_t size);
 struct ring *ring_resize(struct ring *ring, size_t size);
 void ring_free(struct ring *ring);
index c45de29eb1a1dc689e993ce0128ccaa46c8ca7ee..089a2fc9f053b4b5f5d1630bc12c24d8e25c30a6 100644 (file)
@@ -75,6 +75,30 @@ struct ring *ring_new(size_t size)
        return NULL;
 }
 
+/* Creates a unified ring + storage area at address <area> for <size> bytes.
+ * If <area> is null, then it's allocated of the requested size. The ring
+ * struct is part of the area so the usable area is slightly reduced. However
+ * the ring storage is immediately adjacent to the struct. ring_free() will
+ * ignore such rings, so the caller is responsible for releasing them.
+ */
+struct ring *ring_make_from_area(void *area, size_t size)
+{
+       struct ring *ring = NULL;
+
+       if (size < sizeof(ring))
+               return NULL;
+
+       if (!area)
+               area = malloc(size);
+       if (!area)
+               return NULL;
+
+       ring = area;
+       area += sizeof(*ring);
+       ring_init(ring, area, size - sizeof(*ring));
+       return ring;
+}
+
 /* Resizes existing ring <ring> to <size> which must be larger, without losing
  * its contents. The new size must be at least as large as the previous one or
  * no change will be performed. The pointer to the ring is returned on success,
@@ -113,6 +137,11 @@ void ring_free(struct ring *ring)
 {
        if (!ring)
                return;
+
+       /* make sure it was not allocated by ring_make_from_area */
+       if (ring->buf.area == (void *)ring + sizeof(*ring))
+               return;
+
        free(ring->buf.area);
        free(ring);
 }