Skip to content

Commit 5310fac

Browse files
committed
bufmgr: Use atomic sub for unpinning buffers
The prior commit made it legal to modify BufferDesc.state while the buffer header spinlock is held. This allows us to replace the CAS loop inUnpinBufferNoOwner() with an atomic sub. This improves scalability significantly. See the prior commits for more background. Reviewed-by: Matthias van de Meent <[email protected]> Discussion: https://postgr.es/m/fvfmkr5kk4nyex56ejgxj3uzi63isfxovp2biecb4bspbjrze7@az2pljabhnff
1 parent c75ebc6 commit 5310fac

File tree

1 file changed

+3
-26
lines changed

1 file changed

+3
-26
lines changed

src/backend/storage/buffer/bufmgr.c

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3267,7 +3267,6 @@ UnpinBufferNoOwner(BufferDesc *buf)
32673267
ref->refcount--;
32683268
if (ref->refcount == 0)
32693269
{
3270-
uint32 buf_state;
32713270
uint32 old_buf_state;
32723271

32733272
/*
@@ -3285,33 +3284,11 @@ UnpinBufferNoOwner(BufferDesc *buf)
32853284
*/
32863285
Assert(!LWLockHeldByMe(BufferDescriptorGetContentLock(buf)));
32873286

3288-
/*
3289-
* Decrement the shared reference count.
3290-
*
3291-
* Since buffer spinlock holder can update status using just write,
3292-
* it's not safe to use atomic decrement here; thus use a CAS loop.
3293-
*
3294-
* TODO: The above requirement does not hold anymore, in a future
3295-
* commit this will be rewritten to release the pin in a single atomic
3296-
* operation.
3297-
*/
3298-
old_buf_state = pg_atomic_read_u32(&buf->state);
3299-
for (;;)
3300-
{
3301-
if (old_buf_state & BM_LOCKED)
3302-
old_buf_state = WaitBufHdrUnlocked(buf);
3303-
3304-
buf_state = old_buf_state;
3305-
3306-
buf_state -= BUF_REFCOUNT_ONE;
3307-
3308-
if (pg_atomic_compare_exchange_u32(&buf->state, &old_buf_state,
3309-
buf_state))
3310-
break;
3311-
}
3287+
/* decrement the shared reference count */
3288+
old_buf_state = pg_atomic_fetch_sub_u32(&buf->state, BUF_REFCOUNT_ONE);
33123289

33133290
/* Support LockBufferForCleanup() */
3314-
if (buf_state & BM_PIN_COUNT_WAITER)
3291+
if (old_buf_state & BM_PIN_COUNT_WAITER)
33153292
WakePinCountWaiter(buf);
33163293

33173294
ForgetPrivateRefCountEntry(ref);

0 commit comments

Comments
 (0)