From: Willy Tarreau Date: Mon, 11 Mar 2024 13:27:42 +0000 (+0100) Subject: MINOR: ring: add the definition of a ring waiting cell X-Git-Tag: v3.0-dev6~14 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e3f101a19aa4ea863078631f56309e428854b9ee;p=thirdparty%2Fhaproxy.git MINOR: ring: add the definition of a ring waiting cell This is what will be used to describe one waiting thread, its message in the queues, and the aggregation of pending messages after it. --- diff --git a/include/haproxy/ring-t.h b/include/haproxy/ring-t.h index 34384912e1..3d699b503c 100644 --- a/include/haproxy/ring-t.h +++ b/include/haproxy/ring-t.h @@ -106,6 +106,25 @@ /* 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 */ diff --git a/src/ring.c b/src/ring.c index 1c01122b71..d45bc245d2 100644 --- a/src/ring.c +++ b/src/ring.c @@ -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);