diff --git a/include/haproxy/ring-t.h b/include/haproxy/ring-t.h index 936712543..34384912e 100644 --- a/include/haproxy/ring-t.h +++ b/include/haproxy/ring-t.h @@ -123,7 +123,9 @@ struct ring { struct ring_storage *storage; // the mapped part struct mt_list waiters; // list of waiters, for now, CLI "show event" int readers_count; - uint flags; // RING_FL_* + 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 }; #endif /* _HAPROXY_RING_T_H */ diff --git a/src/ring.c b/src/ring.c index 31b75a13f..0916b3f8f 100644 --- a/src/ring.c +++ b/src/ring.c @@ -49,6 +49,8 @@ void ring_init(struct ring *ring, void *area, size_t size, int reset) ring->readers_count = 0; ring->flags = 0; ring->storage = area; + ring->pending = 0; + ring->waking = 0; if (reset) { ring->storage->size = size - sizeof(*ring->storage); @@ -338,11 +340,16 @@ ssize_t ring_write(struct ring *ring, size_t maxlen, const struct ist pfx[], siz /* notify potential readers */ if (sent && HA_ATOMIC_LOAD(&ring->readers_count)) { - struct mt_list *elt1, elt2; - struct appctx *appctx; + HA_ATOMIC_INC(&ring->pending); + while (HA_ATOMIC_LOAD(&ring->pending) && HA_ATOMIC_XCHG(&ring->waking, 1) == 0) { + struct mt_list *elt1, elt2; + struct appctx *appctx; - mt_list_for_each_entry_safe(appctx, &ring->waiters, wait_entry, elt1, elt2) - appctx_wakeup(appctx); + HA_ATOMIC_STORE(&ring->pending, 0); + mt_list_for_each_entry_safe(appctx, &ring->waiters, wait_entry, elt1, elt2) + appctx_wakeup(appctx); + HA_ATOMIC_STORE(&ring->waking, 0); + } } leave: