]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: pools: do not maintain the lock during pool_flush()
authorWilly Tarreau <w@1wt.eu>
Thu, 10 Jun 2021 05:13:04 +0000 (07:13 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 10 Jun 2021 15:46:50 +0000 (17:46 +0200)
The locked version of pool_flush() is absurd, it locks the pool for each
and every element to be released till the end. Not only this is extremely
inefficient, but it may even never finish if other threads spend their
time refilling the pool. The only case where this can happen is during
soft-stop so the risk remains limited, but it should be addressed.

src/pool.c

index d788c6168ac19124d886951f9a3c58b741483bcb..c69143a089499df5c7ba9d239e2e8cf7e9a45133 100644 (file)
@@ -360,20 +360,19 @@ void pool_gc(struct pool_head *pool_ctx)
  */
 void pool_flush(struct pool_head *pool)
 {
-       void *temp;
+       void *temp, **next;
 
        if (!pool)
                return;
 
-       while (1) {
-               HA_SPIN_LOCK(POOL_LOCK, &pool->lock);
-               temp = pool->free_list;
-               if (!temp) {
-                       HA_SPIN_UNLOCK(POOL_LOCK, &pool->lock);
-                       break;
-               }
-               pool->free_list = *POOL_LINK(pool, temp);
-               HA_SPIN_UNLOCK(POOL_LOCK, &pool->lock);
+       HA_SPIN_LOCK(POOL_LOCK, &pool->lock);
+       next = pool->free_list;
+       pool->free_list = NULL;
+       HA_SPIN_UNLOCK(POOL_LOCK, &pool->lock);
+
+       while (next) {
+               temp = next;
+               next = *POOL_LINK(pool, temp);
                pool_put_to_os(pool, temp);
        }
        /* here, we should have pool->allocated == pool->used */