tranche-ify buffer locks
authorRobert Haas <rhaas@postgresql.org>
Sun, 15 Nov 2015 15:37:19 +0000 (10:37 -0500)
committerRobert Haas <rhaas@postgresql.org>
Sun, 15 Nov 2015 15:37:19 +0000 (10:37 -0500)
src/backend/storage/buffer/buf_init.c
src/backend/storage/buffer/bufmgr.c
src/backend/storage/lmgr/lwlock.c
src/include/storage/buf_internals.h
src/include/storage/lwlock.h

index 3ae2848da05964bd8c7e21a86661d9a6b3e34fd1..422e8a9e31dcd68706eb49878503fab979a0e4dc 100644 (file)
@@ -20,6 +20,8 @@
 
 BufferDescPadded *BufferDescriptors;
 char      *BufferBlocks;
+static LWLockTranche BufferContentLWLockTranche;
+static LWLockTranche BufferIOLWLockTranche;
 
 
 /*
@@ -59,7 +61,8 @@ char     *BufferBlocks;
  * Initialize shared buffer pool
  *
  * This is called once during shared-memory initialization (either in the
- * postmaster, or in a standalone backend).
+ * postmaster, or in a standalone backend).  It is also called by a backend
+ * forked from the postmaster in the EXEC_BACKEND case.
  */
 void
 InitBufferPool(void)
@@ -110,14 +113,27 @@ InitBufferPool(void)
                         */
                        buf->freeNext = i + 1;
 
-                       buf->io_in_progress_lock = LWLockAssign();
-                       buf->content_lock = LWLockAssign();
+                       LWLockInitialize(&buf->io_in_progress_lock,
+                                                        LWTRANCHE_BUFFER_IO_IN_PROGRESS);
+                       LWLockInitialize(&buf->content_lock, LWTRANCHE_BUFFER_CONTENT);
                }
 
                /* Correct last entry of linked list */
                GetBufferDescriptor(NBuffers - 1)->freeNext = FREENEXT_END_OF_LIST;
        }
 
+       /* Register LWLock tranches. */
+       BufferContentLWLockTranche.name = "buffer_content";
+       BufferContentLWLockTranche.array_base = BufferDescriptors;
+       BufferContentLWLockTranche.array_stride = sizeof(BufferDesc);
+       LWLockRegisterTranche(LWTRANCHE_BUFFER_CONTENT,
+                                                 &BufferContentLWLockTranche);
+       BufferIOLWLockTranche.name = "buffer_io";
+       BufferIOLWLockTranche.array_base = BufferDescriptors;
+       BufferIOLWLockTranche.array_stride = sizeof(BufferDesc);
+       LWLockRegisterTranche(LWTRANCHE_BUFFER_IO_IN_PROGRESS,
+                                                 &BufferContentLWLockTranche);
+
        /* Init other shared buffer-management stuff */
        StrategyInitialize(!foundDescs);
 }
index 63188a3932ecc4e364c3dc7471b508c5b15cb8c3..eb61f6382f2c9ee04fcebb1751b3829640229a5d 100644 (file)
@@ -738,7 +738,7 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
                        if (!isLocalBuf)
                        {
                                if (mode == RBM_ZERO_AND_LOCK)
-                                       LWLockAcquire(bufHdr->content_lock, LW_EXCLUSIVE);
+                                       LWLockAcquire(&bufHdr->content_lock, LW_EXCLUSIVE);
                                else if (mode == RBM_ZERO_AND_CLEANUP_LOCK)
                                        LockBufferForCleanup(BufferDescriptorGetBuffer(bufHdr));
                        }
@@ -879,7 +879,7 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
        if ((mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK) &&
                !isLocalBuf)
        {
-               LWLockAcquire(bufHdr->content_lock, LW_EXCLUSIVE);
+               LWLockAcquire(&bufHdr->content_lock, LW_EXCLUSIVE);
        }
 
        if (isLocalBuf)
@@ -1045,7 +1045,7 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
                         * happens to be trying to split the page the first one got from
                         * StrategyGetBuffer.)
                         */
-                       if (LWLockConditionalAcquire(buf->content_lock, LW_SHARED))
+                       if (LWLockConditionalAcquire(&buf->content_lock, LW_SHARED))
                        {
                                /*
                                 * If using a nondefault strategy, and writing the buffer
@@ -1067,7 +1067,7 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
                                                StrategyRejectBuffer(strategy, buf))
                                        {
                                                /* Drop lock/pin and loop around for another buffer */
-                                               LWLockRelease(buf->content_lock);
+                                               LWLockRelease(&buf->content_lock);
                                                UnpinBuffer(buf, true);
                                                continue;
                                        }
@@ -1080,7 +1080,7 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
                                                                                          smgr->smgr_rnode.node.relNode);
 
                                FlushBuffer(buf, NULL);
-                               LWLockRelease(buf->content_lock);
+                               LWLockRelease(&buf->content_lock);
 
                                TRACE_POSTGRESQL_BUFFER_WRITE_DIRTY_DONE(forkNum, blockNum,
                                                                                           smgr->smgr_rnode.node.spcNode,
@@ -1395,7 +1395,7 @@ MarkBufferDirty(Buffer buffer)
 
        Assert(BufferIsPinned(buffer));
        /* unfortunately we can't check if the lock is held exclusively */
-       Assert(LWLockHeldByMe(bufHdr->content_lock));
+       Assert(LWLockHeldByMe(&bufHdr->content_lock));
 
        LockBufHdr(bufHdr);
 
@@ -1595,8 +1595,8 @@ UnpinBuffer(BufferDesc *buf, bool fixOwner)
        if (ref->refcount == 0)
        {
                /* I'd better not still hold any locks on the buffer */
-               Assert(!LWLockHeldByMe(buf->content_lock));
-               Assert(!LWLockHeldByMe(buf->io_in_progress_lock));
+               Assert(!LWLockHeldByMe(&buf->content_lock));
+               Assert(!LWLockHeldByMe(&buf->io_in_progress_lock));
 
                LockBufHdr(buf);
 
@@ -2116,11 +2116,11 @@ SyncOneBuffer(int buf_id, bool skip_recently_used)
         * buffer is clean by the time we've locked it.)
         */
        PinBuffer_Locked(bufHdr);
-       LWLockAcquire(bufHdr->content_lock, LW_SHARED);
+       LWLockAcquire(&bufHdr->content_lock, LW_SHARED);
 
        FlushBuffer(bufHdr, NULL);
 
-       LWLockRelease(bufHdr->content_lock);
+       LWLockRelease(&bufHdr->content_lock);
        UnpinBuffer(bufHdr, true);
 
        return result | BUF_WRITTEN;
@@ -2926,9 +2926,9 @@ FlushRelationBuffers(Relation rel)
                        (bufHdr->flags & BM_VALID) && (bufHdr->flags & BM_DIRTY))
                {
                        PinBuffer_Locked(bufHdr);
-                       LWLockAcquire(bufHdr->content_lock, LW_SHARED);
+                       LWLockAcquire(&bufHdr->content_lock, LW_SHARED);
                        FlushBuffer(bufHdr, rel->rd_smgr);
-                       LWLockRelease(bufHdr->content_lock);
+                       LWLockRelease(&bufHdr->content_lock);
                        UnpinBuffer(bufHdr, true);
                }
                else
@@ -2978,9 +2978,9 @@ FlushDatabaseBuffers(Oid dbid)
                        (bufHdr->flags & BM_VALID) && (bufHdr->flags & BM_DIRTY))
                {
                        PinBuffer_Locked(bufHdr);
-                       LWLockAcquire(bufHdr->content_lock, LW_SHARED);
+                       LWLockAcquire(&bufHdr->content_lock, LW_SHARED);
                        FlushBuffer(bufHdr, NULL);
-                       LWLockRelease(bufHdr->content_lock);
+                       LWLockRelease(&bufHdr->content_lock);
                        UnpinBuffer(bufHdr, true);
                }
                else
@@ -3080,7 +3080,7 @@ MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
 
        Assert(GetPrivateRefCount(buffer) > 0);
        /* here, either share or exclusive lock is OK */
-       Assert(LWLockHeldByMe(bufHdr->content_lock));
+       Assert(LWLockHeldByMe(&bufHdr->content_lock));
 
        /*
         * This routine might get called many times on the same page, if we are
@@ -3233,11 +3233,11 @@ LockBuffer(Buffer buffer, int mode)
        buf = GetBufferDescriptor(buffer - 1);
 
        if (mode == BUFFER_LOCK_UNLOCK)
-               LWLockRelease(buf->content_lock);
+               LWLockRelease(&buf->content_lock);
        else if (mode == BUFFER_LOCK_SHARE)
-               LWLockAcquire(buf->content_lock, LW_SHARED);
+               LWLockAcquire(&buf->content_lock, LW_SHARED);
        else if (mode == BUFFER_LOCK_EXCLUSIVE)
-               LWLockAcquire(buf->content_lock, LW_EXCLUSIVE);
+               LWLockAcquire(&buf->content_lock, LW_EXCLUSIVE);
        else
                elog(ERROR, "unrecognized buffer lock mode: %d", mode);
 }
@@ -3258,7 +3258,7 @@ ConditionalLockBuffer(Buffer buffer)
 
        buf = GetBufferDescriptor(buffer - 1);
 
-       return LWLockConditionalAcquire(buf->content_lock, LW_EXCLUSIVE);
+       return LWLockConditionalAcquire(&buf->content_lock, LW_EXCLUSIVE);
 }
 
 /*
@@ -3468,8 +3468,8 @@ WaitIO(BufferDesc *buf)
                UnlockBufHdr(buf);
                if (!(sv_flags & BM_IO_IN_PROGRESS))
                        break;
-               LWLockAcquire(buf->io_in_progress_lock, LW_SHARED);
-               LWLockRelease(buf->io_in_progress_lock);
+               LWLockAcquire(&buf->io_in_progress_lock, LW_SHARED);
+               LWLockRelease(&buf->io_in_progress_lock);
        }
 }
 
@@ -3502,7 +3502,7 @@ StartBufferIO(BufferDesc *buf, bool forInput)
                 * Grab the io_in_progress lock so that other processes can wait for
                 * me to finish the I/O.
                 */
-               LWLockAcquire(buf->io_in_progress_lock, LW_EXCLUSIVE);
+               LWLockAcquire(&buf->io_in_progress_lock, LW_EXCLUSIVE);
 
                LockBufHdr(buf);
 
@@ -3516,7 +3516,7 @@ StartBufferIO(BufferDesc *buf, bool forInput)
                 * him to get unwedged.
                 */
                UnlockBufHdr(buf);
-               LWLockRelease(buf->io_in_progress_lock);
+               LWLockRelease(&buf->io_in_progress_lock);
                WaitIO(buf);
        }
 
@@ -3526,7 +3526,7 @@ StartBufferIO(BufferDesc *buf, bool forInput)
        {
                /* someone else already did the I/O */
                UnlockBufHdr(buf);
-               LWLockRelease(buf->io_in_progress_lock);
+               LWLockRelease(&buf->io_in_progress_lock);
                return false;
        }
 
@@ -3574,7 +3574,7 @@ TerminateBufferIO(BufferDesc *buf, bool clear_dirty, int set_flag_bits)
 
        InProgressBuf = NULL;
 
-       LWLockRelease(buf->io_in_progress_lock);
+       LWLockRelease(&buf->io_in_progress_lock);
 }
 
 /*
@@ -3599,7 +3599,7 @@ AbortBufferIO(void)
                 * we can use TerminateBufferIO. Anyone who's executing WaitIO on the
                 * buffer will be in a busy spin until we succeed in doing this.
                 */
-               LWLockAcquire(buf->io_in_progress_lock, LW_EXCLUSIVE);
+               LWLockAcquire(&buf->io_in_progress_lock, LW_EXCLUSIVE);
 
                LockBufHdr(buf);
                Assert(buf->flags & BM_IO_IN_PROGRESS);
index 6bca02c5f213be3f4f3f7156a3bf8d8d43af4b83..43534d63c3396d5e74b59be6d0e3a169b0ab86db 100644 (file)
@@ -445,7 +445,7 @@ CreateLWLocks(void)
 
                /* Initialize all LWLocks in main array */
                for (id = 0, lock = MainLWLockArray; id < numLocks; id++, lock++)
-                       LWLockInitialize(&lock->lock, 0);
+                       LWLockInitialize(&lock->lock, LWTRANCHE_MAIN);
 
                /*
                 * Initialize the dynamic-allocation counters, which are stored just
@@ -457,7 +457,7 @@ CreateLWLocks(void)
                LWLockCounter = (int *) ((char *) MainLWLockArray - 3 * sizeof(int));
                LWLockCounter[0] = NUM_FIXED_LWLOCKS;
                LWLockCounter[1] = numLocks;
-               LWLockCounter[2] = 1;   /* 0 is the main array */
+               LWLockCounter[2] = LWTRANCHE_LAST_BUILTIN_ID + 1;
        }
 
        if (LWLockTrancheArray == NULL)
@@ -466,12 +466,13 @@ CreateLWLocks(void)
                LWLockTrancheArray = (LWLockTranche **)
                        MemoryContextAlloc(TopMemoryContext,
                                                  LWLockTranchesAllocated * sizeof(LWLockTranche *));
+               Assert(LWLockTranchesAllocated > LWTRANCHE_LAST_BUILTIN_ID);
        }
 
        MainLWLockTranche.name = "main";
        MainLWLockTranche.array_base = MainLWLockArray;
        MainLWLockTranche.array_stride = sizeof(LWLockPadded);
-       LWLockRegisterTranche(0, &MainLWLockTranche);
+       LWLockRegisterTranche(LWTRANCHE_MAIN, &MainLWLockTranche);
 }
 
 /*
index 19247c4b2be1741e48b9b082e989cc0d51aea339..c64ce97579f3f51612c2bce3f9bd04b355a19825 100644 (file)
@@ -147,8 +147,8 @@ typedef struct BufferDesc
        int                     buf_id;                 /* buffer's index number (from 0) */
        int                     freeNext;               /* link in freelist chain */
 
-       LWLock     *io_in_progress_lock;        /* to wait for I/O to complete */
-       LWLock     *content_lock;       /* to lock access to buffer contents */
+       LWLock          io_in_progress_lock;    /* to wait for I/O to complete */
+       LWLock          content_lock;   /* to lock access to buffer contents */
 } BufferDesc;
 
 /*
index 4653e099b0dba11519bbad59622e4a32b0ce5ff2..a5fbd20e9740612f1685acc872d2d8f6f8c980b6 100644 (file)
@@ -176,6 +176,15 @@ extern int LWLockNewTrancheId(void);
 extern void LWLockRegisterTranche(int tranche_id, LWLockTranche *tranche);
 extern void LWLockInitialize(LWLock *lock, int tranche_id);
 
+/*
+ * We reserve a few predefined tranche IDs.  These values will never be
+ * returned by LWLockNewTrancheId.
+ */
+#define LWTRANCHE_MAIN                                         0
+#define LWTRANCHE_BUFFER_CONTENT                       1
+#define LWTRANCHE_BUFFER_IO_IN_PROGRESS                2
+#define LWTRANCHE_LAST_BUILTIN_ID                      LWTRANCHE_BUFFER_IO_IN_PROGRESS
+
 /*
  * Prior to PostgreSQL 9.4, we used an enum type called LWLockId to refer
  * to LWLocks.  New code should instead use LWLock *.  However, for the