]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: ring: add the definition of a ring waiting cell
authorWilly Tarreau <w@1wt.eu>
Mon, 11 Mar 2024 13:27:42 +0000 (14:27 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 25 Mar 2024 17:34:19 +0000 (17:34 +0000)
This is what will be used to describe one waiting thread, its message
in the queues, and the aggregation of pending messages after it.

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

index 34384912e1537d60ea8d6f86b5e61f5c8a3fef16..3d699b503c486005afb0f60b0b943543060d88a1 100644 (file)
 /* mask used to lock the tail */
 #define RING_TAIL_LOCK     (1ULL << ((sizeof(size_t) * 8) - 1))
 
+/* A cell describing a waiting thread.
+ * ->next is initialized to 0x1 before the pointer is set, so that any
+ * leader thread can see that the pointer is not set yet. This allows
+ * to enqueue all waiting threads very quickly using XCHG() on the head
+ * without having to rely on a flaky CAS, while threads finish their setup
+ * in parallel. The pointer will turn to NULL again once the thread is
+ * released.
+ */
+struct ring_wait_cell {
+       size_t to_send_self;         // size needed to serialize this msg
+       size_t needed_tot;           // size needed to serialize pending msgs
+       size_t maxlen;               // msg truncated to this size
+       const struct ist *pfx;       // prefixes
+       size_t npfx;                 // #prefixes
+       const struct ist *msg;       // message parts
+       size_t nmsg;                 // #message parts
+       struct ring_wait_cell *next; // next waiting thread
+};
+
 /* this is the mmapped part */
 struct ring_storage {
        size_t size;         // storage size
@@ -126,6 +145,13 @@ struct ring {
        uint flags;             // RING_FL_*
        uint pending;           // new writes that have not yet been subject to a wakeup
        uint waking;            // indicates a thread is currently waking up readers
+
+       /* keep the queue in a separate cache line below */
+       THREAD_PAD(64 - 3*sizeof(void*) - 4*sizeof(int));
+       struct ring_wait_cell *queue; // wait queue
+
+       /* and leave a spacer after it to avoid false sharing */
+       THREAD_PAD(64 - sizeof(void*));
 };
 
 #endif /* _HAPROXY_RING_T_H */
index 1c01122b710a0a8927bfa4f7d02c39a38b3db992..d45bc245d288f1519d8b9d68a2d71460f61dcfc5 100644 (file)
@@ -51,6 +51,7 @@ void ring_init(struct ring *ring, void *area, size_t size, int reset)
        ring->storage = area;
        ring->pending = 0;
        ring->waking = 0;
+       ring->queue = NULL;
 
        if (reset) {
                ring->storage->size = size - sizeof(*ring->storage);