*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.54 1999/06/10 14:17:09 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.55 1999/06/11 09:00:02 vadim Exp $
*
*-------------------------------------------------------------------------
*/
}
if (BufferLocks[i] & BL_RI_LOCK)
{
- Assert(buf->ri_lock);
+ /*
+ * Someone else could remove our RI lock when acquiring
+ * W lock. This is possible if we came here from elog(ERROR)
+ * from IpcSemaphore{Lock|Unlock}(WaitCLSemId). And so we
+ * don't do Assert(buf->ri_lock) here.
+ */
buf->ri_lock = false;
}
if (BufferLocks[i] & BL_W_LOCK)
{
Assert(buf->w_lock);
Assert(buf->r_locks == 0);
- Assert(!buf->ri_lock);
Assert(!(BufferLocks[buffer - 1] & (BL_R_LOCK | BL_RI_LOCK)))
buf->w_lock = false;
BufferLocks[buffer - 1] &= ~BL_W_LOCK;
Assert(!(BufferLocks[buffer - 1] & (BL_R_LOCK | BL_W_LOCK | BL_RI_LOCK)));
while (buf->r_locks > 0 || buf->w_lock)
{
- if (buf->r_locks > 3)
+ if (buf->r_locks > 3 || (BufferLocks[buffer - 1] & BL_RI_LOCK))
{
- if (!(BufferLocks[buffer - 1] & BL_RI_LOCK))
- BufferLocks[buffer - 1] |= BL_RI_LOCK;
+ /*
+ * Our RI lock might be removed by concurrent W lock
+ * acquiring (see what we do with RI locks below
+ * when our own W acquiring succeeded) and so
+ * we set RI lock again if we already did this.
+ */
+ BufferLocks[buffer - 1] |= BL_RI_LOCK;
buf->ri_lock = true;
}
#ifdef HAS_TEST_AND_SET
BufferLocks[buffer - 1] |= BL_W_LOCK;
if (BufferLocks[buffer - 1] & BL_RI_LOCK)
{
+ /*
+ * It's possible to remove RI locks acquired by another
+ * W lockers here, but they'll take care about it.
+ */
buf->ri_lock = false;
BufferLocks[buffer - 1] &= ~BL_RI_LOCK;
}