mirror of
https://github.com/postgres/postgres.git
synced 2026-07-07 16:50:58 -04:00
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 <boekewurm+postgres@gmail.com> Discussion: https://postgr.es/m/fvfmkr5kk4nyex56ejgxj3uzi63isfxovp2biecb4bspbjrze7@az2pljabhnff
This commit is contained in:
parent
c75ebc657f
commit
5310fac6e0
1 changed files with 3 additions and 26 deletions
|
|
@ -3267,7 +3267,6 @@ UnpinBufferNoOwner(BufferDesc *buf)
|
|||
ref->refcount--;
|
||||
if (ref->refcount == 0)
|
||||
{
|
||||
uint32 buf_state;
|
||||
uint32 old_buf_state;
|
||||
|
||||
/*
|
||||
|
|
@ -3285,33 +3284,11 @@ UnpinBufferNoOwner(BufferDesc *buf)
|
|||
*/
|
||||
Assert(!LWLockHeldByMe(BufferDescriptorGetContentLock(buf)));
|
||||
|
||||
/*
|
||||
* Decrement the shared reference count.
|
||||
*
|
||||
* Since buffer spinlock holder can update status using just write,
|
||||
* it's not safe to use atomic decrement here; thus use a CAS loop.
|
||||
*
|
||||
* TODO: The above requirement does not hold anymore, in a future
|
||||
* commit this will be rewritten to release the pin in a single atomic
|
||||
* operation.
|
||||
*/
|
||||
old_buf_state = pg_atomic_read_u32(&buf->state);
|
||||
for (;;)
|
||||
{
|
||||
if (old_buf_state & BM_LOCKED)
|
||||
old_buf_state = WaitBufHdrUnlocked(buf);
|
||||
|
||||
buf_state = old_buf_state;
|
||||
|
||||
buf_state -= BUF_REFCOUNT_ONE;
|
||||
|
||||
if (pg_atomic_compare_exchange_u32(&buf->state, &old_buf_state,
|
||||
buf_state))
|
||||
break;
|
||||
}
|
||||
/* decrement the shared reference count */
|
||||
old_buf_state = pg_atomic_fetch_sub_u32(&buf->state, BUF_REFCOUNT_ONE);
|
||||
|
||||
/* Support LockBufferForCleanup() */
|
||||
if (buf_state & BM_PIN_COUNT_WAITER)
|
||||
if (old_buf_state & BM_PIN_COUNT_WAITER)
|
||||
WakePinCountWaiter(buf);
|
||||
|
||||
ForgetPrivateRefCountEntry(ref);
|
||||
|
|
|
|||
Loading…
Reference in a new issue