]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: buffers: relax the buffer lock a little bit
authorWilly Tarreau <w@1wt.eu>
Tue, 28 May 2019 15:21:18 +0000 (17:21 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 28 May 2019 15:25:21 +0000 (17:25 +0200)
In lock profiles it's visible that there is a huge contention on the
buffer lock. The reason is that when offer_buffers() is called, it
systematically takes the lock before verifying if there is any
waiter. However doing so doesn't protect against races since a
waiter can happen just after we release the lock as well. Similarly
in h2 we take the lock every time an h2c is going to be released,
even without checking that the h2c belongs to a wait list. These
two have now been addressed by verifying non-emptiness of the list
prior to taking the lock.

include/common/buffer.h
src/mux_h2.c

index 960402633f3c47f2f72dd1064fd3d0f8d519b078..3d6c97ca629283874dee37f81981af8420b40953 100644 (file)
@@ -201,12 +201,12 @@ void __offer_buffer(void *from, unsigned int threshold);
 
 static inline void offer_buffers(void *from, unsigned int threshold)
 {
-       HA_SPIN_LOCK(BUF_WQ_LOCK, &buffer_wq_lock);
-       if (LIST_ISEMPTY(&buffer_wq)) {
-               HA_SPIN_UNLOCK(BUF_WQ_LOCK, &buffer_wq_lock);
+       if (LIST_ISEMPTY(&buffer_wq))
                return;
-       }
-       __offer_buffer(from, threshold);
+
+       HA_SPIN_LOCK(BUF_WQ_LOCK, &buffer_wq_lock);
+       if (!LIST_ISEMPTY(&buffer_wq))
+               __offer_buffer(from, threshold);
        HA_SPIN_UNLOCK(BUF_WQ_LOCK, &buffer_wq_lock);
 }
 
index 7d29a7d1f66e2e8f75ef05267186b4179050ba57..8b8135d1a178ea18d971814a1389d3479e9fe5fd 100644 (file)
@@ -662,9 +662,11 @@ static void h2_release(struct h2c *h2c)
 
                hpack_dht_free(h2c->ddht);
 
-               HA_SPIN_LOCK(BUF_WQ_LOCK, &buffer_wq_lock);
-               LIST_DEL(&h2c->buf_wait.list);
-               HA_SPIN_UNLOCK(BUF_WQ_LOCK, &buffer_wq_lock);
+               if (LIST_ADDED(&h2c->buf_wait.list)) {
+                       HA_SPIN_LOCK(BUF_WQ_LOCK, &buffer_wq_lock);
+                       LIST_DEL(&h2c->buf_wait.list);
+                       HA_SPIN_UNLOCK(BUF_WQ_LOCK, &buffer_wq_lock);
+               }
 
                h2_release_buf(h2c, &h2c->dbuf);
                h2_release_mbuf(h2c);