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 d788c61..c69143a 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 */