aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/buffer/buf_init.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-03-04 20:21:07 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-03-04 20:21:07 +0000
commit5d5087363d7cdbd00fc432a1216e83a00f7139bd (patch)
tree56492be3beb9be188f37bfa68c9bfc0e35b0961c /src/backend/storage/buffer/buf_init.c
parent5592a6cf46d60187b6f4895d2144e67d4f54fa25 (diff)
downloadpostgresql-5d5087363d7cdbd00fc432a1216e83a00f7139bd.tar.gz
postgresql-5d5087363d7cdbd00fc432a1216e83a00f7139bd.zip
Replace the BufMgrLock with separate locks on the lookup hashtable and
the freelist, plus per-buffer spinlocks that protect access to individual shared buffer headers. This requires abandoning a global freelist (since the freelist is a global contention point), which shoots down ARC and 2Q as well as plain LRU management. Adopt a clock sweep algorithm instead. Preliminary results show substantial improvement in multi-backend situations.
Diffstat (limited to 'src/backend/storage/buffer/buf_init.c')
-rw-r--r--src/backend/storage/buffer/buf_init.c74
1 files changed, 33 insertions, 41 deletions
diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c
index f6500fec89e..1b8f0420791 100644
--- a/src/backend/storage/buffer/buf_init.c
+++ b/src/backend/storage/buffer/buf_init.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/buffer/buf_init.c,v 1.71 2005/02/03 23:29:11 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/buffer/buf_init.c,v 1.72 2005/03/04 20:21:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -22,6 +22,8 @@ BufferDesc *BufferDescriptors;
Block *BufferBlockPointers;
int32 *PrivateRefCount;
+static char *BufferBlocks;
+
/* statistics counters */
long int ReadBufferCount;
long int ReadLocalBufferCount;
@@ -50,16 +52,11 @@ long int LocalBufferFlushCount;
*
* Synchronization/Locking:
*
- * BufMgrLock lock -- must be acquired before manipulating the
- * buffer search datastructures (lookup/freelist, as well as the
- * flag bits of any buffer). Must be released
- * before exit and before doing any IO.
- *
* IO_IN_PROGRESS -- this is a flag in the buffer descriptor.
* It must be set when an IO is initiated and cleared at
* the end of the IO. It is there to make sure that one
* process doesn't start to use a buffer while another is
- * faulting it in. see IOWait/IOSignal.
+ * faulting it in. see WaitIO and related routines.
*
* refcount -- Counts the number of processes holding pins on a buffer.
* A buffer is pinned during IO and immediately after a BufferAlloc().
@@ -85,10 +82,8 @@ long int LocalBufferFlushCount;
void
InitBufferPool(void)
{
- char *BufferBlocks;
bool foundBufs,
foundDescs;
- int i;
BufferDescriptors = (BufferDesc *)
ShmemInitStruct("Buffer Descriptors",
@@ -102,52 +97,42 @@ InitBufferPool(void)
{
/* both should be present or neither */
Assert(foundDescs && foundBufs);
+ /* note: this path is only taken in EXEC_BACKEND case */
}
else
{
BufferDesc *buf;
- char *block;
-
- /*
- * It's probably not really necessary to grab the lock --- if
- * there's anyone else attached to the shmem at this point, we've
- * got problems.
- */
- LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
+ int i;
buf = BufferDescriptors;
- block = BufferBlocks;
/*
* Initialize all the buffer headers.
*/
- for (i = 0; i < NBuffers; block += BLCKSZ, buf++, i++)
+ for (i = 0; i < NBuffers; buf++, i++)
{
- Assert(ShmemIsValid((unsigned long) block));
+ CLEAR_BUFFERTAG(buf->tag);
+ buf->flags = 0;
+ buf->usage_count = 0;
+ buf->refcount = 0;
+ buf->wait_backend_id = 0;
- /*
- * The bufNext fields link together all totally-unused buffers.
- * Subsequent management of this list is done by
- * StrategyGetBuffer().
- */
- buf->bufNext = i + 1;
+ SpinLockInit(&buf->buf_hdr_lock);
- CLEAR_BUFFERTAG(buf->tag);
buf->buf_id = i;
- buf->data = MAKE_OFFSET(block);
- buf->flags = 0;
- buf->refcount = 0;
+ /*
+ * Initially link all the buffers together as unused.
+ * Subsequent management of this list is done by freelist.c.
+ */
+ buf->freeNext = i + 1;
+
buf->io_in_progress_lock = LWLockAssign();
- buf->cntx_lock = LWLockAssign();
- buf->cntxDirty = false;
- buf->wait_backend_id = 0;
+ buf->content_lock = LWLockAssign();
}
/* Correct last entry of linked list */
- BufferDescriptors[NBuffers - 1].bufNext = -1;
-
- LWLockRelease(BufMgrLock);
+ BufferDescriptors[NBuffers - 1].freeNext = FREENEXT_END_OF_LIST;
}
/* Init other shared buffer-management stuff */
@@ -162,12 +147,13 @@ InitBufferPool(void)
* buffer pool.
*
* NB: this is called before InitProcess(), so we do not have a PGPROC and
- * cannot do LWLockAcquire; hence we can't actually access the bufmgr's
+ * cannot do LWLockAcquire; hence we can't actually access stuff in
* shared memory yet. We are only initializing local data here.
*/
void
InitBufferPoolAccess(void)
{
+ char *block;
int i;
/*
@@ -179,12 +165,18 @@ InitBufferPoolAccess(void)
sizeof(*PrivateRefCount));
/*
- * Convert shmem offsets into addresses as seen by this process. This
- * is just to speed up the BufferGetBlock() macro. It is OK to do this
- * without any lock since the data pointers never change.
+ * Construct addresses for the individual buffer data blocks. We do
+ * this just to speed up the BufferGetBlock() macro. (Since the
+ * addresses should be the same in every backend, we could inherit
+ * this data from the postmaster --- but in the EXEC_BACKEND case
+ * that doesn't work.)
*/
+ block = BufferBlocks;
for (i = 0; i < NBuffers; i++)
- BufferBlockPointers[i] = (Block) MAKE_PTR(BufferDescriptors[i].data);
+ {
+ BufferBlockPointers[i] = (Block) block;
+ block += BLCKSZ;
+ }
}
/*