diff options
Diffstat (limited to 'src/backend/storage/buffer/freelist.c')
-rw-r--r-- | src/backend/storage/buffer/freelist.c | 373 |
1 files changed, 198 insertions, 175 deletions
diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index f4e7bcdc57a..94a8e84b8c6 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -1,14 +1,14 @@ /*------------------------------------------------------------------------- * * freelist.c-- - * routines for manipulating the buffer pool's replacement strategy - * freelist. + * routines for manipulating the buffer pool's replacement strategy + * freelist. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/buffer/freelist.c,v 1.4 1997/08/19 21:32:44 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/buffer/freelist.c,v 1.5 1997/09/07 04:48:22 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -16,23 +16,23 @@ * OLD COMMENTS * * Data Structures: - * SharedFreeList is a circular queue. Notice that this - * is a shared memory queue so the next/prev "ptrs" are - * buffer ids, not addresses. + * SharedFreeList is a circular queue. Notice that this + * is a shared memory queue so the next/prev "ptrs" are + * buffer ids, not addresses. * * Sync: all routines in this file assume that the buffer - * semaphore has been acquired by the caller. + * semaphore has been acquired by the caller. */ #include <stdio.h> #include "postgres.h" #include "storage/bufmgr.h" -#include "storage/buf_internals.h" /* where declarations go */ +#include "storage/buf_internals.h" /* where declarations go */ #include "storage/spin.h" -static BufferDesc *SharedFreeList; +static BufferDesc *SharedFreeList; /* only actually used in debugging. The lock * should be acquired before calling the freelist manager. @@ -40,40 +40,40 @@ static BufferDesc *SharedFreeList; extern SPINLOCK BufMgrLock; #define IsInQueue(bf) \ - Assert((bf->freeNext != INVALID_DESCRIPTOR));\ - Assert((bf->freePrev != INVALID_DESCRIPTOR));\ - Assert((bf->flags & BM_FREE)) + Assert((bf->freeNext != INVALID_DESCRIPTOR));\ + Assert((bf->freePrev != INVALID_DESCRIPTOR));\ + Assert((bf->flags & BM_FREE)) #define NotInQueue(bf) \ - Assert((bf->freeNext == INVALID_DESCRIPTOR));\ - Assert((bf->freePrev == INVALID_DESCRIPTOR));\ - Assert(! (bf->flags & BM_FREE)) + Assert((bf->freeNext == INVALID_DESCRIPTOR));\ + Assert((bf->freePrev == INVALID_DESCRIPTOR));\ + Assert(! (bf->flags & BM_FREE)) /* - * AddBufferToFreelist -- + * AddBufferToFreelist -- * * In theory, this is the only routine that needs to be changed - * if the buffer replacement strategy changes. Just change + * if the buffer replacement strategy changes. Just change * the manner in which buffers are added to the freelist queue. * Currently, they are added on an LRU basis. */ void -AddBufferToFreelist(BufferDesc *bf) +AddBufferToFreelist(BufferDesc * bf) { #ifdef BMTRACE - _bm_trace(bf->tag.relId.dbId, bf->tag.relId.relId, bf->tag.blockNum, - BufferDescriptorGetBuffer(bf), BMT_DEALLOC); -#endif /* BMTRACE */ - NotInQueue(bf); - - /* change bf so it points to inFrontOfNew and its successor */ - bf->freePrev = SharedFreeList->freePrev; - bf->freeNext = Free_List_Descriptor; - - /* insert new into chain */ - BufferDescriptors[bf->freeNext].freePrev = bf->buf_id; - BufferDescriptors[bf->freePrev].freeNext = bf->buf_id; + _bm_trace(bf->tag.relId.dbId, bf->tag.relId.relId, bf->tag.blockNum, + BufferDescriptorGetBuffer(bf), BMT_DEALLOC); +#endif /* BMTRACE */ + NotInQueue(bf); + + /* change bf so it points to inFrontOfNew and its successor */ + bf->freePrev = SharedFreeList->freePrev; + bf->freeNext = Free_List_Descriptor; + + /* insert new into chain */ + BufferDescriptors[bf->freeNext].freePrev = bf->buf_id; + BufferDescriptors[bf->freePrev].freeNext = bf->buf_id; } #undef PinBuffer @@ -82,47 +82,52 @@ AddBufferToFreelist(BufferDesc *bf) * PinBuffer -- make buffer unavailable for replacement. */ void -PinBuffer(BufferDesc *buf) +PinBuffer(BufferDesc * buf) { - long b; - - /* Assert (buf->refcount < 25); */ - - if (buf->refcount == 0) { - IsInQueue(buf); - - /* remove from freelist queue */ - BufferDescriptors[buf->freeNext].freePrev = buf->freePrev; - BufferDescriptors[buf->freePrev].freeNext = buf->freeNext; - buf->freeNext = buf->freePrev = INVALID_DESCRIPTOR; - - /* mark buffer as no longer free */ - buf->flags &= ~BM_FREE; - } else { - NotInQueue(buf); - } - - b = BufferDescriptorGetBuffer(buf) - 1; - Assert(PrivateRefCount[b] >= 0); - if (PrivateRefCount[b] == 0 && LastRefCount[b] == 0) - buf->refcount++; - PrivateRefCount[b]++; + long b; + + /* Assert (buf->refcount < 25); */ + + if (buf->refcount == 0) + { + IsInQueue(buf); + + /* remove from freelist queue */ + BufferDescriptors[buf->freeNext].freePrev = buf->freePrev; + BufferDescriptors[buf->freePrev].freeNext = buf->freeNext; + buf->freeNext = buf->freePrev = INVALID_DESCRIPTOR; + + /* mark buffer as no longer free */ + buf->flags &= ~BM_FREE; + } + else + { + NotInQueue(buf); + } + + b = BufferDescriptorGetBuffer(buf) - 1; + Assert(PrivateRefCount[b] >= 0); + if (PrivateRefCount[b] == 0 && LastRefCount[b] == 0) + buf->refcount++; + PrivateRefCount[b]++; } #ifdef NOT_USED void -PinBuffer_Debug(char *file, int line, BufferDesc *buf) +PinBuffer_Debug(char *file, int line, BufferDesc * buf) { - PinBuffer(buf); - if (ShowPinTrace) { - Buffer buffer = BufferDescriptorGetBuffer(buf); - - fprintf(stderr, "PIN(Pin) %ld relname = %s, blockNum = %d, \ + PinBuffer(buf); + if (ShowPinTrace) + { + Buffer buffer = BufferDescriptorGetBuffer(buf); + + fprintf(stderr, "PIN(Pin) %ld relname = %s, blockNum = %d, \ refcount = %ld, file: %s, line: %d\n", - buffer, buf->sb_relname, buf->tag.blockNum, - PrivateRefCount[buffer - 1], file, line); - } + buffer, buf->sb_relname, buf->tag.blockNum, + PrivateRefCount[buffer - 1], file, line); + } } + #endif #undef UnpinBuffer @@ -131,95 +136,102 @@ refcount = %ld, file: %s, line: %d\n", * UnpinBuffer -- make buffer available for replacement. */ void -UnpinBuffer(BufferDesc *buf) +UnpinBuffer(BufferDesc * buf) { - long b = BufferDescriptorGetBuffer(buf) - 1; - - Assert(buf->refcount); - Assert(PrivateRefCount[b] > 0); - PrivateRefCount[b]--; - if (PrivateRefCount[b] == 0 && LastRefCount[b] == 0) - buf->refcount--; - NotInQueue(buf); - - if (buf->refcount == 0) { - AddBufferToFreelist(buf); - buf->flags |= BM_FREE; - } else { - /* do nothing */ - } + long b = BufferDescriptorGetBuffer(buf) - 1; + + Assert(buf->refcount); + Assert(PrivateRefCount[b] > 0); + PrivateRefCount[b]--; + if (PrivateRefCount[b] == 0 && LastRefCount[b] == 0) + buf->refcount--; + NotInQueue(buf); + + if (buf->refcount == 0) + { + AddBufferToFreelist(buf); + buf->flags |= BM_FREE; + } + else + { + /* do nothing */ + } } #ifdef NOT_USED void -UnpinBuffer_Debug(char *file, int line, BufferDesc *buf) +UnpinBuffer_Debug(char *file, int line, BufferDesc * buf) { - UnpinBuffer(buf); - if (ShowPinTrace) { - Buffer buffer = BufferDescriptorGetBuffer(buf); - - fprintf(stderr, "UNPIN(Unpin) %ld relname = %s, blockNum = %d, \ + UnpinBuffer(buf); + if (ShowPinTrace) + { + Buffer buffer = BufferDescriptorGetBuffer(buf); + + fprintf(stderr, "UNPIN(Unpin) %ld relname = %s, blockNum = %d, \ refcount = %ld, file: %s, line: %d\n", - buffer, buf->sb_relname, buf->tag.blockNum, - PrivateRefCount[buffer - 1], file, line); - } + buffer, buf->sb_relname, buf->tag.blockNum, + PrivateRefCount[buffer - 1], file, line); + } } + #endif /* * GetFreeBuffer() -- get the 'next' buffer from the freelist. * */ -BufferDesc * +BufferDesc * GetFreeBuffer() { - BufferDesc *buf; - - if (Free_List_Descriptor == SharedFreeList->freeNext) { - - /* queue is empty. All buffers in the buffer pool are pinned. */ - elog(WARN,"out of free buffers: time to abort !\n"); - return(NULL); - } - buf = &(BufferDescriptors[SharedFreeList->freeNext]); - - /* remove from freelist queue */ - BufferDescriptors[buf->freeNext].freePrev = buf->freePrev; - BufferDescriptors[buf->freePrev].freeNext = buf->freeNext; - buf->freeNext = buf->freePrev = INVALID_DESCRIPTOR; - - buf->flags &= ~(BM_FREE); - - return(buf); + BufferDesc *buf; + + if (Free_List_Descriptor == SharedFreeList->freeNext) + { + + /* queue is empty. All buffers in the buffer pool are pinned. */ + elog(WARN, "out of free buffers: time to abort !\n"); + return (NULL); + } + buf = &(BufferDescriptors[SharedFreeList->freeNext]); + + /* remove from freelist queue */ + BufferDescriptors[buf->freeNext].freePrev = buf->freePrev; + BufferDescriptors[buf->freePrev].freeNext = buf->freeNext; + buf->freeNext = buf->freePrev = INVALID_DESCRIPTOR; + + buf->flags &= ~(BM_FREE); + + return (buf); } /* * InitFreeList -- initialize the dummy buffer descriptor used - * as a freelist head. + * as a freelist head. * * Assume: All of the buffers are already linked in a circular - * queue. Only called by postmaster and only during - * initialization. + * queue. Only called by postmaster and only during + * initialization. */ void InitFreeList(bool init) { - SharedFreeList = &(BufferDescriptors[Free_List_Descriptor]); - - if (init) { - /* we only do this once, normally the postmaster */ - SharedFreeList->data = INVALID_OFFSET; - SharedFreeList->flags = 0; - SharedFreeList->flags &= ~(BM_VALID | BM_DELETED | BM_FREE); - SharedFreeList->buf_id = Free_List_Descriptor; - - /* insert it into a random spot in the circular queue */ - SharedFreeList->freeNext = BufferDescriptors[0].freeNext; - SharedFreeList->freePrev = 0; - BufferDescriptors[SharedFreeList->freeNext].freePrev = - BufferDescriptors[SharedFreeList->freePrev].freeNext = - Free_List_Descriptor; - } + SharedFreeList = &(BufferDescriptors[Free_List_Descriptor]); + + if (init) + { + /* we only do this once, normally the postmaster */ + SharedFreeList->data = INVALID_OFFSET; + SharedFreeList->flags = 0; + SharedFreeList->flags &= ~(BM_VALID | BM_DELETED | BM_FREE); + SharedFreeList->buf_id = Free_List_Descriptor; + + /* insert it into a random spot in the circular queue */ + SharedFreeList->freeNext = BufferDescriptors[0].freeNext; + SharedFreeList->freePrev = 0; + BufferDescriptors[SharedFreeList->freeNext].freePrev = + BufferDescriptors[SharedFreeList->freePrev].freeNext = + Free_List_Descriptor; + } } @@ -230,67 +242,78 @@ InitFreeList(bool init) void DBG_FreeListCheck(int nfree) { - int i; - BufferDesc *buf; - - buf = &(BufferDescriptors[SharedFreeList->freeNext]); - for (i=0;i<nfree;i++,buf = &(BufferDescriptors[buf->freeNext])) { - - if (! (buf->flags & (BM_FREE))){ - if (buf != SharedFreeList) { - printf("\tfree list corrupted: %d flags %x\n", - buf->buf_id,buf->flags); - } else { - printf("\tfree list corrupted: too short -- %d not %d\n", - i,nfree); - - } - - + int i; + BufferDesc *buf; + + buf = &(BufferDescriptors[SharedFreeList->freeNext]); + for (i = 0; i < nfree; i++, buf = &(BufferDescriptors[buf->freeNext])) + { + + if (!(buf->flags & (BM_FREE))) + { + if (buf != SharedFreeList) + { + printf("\tfree list corrupted: %d flags %x\n", + buf->buf_id, buf->flags); + } + else + { + printf("\tfree list corrupted: too short -- %d not %d\n", + i, nfree); + + } + + + } + if ((BufferDescriptors[buf->freeNext].freePrev != buf->buf_id) || + (BufferDescriptors[buf->freePrev].freeNext != buf->buf_id)) + { + printf("\tfree list links corrupted: %d %ld %ld\n", + buf->buf_id, buf->freePrev, buf->freeNext); + } + } - if ((BufferDescriptors[buf->freeNext].freePrev != buf->buf_id) || - (BufferDescriptors[buf->freePrev].freeNext != buf->buf_id)) { - printf("\tfree list links corrupted: %d %ld %ld\n", - buf->buf_id,buf->freePrev,buf->freeNext); + if (buf != SharedFreeList) + { + printf("\tfree list corrupted: %d-th buffer is %d\n", + nfree, buf->buf_id); + } - - } - if (buf != SharedFreeList) { - printf("\tfree list corrupted: %d-th buffer is %d\n", - nfree,buf->buf_id); - - } } + #endif #ifdef NOT_USED /* * PrintBufferFreeList - - * prints the buffer free list, for debugging + * prints the buffer free list, for debugging */ static void PrintBufferFreeList() { - BufferDesc *buf; - - if (SharedFreeList->freeNext == Free_List_Descriptor) { - printf("free list is empty.\n"); - return; - } - - buf = &(BufferDescriptors[SharedFreeList->freeNext]); - for (;;) { - int i = (buf - BufferDescriptors); - printf("[%-2d] (%s, %d) flags=0x%x, refcnt=%d %ld, nxt=%ld prv=%ld)\n", - i, buf->sb_relname, buf->tag.blockNum, - buf->flags, buf->refcount, PrivateRefCount[i], - buf->freeNext, buf->freePrev); - - if (buf->freeNext == Free_List_Descriptor) - break; - - buf = &(BufferDescriptors[buf->freeNext]); - } + BufferDesc *buf; + + if (SharedFreeList->freeNext == Free_List_Descriptor) + { + printf("free list is empty.\n"); + return; + } + + buf = &(BufferDescriptors[SharedFreeList->freeNext]); + for (;;) + { + int i = (buf - BufferDescriptors); + + printf("[%-2d] (%s, %d) flags=0x%x, refcnt=%d %ld, nxt=%ld prv=%ld)\n", + i, buf->sb_relname, buf->tag.blockNum, + buf->flags, buf->refcount, PrivateRefCount[i], + buf->freeNext, buf->freePrev); + + if (buf->freeNext == Free_List_Descriptor) + break; + + buf = &(BufferDescriptors[buf->freeNext]); + } } #endif |