PostgreSQL Source Code  git master
buf_internals.h File Reference
#include "pgstat.h"
#include "port/atomics.h"
#include "storage/buf.h"
#include "storage/bufmgr.h"
#include "storage/condition_variable.h"
#include "storage/latch.h"
#include "storage/lwlock.h"
#include "storage/shmem.h"
#include "storage/smgr.h"
#include "storage/spin.h"
#include "utils/relcache.h"
Include dependency graph for buf_internals.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  buftag
 
struct  BufferDesc
 
union  BufferDescPadded
 
struct  PendingWriteback
 
struct  WritebackContext
 
struct  CkptSortItem
 

Macros

#define BUF_REFCOUNT_ONE   1
 
#define BUF_REFCOUNT_MASK   ((1U << 18) - 1)
 
#define BUF_USAGECOUNT_MASK   0x003C0000U
 
#define BUF_USAGECOUNT_ONE   (1U << 18)
 
#define BUF_USAGECOUNT_SHIFT   18
 
#define BUF_FLAG_MASK   0xFFC00000U
 
#define BUF_STATE_GET_REFCOUNT(state)   ((state) & BUF_REFCOUNT_MASK)
 
#define BUF_STATE_GET_USAGECOUNT(state)   (((state) & BUF_USAGECOUNT_MASK) >> BUF_USAGECOUNT_SHIFT)
 
#define BM_LOCKED   (1U << 22) /* buffer header is locked */
 
#define BM_DIRTY   (1U << 23) /* data needs writing */
 
#define BM_VALID   (1U << 24) /* data is valid */
 
#define BM_TAG_VALID   (1U << 25) /* tag is assigned */
 
#define BM_IO_IN_PROGRESS   (1U << 26) /* read or write in progress */
 
#define BM_IO_ERROR   (1U << 27) /* previous I/O failed */
 
#define BM_JUST_DIRTIED   (1U << 28) /* dirtied since write started */
 
#define BM_PIN_COUNT_WAITER   (1U << 29) /* have waiter for sole pin */
 
#define BM_CHECKPOINT_NEEDED   (1U << 30) /* must write for checkpoint */
 
#define BM_PERMANENT
 
#define BM_MAX_USAGE_COUNT   5
 
#define BUFFERDESC_PAD_TO_SIZE   (SIZEOF_VOID_P == 8 ? 64 : 1)
 
#define FREENEXT_END_OF_LIST   (-1)
 
#define FREENEXT_NOT_IN_LIST   (-2)
 

Typedefs

typedef struct buftag BufferTag
 
typedef struct BufferDesc BufferDesc
 
typedef union BufferDescPadded BufferDescPadded
 
typedef struct PendingWriteback PendingWriteback
 
typedef struct WritebackContext WritebackContext
 
typedef struct CkptSortItem CkptSortItem
 

Functions

static RelFileNumber BufTagGetRelNumber (const BufferTag *tag)
 
static ForkNumber BufTagGetForkNum (const BufferTag *tag)
 
static void BufTagSetRelForkDetails (BufferTag *tag, RelFileNumber relnumber, ForkNumber forknum)
 
static RelFileLocator BufTagGetRelFileLocator (const BufferTag *tag)
 
static void ClearBufferTag (BufferTag *tag)
 
static void InitBufferTag (BufferTag *tag, const RelFileLocator *rlocator, ForkNumber forkNum, BlockNumber blockNum)
 
static bool BufferTagsEqual (const BufferTag *tag1, const BufferTag *tag2)
 
static bool BufTagMatchesRelFileLocator (const BufferTag *tag, const RelFileLocator *rlocator)
 
static uint32 BufTableHashPartition (uint32 hashcode)
 
static LWLockBufMappingPartitionLock (uint32 hashcode)
 
static LWLockBufMappingPartitionLockByIndex (uint32 index)
 
static BufferDescGetBufferDescriptor (uint32 id)
 
static BufferDescGetLocalBufferDescriptor (uint32 id)
 
static Buffer BufferDescriptorGetBuffer (const BufferDesc *bdesc)
 
static ConditionVariableBufferDescriptorGetIOCV (const BufferDesc *bdesc)
 
static LWLockBufferDescriptorGetContentLock (const BufferDesc *bdesc)
 
uint32 LockBufHdr (BufferDesc *desc)
 
static void UnlockBufHdr (BufferDesc *desc, uint32 buf_state)
 
void WritebackContextInit (WritebackContext *context, int *max_pending)
 
void IssuePendingWritebacks (WritebackContext *context)
 
void ScheduleBufferTagForWriteback (WritebackContext *context, BufferTag *tag)
 
IOContext IOContextForStrategy (BufferAccessStrategy bas)
 
BufferDescStrategyGetBuffer (BufferAccessStrategy strategy, uint32 *buf_state, bool *from_ring)
 
void StrategyFreeBuffer (BufferDesc *buf)
 
bool StrategyRejectBuffer (BufferAccessStrategy strategy, BufferDesc *buf, bool from_ring)
 
int StrategySyncStart (uint32 *complete_passes, uint32 *num_buf_alloc)
 
void StrategyNotifyBgWriter (int bgwprocno)
 
Size StrategyShmemSize (void)
 
void StrategyInitialize (bool init)
 
bool have_free_buffer (void)
 
Size BufTableShmemSize (int size)
 
void InitBufTable (int size)
 
uint32 BufTableHashCode (BufferTag *tagPtr)
 
int BufTableLookup (BufferTag *tagPtr, uint32 hashcode)
 
int BufTableInsert (BufferTag *tagPtr, uint32 hashcode, int buf_id)
 
void BufTableDelete (BufferTag *tagPtr, uint32 hashcode)
 
PrefetchBufferResult PrefetchLocalBuffer (SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum)
 
BufferDescLocalBufferAlloc (SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, bool *foundPtr, IOContext *io_context)
 
void MarkLocalBufferDirty (Buffer buffer)
 
void DropRelationLocalBuffers (RelFileLocator rlocator, ForkNumber forkNum, BlockNumber firstDelBlock)
 
void DropRelationAllLocalBuffers (RelFileLocator rlocator)
 
void AtEOXact_LocalBuffers (bool isCommit)
 

Variables

PGDLLIMPORT BufferDescPaddedBufferDescriptors
 
PGDLLIMPORT ConditionVariableMinimallyPaddedBufferIOCVArray
 
PGDLLIMPORT WritebackContext BackendWritebackContext
 
PGDLLIMPORT BufferDescLocalBufferDescriptors
 
PGDLLIMPORT CkptSortItemCkptBufferIds
 

Macro Definition Documentation

◆ BM_CHECKPOINT_NEEDED

#define BM_CHECKPOINT_NEEDED   (1U << 30) /* must write for checkpoint */

Definition at line 67 of file buf_internals.h.

◆ BM_DIRTY

#define BM_DIRTY   (1U << 23) /* data needs writing */

Definition at line 60 of file buf_internals.h.

◆ BM_IO_ERROR

#define BM_IO_ERROR   (1U << 27) /* previous I/O failed */

Definition at line 64 of file buf_internals.h.

◆ BM_IO_IN_PROGRESS

#define BM_IO_IN_PROGRESS   (1U << 26) /* read or write in progress */

Definition at line 63 of file buf_internals.h.

◆ BM_JUST_DIRTIED

#define BM_JUST_DIRTIED   (1U << 28) /* dirtied since write started */

Definition at line 65 of file buf_internals.h.

◆ BM_LOCKED

#define BM_LOCKED   (1U << 22) /* buffer header is locked */

Definition at line 59 of file buf_internals.h.

◆ BM_MAX_USAGE_COUNT

#define BM_MAX_USAGE_COUNT   5

Definition at line 77 of file buf_internals.h.

◆ BM_PERMANENT

#define BM_PERMANENT
Value:
(1U << 31) /* permanent buffer (not unlogged,
* or init fork) */

Definition at line 68 of file buf_internals.h.

◆ BM_PIN_COUNT_WAITER

#define BM_PIN_COUNT_WAITER   (1U << 29) /* have waiter for sole pin */

Definition at line 66 of file buf_internals.h.

◆ BM_TAG_VALID

#define BM_TAG_VALID   (1U << 25) /* tag is assigned */

Definition at line 62 of file buf_internals.h.

◆ BM_VALID

#define BM_VALID   (1U << 24) /* data is valid */

Definition at line 61 of file buf_internals.h.

◆ BUF_FLAG_MASK

#define BUF_FLAG_MASK   0xFFC00000U

Definition at line 47 of file buf_internals.h.

◆ BUF_REFCOUNT_MASK

#define BUF_REFCOUNT_MASK   ((1U << 18) - 1)

Definition at line 43 of file buf_internals.h.

◆ BUF_REFCOUNT_ONE

#define BUF_REFCOUNT_ONE   1

Definition at line 42 of file buf_internals.h.

◆ BUF_STATE_GET_REFCOUNT

#define BUF_STATE_GET_REFCOUNT (   state)    ((state) & BUF_REFCOUNT_MASK)

Definition at line 50 of file buf_internals.h.

◆ BUF_STATE_GET_USAGECOUNT

#define BUF_STATE_GET_USAGECOUNT (   state)    (((state) & BUF_USAGECOUNT_MASK) >> BUF_USAGECOUNT_SHIFT)

Definition at line 51 of file buf_internals.h.

◆ BUF_USAGECOUNT_MASK

#define BUF_USAGECOUNT_MASK   0x003C0000U

Definition at line 44 of file buf_internals.h.

◆ BUF_USAGECOUNT_ONE

#define BUF_USAGECOUNT_ONE   (1U << 18)

Definition at line 45 of file buf_internals.h.

◆ BUF_USAGECOUNT_SHIFT

#define BUF_USAGECOUNT_SHIFT   18

Definition at line 46 of file buf_internals.h.

◆ BUFFERDESC_PAD_TO_SIZE

#define BUFFERDESC_PAD_TO_SIZE   (SIZEOF_VOID_P == 8 ? 64 : 1)

Definition at line 276 of file buf_internals.h.

◆ FREENEXT_END_OF_LIST

#define FREENEXT_END_OF_LIST   (-1)

Definition at line 350 of file buf_internals.h.

◆ FREENEXT_NOT_IN_LIST

#define FREENEXT_NOT_IN_LIST   (-2)

Definition at line 351 of file buf_internals.h.

Typedef Documentation

◆ BufferDesc

typedef struct BufferDesc BufferDesc

◆ BufferDescPadded

◆ BufferTag

typedef struct buftag BufferTag

◆ CkptSortItem

typedef struct CkptSortItem CkptSortItem

◆ PendingWriteback

◆ WritebackContext

Function Documentation

◆ AtEOXact_LocalBuffers()

void AtEOXact_LocalBuffers ( bool  isCommit)

Definition at line 606 of file localbuf.c.

607 {
609 }
static void CheckForLocalBufferLeaks(void)
Definition: localbuf.c:577

References CheckForLocalBufferLeaks().

Referenced by AtEOXact_Buffers().

◆ BufferDescriptorGetBuffer()

static Buffer BufferDescriptorGetBuffer ( const BufferDesc bdesc)
inlinestatic

◆ BufferDescriptorGetContentLock()

◆ BufferDescriptorGetIOCV()

static ConditionVariable* BufferDescriptorGetIOCV ( const BufferDesc bdesc)
inlinestatic

Definition at line 335 of file buf_internals.h.

337 {
338  return &(BufferIOCVArray[bdesc->buf_id]).cv;
PGDLLIMPORT ConditionVariableMinimallyPadded * BufferIOCVArray
Definition: buf_init.c:23

References BufferDesc::buf_id, and BufferIOCVArray.

Referenced by InitBufferPool(), TerminateBufferIO(), and WaitIO().

◆ BufferTagsEqual()

static bool BufferTagsEqual ( const BufferTag tag1,
const BufferTag tag2 
)
inlinestatic

Definition at line 152 of file buf_internals.h.

154 {
155  return (tag1->spcOid == tag2->spcOid) &&
156  (tag1->dbOid == tag2->dbOid) &&
157  (tag1->relNumber == tag2->relNumber) &&
158  (tag1->blockNum == tag2->blockNum) &&
159  (tag1->forkNum == tag2->forkNum);
BlockNumber blockNum
Definition: buf_internals.h:97
RelFileNumber relNumber
Definition: buf_internals.h:95
ForkNumber forkNum
Definition: buf_internals.h:96
Oid spcOid
Definition: buf_internals.h:93
Oid dbOid
Definition: buf_internals.h:94

References buftag::blockNum, buftag::dbOid, buftag::forkNum, buftag::relNumber, and buftag::spcOid.

Referenced by InvalidateBuffer(), LocalBufferAlloc(), and ReadRecentBuffer().

◆ BufMappingPartitionLock()

static LWLock* BufMappingPartitionLock ( uint32  hashcode)
inlinestatic

Definition at line 184 of file buf_internals.h.

186 {
188  BufTableHashPartition(hashcode)].lock;
static uint32 BufTableHashPartition(uint32 hashcode)
LWLockPadded * MainLWLockArray
Definition: lwlock.c:212
#define BUFFER_MAPPING_LWLOCK_OFFSET
Definition: lwlock.h:105
LWLock lock
Definition: lwlock.h:68

References BUFFER_MAPPING_LWLOCK_OFFSET, BufTableHashPartition(), LWLockPadded::lock, and MainLWLockArray.

Referenced by BufferAlloc(), FindAndDropRelationBuffers(), InvalidateBuffer(), and PrefetchSharedBuffer().

◆ BufMappingPartitionLockByIndex()

static LWLock* BufMappingPartitionLockByIndex ( uint32  index)
inlinestatic

◆ BufTableDelete()

void BufTableDelete ( BufferTag tagPtr,
uint32  hashcode 
)

Definition at line 149 of file buf_table.c.

150 {
151  BufferLookupEnt *result;
152 
153  result = (BufferLookupEnt *)
155  tagPtr,
156  hashcode,
157  HASH_REMOVE,
158  NULL);
159 
160  if (!result) /* shouldn't happen */
161  elog(ERROR, "shared buffer hash table corrupted");
162 }
static HTAB * SharedBufHash
Definition: buf_table.c:34
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:966
#define ERROR
Definition: elog.h:39
@ HASH_REMOVE
Definition: hsearch.h:115

References elog(), ERROR, HASH_REMOVE, hash_search_with_hash_value(), and SharedBufHash.

Referenced by BufferAlloc(), and InvalidateBuffer().

◆ BufTableHashCode()

uint32 BufTableHashCode ( BufferTag tagPtr)

Definition at line 79 of file buf_table.c.

80 {
81  return get_hash_value(SharedBufHash, (void *) tagPtr);
82 }
uint32 get_hash_value(HTAB *hashp, const void *keyPtr)
Definition: dynahash.c:909

References get_hash_value(), and SharedBufHash.

Referenced by BufferAlloc(), FindAndDropRelationBuffers(), InvalidateBuffer(), and PrefetchSharedBuffer().

◆ BufTableHashPartition()

static uint32 BufTableHashPartition ( uint32  hashcode)
inlinestatic

Definition at line 178 of file buf_internals.h.

180 {
181  return hashcode % NUM_BUFFER_PARTITIONS;
#define NUM_BUFFER_PARTITIONS
Definition: lwlock.h:94

References NUM_BUFFER_PARTITIONS.

Referenced by BufMappingPartitionLock().

◆ BufTableInsert()

int BufTableInsert ( BufferTag tagPtr,
uint32  hashcode,
int  buf_id 
)

Definition at line 119 of file buf_table.c.

120 {
121  BufferLookupEnt *result;
122  bool found;
123 
124  Assert(buf_id >= 0); /* -1 is reserved for not-in-table */
125  Assert(tagPtr->blockNum != P_NEW); /* invalid tag */
126 
127  result = (BufferLookupEnt *)
129  tagPtr,
130  hashcode,
131  HASH_ENTER,
132  &found);
133 
134  if (found) /* found something already in the table */
135  return result->id;
136 
137  result->id = buf_id;
138 
139  return -1;
140 }
#define P_NEW
Definition: bufmgr.h:105
@ HASH_ENTER
Definition: hsearch.h:114
Assert(fmt[strlen(fmt) - 1] !='\n')

References Assert(), buftag::blockNum, HASH_ENTER, hash_search_with_hash_value(), BufferLookupEnt::id, P_NEW, and SharedBufHash.

Referenced by BufferAlloc().

◆ BufTableLookup()

int BufTableLookup ( BufferTag tagPtr,
uint32  hashcode 
)

Definition at line 91 of file buf_table.c.

92 {
93  BufferLookupEnt *result;
94 
95  result = (BufferLookupEnt *)
97  tagPtr,
98  hashcode,
99  HASH_FIND,
100  NULL);
101 
102  if (!result)
103  return -1;
104 
105  return result->id;
106 }
@ HASH_FIND
Definition: hsearch.h:113

References HASH_FIND, hash_search_with_hash_value(), BufferLookupEnt::id, and SharedBufHash.

Referenced by BufferAlloc(), FindAndDropRelationBuffers(), and PrefetchSharedBuffer().

◆ BufTableShmemSize()

Size BufTableShmemSize ( int  size)

Definition at line 42 of file buf_table.c.

43 {
44  return hash_estimate_size(size, sizeof(BufferLookupEnt));
45 }
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:781

References hash_estimate_size().

Referenced by StrategyShmemSize().

◆ BufTagGetForkNum()

◆ BufTagGetRelFileLocator()

◆ BufTagGetRelNumber()

static RelFileNumber BufTagGetRelNumber ( const BufferTag tag)
inlinestatic

Definition at line 101 of file buf_internals.h.

103 {
104  return tag->relNumber;

References buftag::relNumber.

Referenced by apw_dump_now(), BufferSync(), BufTagGetRelFileLocator(), BufTagMatchesRelFileLocator(), and pg_buffercache_pages().

◆ BufTagMatchesRelFileLocator()

static bool BufTagMatchesRelFileLocator ( const BufferTag tag,
const RelFileLocator rlocator 
)
inlinestatic

◆ BufTagSetRelForkDetails()

static void BufTagSetRelForkDetails ( BufferTag tag,
RelFileNumber  relnumber,
ForkNumber  forknum 
)
inlinestatic

Definition at line 113 of file buf_internals.h.

116 {
117  tag->relNumber = relnumber;
118  tag->forkNum = forknum;

References buftag::forkNum, and buftag::relNumber.

Referenced by ClearBufferTag(), and InitBufferTag().

◆ ClearBufferTag()

static void ClearBufferTag ( BufferTag tag)
inlinestatic

Definition at line 133 of file buf_internals.h.

135 {
136  tag->spcOid = InvalidOid;
137  tag->dbOid = InvalidOid;
#define InvalidBlockNumber
Definition: block.h:33
static void BufTagSetRelForkDetails(BufferTag *tag, RelFileNumber relnumber, ForkNumber forknum)
#define InvalidOid
Definition: postgres_ext.h:36
@ InvalidForkNumber
Definition: relpath.h:49
#define InvalidRelFileNumber
Definition: relpath.h:26

References buftag::blockNum, BufTagSetRelForkDetails(), buftag::dbOid, InvalidBlockNumber, InvalidForkNumber, InvalidOid, InvalidRelFileNumber, and buftag::spcOid.

Referenced by DropRelationAllLocalBuffers(), DropRelationLocalBuffers(), InitBufferPool(), InvalidateBuffer(), and LocalBufferAlloc().

◆ DropRelationAllLocalBuffers()

void DropRelationAllLocalBuffers ( RelFileLocator  rlocator)

Definition at line 384 of file localbuf.c.

385 {
386  int i;
387 
388  for (i = 0; i < NLocBuffer; i++)
389  {
391  LocalBufferLookupEnt *hresult;
392  uint32 buf_state;
393 
394  buf_state = pg_atomic_read_u32(&bufHdr->state);
395 
396  if ((buf_state & BM_TAG_VALID) &&
397  BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator))
398  {
399  if (LocalRefCount[i] != 0)
400  elog(ERROR, "block %u of %s is still referenced (local %u)",
401  bufHdr->tag.blockNum,
403  MyBackendId,
404  BufTagGetForkNum(&bufHdr->tag)),
405  LocalRefCount[i]);
406  /* Remove entry from hashtable */
407  hresult = (LocalBufferLookupEnt *)
408  hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL);
409  if (!hresult) /* shouldn't happen */
410  elog(ERROR, "local buffer hash table corrupted");
411  /* Mark buffer invalid */
412  ClearBufferTag(&bufHdr->tag);
413  buf_state &= ~BUF_FLAG_MASK;
414  buf_state &= ~BUF_USAGECOUNT_MASK;
415  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
416  }
417  }
418 }
static void pg_atomic_unlocked_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:272
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:236
#define BM_TAG_VALID
Definition: buf_internals.h:62
#define BUF_USAGECOUNT_MASK
Definition: buf_internals.h:44
static ForkNumber BufTagGetForkNum(const BufferTag *tag)
static BufferDesc * GetLocalBufferDescriptor(uint32 id)
static bool BufTagMatchesRelFileLocator(const BufferTag *tag, const RelFileLocator *rlocator)
#define BUF_FLAG_MASK
Definition: buf_internals.h:47
static void ClearBufferTag(BufferTag *tag)
static RelFileLocator BufTagGetRelFileLocator(const BufferTag *tag)
unsigned int uint32
Definition: c.h:490
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:953
BackendId MyBackendId
Definition: globals.c:85
int i
Definition: isn.c:73
int32 * LocalRefCount
Definition: localbuf.c:46
static HTAB * LocalBufHash
Definition: localbuf.c:50
int NLocBuffer
Definition: localbuf.c:42
#define relpathbackend(rlocator, backend, forknum)
Definition: relpath.h:85
BufferTag tag
pg_atomic_uint32 state

References buftag::blockNum, BM_TAG_VALID, BUF_FLAG_MASK, BUF_USAGECOUNT_MASK, BufTagGetForkNum(), BufTagGetRelFileLocator(), BufTagMatchesRelFileLocator(), ClearBufferTag(), elog(), ERROR, GetLocalBufferDescriptor(), HASH_REMOVE, hash_search(), i, LocalBufHash, LocalRefCount, MyBackendId, NLocBuffer, pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), relpathbackend, BufferDesc::state, and BufferDesc::tag.

Referenced by DropRelationsAllBuffers().

◆ DropRelationLocalBuffers()

void DropRelationLocalBuffers ( RelFileLocator  rlocator,
ForkNumber  forkNum,
BlockNumber  firstDelBlock 
)

Definition at line 336 of file localbuf.c.

338 {
339  int i;
340 
341  for (i = 0; i < NLocBuffer; i++)
342  {
344  LocalBufferLookupEnt *hresult;
345  uint32 buf_state;
346 
347  buf_state = pg_atomic_read_u32(&bufHdr->state);
348 
349  if ((buf_state & BM_TAG_VALID) &&
350  BufTagMatchesRelFileLocator(&bufHdr->tag, &rlocator) &&
351  BufTagGetForkNum(&bufHdr->tag) == forkNum &&
352  bufHdr->tag.blockNum >= firstDelBlock)
353  {
354  if (LocalRefCount[i] != 0)
355  elog(ERROR, "block %u of %s is still referenced (local %u)",
356  bufHdr->tag.blockNum,
358  MyBackendId,
359  BufTagGetForkNum(&bufHdr->tag)),
360  LocalRefCount[i]);
361 
362  /* Remove entry from hashtable */
363  hresult = (LocalBufferLookupEnt *)
364  hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL);
365  if (!hresult) /* shouldn't happen */
366  elog(ERROR, "local buffer hash table corrupted");
367  /* Mark buffer invalid */
368  ClearBufferTag(&bufHdr->tag);
369  buf_state &= ~BUF_FLAG_MASK;
370  buf_state &= ~BUF_USAGECOUNT_MASK;
371  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
372  }
373  }
374 }

References buftag::blockNum, BM_TAG_VALID, BUF_FLAG_MASK, BUF_USAGECOUNT_MASK, BufTagGetForkNum(), BufTagGetRelFileLocator(), BufTagMatchesRelFileLocator(), ClearBufferTag(), elog(), ERROR, GetLocalBufferDescriptor(), HASH_REMOVE, hash_search(), i, LocalBufHash, LocalRefCount, MyBackendId, NLocBuffer, pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), relpathbackend, BufferDesc::state, and BufferDesc::tag.

Referenced by DropRelationBuffers().

◆ GetBufferDescriptor()

◆ GetLocalBufferDescriptor()

◆ have_free_buffer()

bool have_free_buffer ( void  )

Definition at line 175 of file freelist.c.

176 {
178  return true;
179  else
180  return false;
181 }
static BufferStrategyControl * StrategyControl
Definition: freelist.c:65

References BufferStrategyControl::firstFreeBuffer, and StrategyControl.

Referenced by apw_load_buffers(), and autoprewarm_database_main().

◆ InitBufferTag()

static void InitBufferTag ( BufferTag tag,
const RelFileLocator rlocator,
ForkNumber  forkNum,
BlockNumber  blockNum 
)
inlinestatic

◆ InitBufTable()

void InitBufTable ( int  size)

Definition at line 52 of file buf_table.c.

53 {
54  HASHCTL info;
55 
56  /* assume no locking is needed yet */
57 
58  /* BufferTag maps to Buffer */
59  info.keysize = sizeof(BufferTag);
60  info.entrysize = sizeof(BufferLookupEnt);
62 
63  SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
64  size, size,
65  &info,
67 }
struct buftag BufferTag
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
#define HASH_PARTITION
Definition: hsearch.h:92
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Definition: shmem.c:341
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76
long num_partitions
Definition: hsearch.h:68

References HASHCTL::entrysize, HASH_BLOBS, HASH_ELEM, HASH_PARTITION, HASHCTL::keysize, NUM_BUFFER_PARTITIONS, HASHCTL::num_partitions, SharedBufHash, and ShmemInitHash().

Referenced by StrategyInitialize().

◆ IOContextForStrategy()

IOContext IOContextForStrategy ( BufferAccessStrategy  bas)

Definition at line 673 of file freelist.c.

674 {
675  if (!strategy)
676  return IOCONTEXT_NORMAL;
677 
678  switch (strategy->btype)
679  {
680  case BAS_NORMAL:
681 
682  /*
683  * Currently, GetAccessStrategy() returns NULL for
684  * BufferAccessStrategyType BAS_NORMAL, so this case is
685  * unreachable.
686  */
687  pg_unreachable();
688  return IOCONTEXT_NORMAL;
689  case BAS_BULKREAD:
690  return IOCONTEXT_BULKREAD;
691  case BAS_BULKWRITE:
692  return IOCONTEXT_BULKWRITE;
693  case BAS_VACUUM:
694  return IOCONTEXT_VACUUM;
695  }
696 
697  elog(ERROR, "unrecognized BufferAccessStrategyType: %d", strategy->btype);
698  pg_unreachable();
699 }
@ BAS_BULKREAD
Definition: bufmgr.h:35
@ BAS_NORMAL
Definition: bufmgr.h:34
@ BAS_VACUUM
Definition: bufmgr.h:38
@ BAS_BULKWRITE
Definition: bufmgr.h:37
#define pg_unreachable()
Definition: c.h:280
@ IOCONTEXT_NORMAL
Definition: pgstat.h:288
@ IOCONTEXT_VACUUM
Definition: pgstat.h:289
@ IOCONTEXT_BULKREAD
Definition: pgstat.h:286
@ IOCONTEXT_BULKWRITE
Definition: pgstat.h:287

References BAS_BULKREAD, BAS_BULKWRITE, BAS_NORMAL, BAS_VACUUM, BufferAccessStrategyData::btype, elog(), ERROR, IOCONTEXT_BULKREAD, IOCONTEXT_BULKWRITE, IOCONTEXT_NORMAL, IOCONTEXT_VACUUM, and pg_unreachable.

Referenced by BufferAlloc().

◆ IssuePendingWritebacks()

void IssuePendingWritebacks ( WritebackContext context)

Definition at line 5015 of file bufmgr.c.

5016 {
5017  int i;
5018 
5019  if (context->nr_pending == 0)
5020  return;
5021 
5022  /*
5023  * Executing the writes in-order can make them a lot faster, and allows to
5024  * merge writeback requests to consecutive blocks into larger writebacks.
5025  */
5026  sort_pending_writebacks(context->pending_writebacks, context->nr_pending);
5027 
5028  /*
5029  * Coalesce neighbouring writes, but nothing else. For that we iterate
5030  * through the, now sorted, array of pending flushes, and look forward to
5031  * find all neighbouring (or identical) writes.
5032  */
5033  for (i = 0; i < context->nr_pending; i++)
5034  {
5037  SMgrRelation reln;
5038  int ahead;
5039  BufferTag tag;
5040  RelFileLocator currlocator;
5041  Size nblocks = 1;
5042 
5043  cur = &context->pending_writebacks[i];
5044  tag = cur->tag;
5045  currlocator = BufTagGetRelFileLocator(&tag);
5046 
5047  /*
5048  * Peek ahead, into following writeback requests, to see if they can
5049  * be combined with the current one.
5050  */
5051  for (ahead = 0; i + ahead + 1 < context->nr_pending; ahead++)
5052  {
5053 
5054  next = &context->pending_writebacks[i + ahead + 1];
5055 
5056  /* different file, stop */
5057  if (!RelFileLocatorEquals(currlocator,
5058  BufTagGetRelFileLocator(&next->tag)) ||
5059  BufTagGetForkNum(&cur->tag) != BufTagGetForkNum(&next->tag))
5060  break;
5061 
5062  /* ok, block queued twice, skip */
5063  if (cur->tag.blockNum == next->tag.blockNum)
5064  continue;
5065 
5066  /* only merge consecutive writes */
5067  if (cur->tag.blockNum + 1 != next->tag.blockNum)
5068  break;
5069 
5070  nblocks++;
5071  cur = next;
5072  }
5073 
5074  i += ahead;
5075 
5076  /* and finally tell the kernel to write the data to storage */
5077  reln = smgropen(currlocator, InvalidBackendId);
5078  smgrwriteback(reln, BufTagGetForkNum(&tag), tag.blockNum, nblocks);
5079  }
5080 
5081  context->nr_pending = 0;
5082 }
#define InvalidBackendId
Definition: backendid.h:23
static int32 next
Definition: blutils.c:219
size_t Size
Definition: c.h:589
struct cursor * cur
Definition: ecpg.c:28
#define RelFileLocatorEquals(locator1, locator2)
void smgrwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, BlockNumber nblocks)
Definition: smgr.c:567
SMgrRelation smgropen(RelFileLocator rlocator, BackendId backend)
Definition: smgr.c:146
PendingWriteback pending_writebacks[WRITEBACK_MAX_PENDING_FLUSHES]

References buftag::blockNum, BufTagGetForkNum(), BufTagGetRelFileLocator(), cur, i, InvalidBackendId, next, WritebackContext::nr_pending, WritebackContext::pending_writebacks, RelFileLocatorEquals, smgropen(), and smgrwriteback().

Referenced by BufferSync(), and ScheduleBufferTagForWriteback().

◆ LocalBufferAlloc()

BufferDesc* LocalBufferAlloc ( SMgrRelation  smgr,
ForkNumber  forkNum,
BlockNumber  blockNum,
bool foundPtr,
IOContext io_context 
)

Definition at line 110 of file localbuf.c.

112 {
113  BufferTag newTag; /* identity of requested block */
114  LocalBufferLookupEnt *hresult;
115  BufferDesc *bufHdr;
116  int b;
117  int trycounter;
118  bool found;
119  uint32 buf_state;
120 
121  InitBufferTag(&newTag, &smgr->smgr_rlocator.locator, forkNum, blockNum);
122 
123  /* Initialize local buffers if first request in this session */
124  if (LocalBufHash == NULL)
126 
127  /* See if the desired buffer already exists */
128  hresult = (LocalBufferLookupEnt *)
129  hash_search(LocalBufHash, &newTag, HASH_FIND, NULL);
130 
131  /*
132  * IO Operations on local buffers are only done in IOCONTEXT_NORMAL. Set
133  * io_context here (instead of after a buffer hit would have returned) for
134  * convenience since we don't have to worry about the overhead of calling
135  * IOContextForStrategy().
136  */
137  *io_context = IOCONTEXT_NORMAL;
138 
139  if (hresult)
140  {
141  b = hresult->id;
142  bufHdr = GetLocalBufferDescriptor(b);
143  Assert(BufferTagsEqual(&bufHdr->tag, &newTag));
144 #ifdef LBDEBUG
145  fprintf(stderr, "LB ALLOC (%u,%d,%d) %d\n",
146  smgr->smgr_rlocator.locator.relNumber, forkNum, blockNum, -b - 1);
147 #endif
148  buf_state = pg_atomic_read_u32(&bufHdr->state);
149 
150  /* this part is equivalent to PinBuffer for a shared buffer */
151  if (LocalRefCount[b] == 0)
152  {
154  {
155  buf_state += BUF_USAGECOUNT_ONE;
156  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
157  }
158  }
159  LocalRefCount[b]++;
161  BufferDescriptorGetBuffer(bufHdr));
162  if (buf_state & BM_VALID)
163  *foundPtr = true;
164  else
165  {
166  /* Previous read attempt must have failed; try again */
167  *foundPtr = false;
168  }
169  return bufHdr;
170  }
171 
172 #ifdef LBDEBUG
173  fprintf(stderr, "LB ALLOC (%u,%d,%d) %d\n",
174  smgr->smgr_rlocator.locator.relNumber, forkNum, blockNum,
175  -nextFreeLocalBuf - 1);
176 #endif
177 
178  /*
179  * Need to get a new buffer. We use a clock sweep algorithm (essentially
180  * the same as what freelist.c does now...)
181  */
182  trycounter = NLocBuffer;
183  for (;;)
184  {
186 
187  if (++nextFreeLocalBuf >= NLocBuffer)
188  nextFreeLocalBuf = 0;
189 
190  bufHdr = GetLocalBufferDescriptor(b);
191 
192  if (LocalRefCount[b] == 0)
193  {
194  buf_state = pg_atomic_read_u32(&bufHdr->state);
195 
196  if (BUF_STATE_GET_USAGECOUNT(buf_state) > 0)
197  {
198  buf_state -= BUF_USAGECOUNT_ONE;
199  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
200  trycounter = NLocBuffer;
201  }
202  else
203  {
204  /* Found a usable buffer */
205  LocalRefCount[b]++;
207  BufferDescriptorGetBuffer(bufHdr));
208  break;
209  }
210  }
211  else if (--trycounter == 0)
212  ereport(ERROR,
213  (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
214  errmsg("no empty local buffer available")));
215  }
216 
217  /*
218  * this buffer is not referenced but it might still be dirty. if that's
219  * the case, write it out before reusing it!
220  */
221  if (buf_state & BM_DIRTY)
222  {
223  SMgrRelation oreln;
224  Page localpage = (char *) LocalBufHdrGetBlock(bufHdr);
225 
226  /* Find smgr relation for buffer */
227  oreln = smgropen(BufTagGetRelFileLocator(&bufHdr->tag), MyBackendId);
228 
229  PageSetChecksumInplace(localpage, bufHdr->tag.blockNum);
230 
231  /* And write... */
232  smgrwrite(oreln,
233  BufTagGetForkNum(&bufHdr->tag),
234  bufHdr->tag.blockNum,
235  localpage,
236  false);
237 
238  /* Mark not-dirty now in case we error out below */
239  buf_state &= ~BM_DIRTY;
240  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
241 
244  }
245 
246  /*
247  * lazy memory allocation: allocate space on first use of a buffer.
248  */
249  if (LocalBufHdrGetBlock(bufHdr) == NULL)
250  {
251  /* Set pointer for use by BufferGetBlock() macro */
253  }
254 
255  /*
256  * Update the hash table: remove old entry, if any, and make new one.
257  */
258  if (buf_state & BM_TAG_VALID)
259  {
260  hresult = (LocalBufferLookupEnt *)
261  hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL);
262  if (!hresult) /* shouldn't happen */
263  elog(ERROR, "local buffer hash table corrupted");
264  /* mark buffer invalid just in case hash insert fails */
265  ClearBufferTag(&bufHdr->tag);
266  buf_state &= ~(BM_VALID | BM_TAG_VALID);
267  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
269  }
270 
271  hresult = (LocalBufferLookupEnt *)
272  hash_search(LocalBufHash, &newTag, HASH_ENTER, &found);
273  if (found) /* shouldn't happen */
274  elog(ERROR, "local buffer hash table corrupted");
275  hresult->id = b;
276 
277  /*
278  * it's all ours now.
279  */
280  bufHdr->tag = newTag;
281  buf_state &= ~(BM_VALID | BM_DIRTY | BM_JUST_DIRTIED | BM_IO_ERROR);
282  buf_state |= BM_TAG_VALID;
283  buf_state &= ~BUF_USAGECOUNT_MASK;
284  buf_state += BUF_USAGECOUNT_ONE;
285  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
286 
287  *foundPtr = false;
288  return bufHdr;
289 }
#define BM_MAX_USAGE_COUNT
Definition: buf_internals.h:77
static void InitBufferTag(BufferTag *tag, const RelFileLocator *rlocator, ForkNumber forkNum, BlockNumber blockNum)
static bool BufferTagsEqual(const BufferTag *tag1, const BufferTag *tag2)
#define BM_DIRTY
Definition: buf_internals.h:60
#define BM_JUST_DIRTIED
Definition: buf_internals.h:65
#define BUF_STATE_GET_USAGECOUNT(state)
Definition: buf_internals.h:51
#define BUF_USAGECOUNT_ONE
Definition: buf_internals.h:45
#define BM_VALID
Definition: buf_internals.h:61
#define BM_IO_ERROR
Definition: buf_internals.h:64
static Buffer BufferDescriptorGetBuffer(const BufferDesc *bdesc)
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1539
Pointer Page
Definition: bufpage.h:78
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ereport(elevel,...)
Definition: elog.h:149
BufferUsage pgBufferUsage
Definition: instrument.c:20
int b
Definition: isn.c:70
#define LocalBufHdrGetBlock(bufHdr)
Definition: localbuf.c:39
static Block GetLocalBufferStorage(void)
Definition: localbuf.c:522
static void InitLocalBuffers(void)
Definition: localbuf.c:427
static int nextFreeLocalBuf
Definition: localbuf.c:48
@ IOOBJECT_TEMP_RELATION
Definition: pgstat.h:279
@ IOOP_EVICT
Definition: pgstat.h:296
@ IOOP_WRITE
Definition: pgstat.h:301
void pgstat_count_io_op(IOObject io_object, IOContext io_context, IOOp io_op)
Definition: pgstat_io.c:66
#define fprintf
Definition: port.h:242
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
void ResourceOwnerRememberBuffer(ResourceOwner owner, Buffer buffer)
Definition: resowner.c:963
void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void *buffer, bool skipFsync)
Definition: smgr.c:554
int64 local_blks_written
Definition: instrument.h:33
RelFileLocator locator
RelFileLocatorBackend smgr_rlocator
Definition: smgr.h:42

References Assert(), b, buftag::blockNum, BM_DIRTY, BM_IO_ERROR, BM_JUST_DIRTIED, BM_MAX_USAGE_COUNT, BM_TAG_VALID, BM_VALID, BUF_STATE_GET_USAGECOUNT, BUF_USAGECOUNT_MASK, BUF_USAGECOUNT_ONE, BufferDescriptorGetBuffer(), BufferTagsEqual(), BufTagGetForkNum(), BufTagGetRelFileLocator(), ClearBufferTag(), CurrentResourceOwner, elog(), ereport, errcode(), errmsg(), ERROR, fprintf, GetLocalBufferDescriptor(), GetLocalBufferStorage(), HASH_ENTER, HASH_FIND, HASH_REMOVE, hash_search(), LocalBufferLookupEnt::id, InitBufferTag(), InitLocalBuffers(), IOCONTEXT_NORMAL, IOOBJECT_TEMP_RELATION, IOOP_EVICT, IOOP_WRITE, BufferUsage::local_blks_written, LocalBufHash, LocalBufHdrGetBlock, LocalRefCount, RelFileLocatorBackend::locator, MyBackendId, nextFreeLocalBuf, NLocBuffer, PageSetChecksumInplace(), pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), pgBufferUsage, pgstat_count_io_op(), RelFileLocator::relNumber, ResourceOwnerRememberBuffer(), SMgrRelationData::smgr_rlocator, smgropen(), smgrwrite(), BufferDesc::state, and BufferDesc::tag.

Referenced by ReadBuffer_common().

◆ LockBufHdr()

uint32 LockBufHdr ( BufferDesc desc)

Definition at line 4822 of file bufmgr.c.

4823 {
4824  SpinDelayStatus delayStatus;
4825  uint32 old_buf_state;
4826 
4827  init_local_spin_delay(&delayStatus);
4828 
4829  while (true)
4830  {
4831  /* set BM_LOCKED flag */
4832  old_buf_state = pg_atomic_fetch_or_u32(&desc->state, BM_LOCKED);
4833  /* if it wasn't set before we're OK */
4834  if (!(old_buf_state & BM_LOCKED))
4835  break;
4836  perform_spin_delay(&delayStatus);
4837  }
4838  finish_spin_delay(&delayStatus);
4839  return old_buf_state | BM_LOCKED;
4840 }
static uint32 pg_atomic_fetch_or_u32(volatile pg_atomic_uint32 *ptr, uint32 or_)
Definition: atomics.h:367
#define BM_LOCKED
Definition: buf_internals.h:59
void perform_spin_delay(SpinDelayStatus *status)
Definition: s_lock.c:126
void finish_spin_delay(SpinDelayStatus *status)
Definition: s_lock.c:186
#define init_local_spin_delay(status)
Definition: s_lock.h:863

References BM_LOCKED, finish_spin_delay(), init_local_spin_delay, perform_spin_delay(), pg_atomic_fetch_or_u32(), and BufferDesc::state.

Referenced by AbortBufferIO(), apw_dump_now(), BufferAlloc(), BufferGetLSNAtomic(), BufferSync(), ConditionalLockBufferForCleanup(), DropDatabaseBuffers(), DropRelationBuffers(), DropRelationsAllBuffers(), FindAndDropRelationBuffers(), FlushBuffer(), FlushDatabaseBuffers(), FlushRelationBuffers(), FlushRelationsAllBuffers(), GetBufferFromRing(), InvalidateBuffer(), IsBufferCleanupOK(), LockBufferForCleanup(), MarkBufferDirtyHint(), pg_buffercache_pages(), ReadBuffer_common(), ReadRecentBuffer(), StartBufferIO(), StrategyGetBuffer(), SyncOneBuffer(), TerminateBufferIO(), UnlockBuffers(), UnpinBuffer(), and WaitIO().

◆ MarkLocalBufferDirty()

void MarkLocalBufferDirty ( Buffer  buffer)

Definition at line 296 of file localbuf.c.

297 {
298  int bufid;
299  BufferDesc *bufHdr;
300  uint32 buf_state;
301 
302  Assert(BufferIsLocal(buffer));
303 
304 #ifdef LBDEBUG
305  fprintf(stderr, "LB DIRTY %d\n", buffer);
306 #endif
307 
308  bufid = -(buffer + 1);
309 
310  Assert(LocalRefCount[bufid] > 0);
311 
312  bufHdr = GetLocalBufferDescriptor(bufid);
313 
314  buf_state = pg_atomic_read_u32(&bufHdr->state);
315 
316  if (!(buf_state & BM_DIRTY))
318 
319  buf_state |= BM_DIRTY;
320 
321  pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state);
322 }
#define BufferIsLocal(buffer)
Definition: buf.h:37
int64 local_blks_dirtied
Definition: instrument.h:32

References Assert(), BM_DIRTY, BufferIsLocal, fprintf, GetLocalBufferDescriptor(), BufferUsage::local_blks_dirtied, LocalRefCount, pg_atomic_read_u32(), pg_atomic_unlocked_write_u32(), pgBufferUsage, and BufferDesc::state.

Referenced by MarkBufferDirty(), and MarkBufferDirtyHint().

◆ PrefetchLocalBuffer()

PrefetchBufferResult PrefetchLocalBuffer ( SMgrRelation  smgr,
ForkNumber  forkNum,
BlockNumber  blockNum 
)

Definition at line 65 of file localbuf.c.

67 {
68  PrefetchBufferResult result = {InvalidBuffer, false};
69  BufferTag newTag; /* identity of requested block */
70  LocalBufferLookupEnt *hresult;
71 
72  InitBufferTag(&newTag, &smgr->smgr_rlocator.locator, forkNum, blockNum);
73 
74  /* Initialize local buffers if first request in this session */
75  if (LocalBufHash == NULL)
77 
78  /* See if the desired buffer already exists */
79  hresult = (LocalBufferLookupEnt *)
80  hash_search(LocalBufHash, &newTag, HASH_FIND, NULL);
81 
82  if (hresult)
83  {
84  /* Yes, so nothing to do */
85  result.recent_buffer = -hresult->id - 1;
86  }
87  else
88  {
89 #ifdef USE_PREFETCH
90  /* Not in buffers, so initiate prefetch */
91  smgrprefetch(smgr, forkNum, blockNum);
92  result.initiated_io = true;
93 #endif /* USE_PREFETCH */
94  }
95 
96  return result;
97 }
#define InvalidBuffer
Definition: buf.h:25
bool smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
Definition: smgr.c:518
Buffer recent_buffer
Definition: bufmgr.h:59

References HASH_FIND, hash_search(), LocalBufferLookupEnt::id, InitBufferTag(), PrefetchBufferResult::initiated_io, InitLocalBuffers(), InvalidBuffer, LocalBufHash, RelFileLocatorBackend::locator, PrefetchBufferResult::recent_buffer, SMgrRelationData::smgr_rlocator, and smgrprefetch().

Referenced by PrefetchBuffer().

◆ ScheduleBufferTagForWriteback()

void ScheduleBufferTagForWriteback ( WritebackContext context,
BufferTag tag 
)

Definition at line 4974 of file bufmgr.c.

4975 {
4976  PendingWriteback *pending;
4977 
4978  /*
4979  * Add buffer to the pending writeback array, unless writeback control is
4980  * disabled.
4981  */
4982  if (*context->max_pending > 0)
4983  {
4985 
4986  pending = &context->pending_writebacks[context->nr_pending++];
4987 
4988  pending->tag = *tag;
4989  }
4990 
4991  /*
4992  * Perform pending flushes if the writeback limit is exceeded. This
4993  * includes the case where previously an item has been added, but control
4994  * is now disabled.
4995  */
4996  if (context->nr_pending >= *context->max_pending)
4997  IssuePendingWritebacks(context);
4998 }
void IssuePendingWritebacks(WritebackContext *context)
Definition: bufmgr.c:5015
#define WRITEBACK_MAX_PENDING_FLUSHES

References Assert(), IssuePendingWritebacks(), WritebackContext::max_pending, WritebackContext::nr_pending, WritebackContext::pending_writebacks, PendingWriteback::tag, and WRITEBACK_MAX_PENDING_FLUSHES.

Referenced by BufferAlloc(), and SyncOneBuffer().

◆ StrategyFreeBuffer()

void StrategyFreeBuffer ( BufferDesc buf)

Definition at line 363 of file freelist.c.

364 {
366 
367  /*
368  * It is possible that we are told to put something in the freelist that
369  * is already in it; don't screw up the list if so.
370  */
371  if (buf->freeNext == FREENEXT_NOT_IN_LIST)
372  {
373  buf->freeNext = StrategyControl->firstFreeBuffer;
374  if (buf->freeNext < 0)
377  }
378 
380 }
#define FREENEXT_NOT_IN_LIST
static char * buf
Definition: pg_test_fsync.c:67
#define SpinLockRelease(lock)
Definition: spin.h:64
#define SpinLockAcquire(lock)
Definition: spin.h:62
slock_t buffer_strategy_lock
Definition: freelist.c:33

References buf, BufferStrategyControl::buffer_strategy_lock, BufferStrategyControl::firstFreeBuffer, FREENEXT_NOT_IN_LIST, BufferStrategyControl::lastFreeBuffer, SpinLockAcquire, SpinLockRelease, and StrategyControl.

Referenced by InvalidateBuffer().

◆ StrategyGetBuffer()

BufferDesc* StrategyGetBuffer ( BufferAccessStrategy  strategy,
uint32 buf_state,
bool from_ring 
)

Definition at line 196 of file freelist.c.

197 {
198  BufferDesc *buf;
199  int bgwprocno;
200  int trycounter;
201  uint32 local_buf_state; /* to avoid repeated (de-)referencing */
202 
203  *from_ring = false;
204 
205  /*
206  * If given a strategy object, see whether it can select a buffer. We
207  * assume strategy objects don't need buffer_strategy_lock.
208  */
209  if (strategy != NULL)
210  {
211  buf = GetBufferFromRing(strategy, buf_state);
212  if (buf != NULL)
213  {
214  *from_ring = true;
215  return buf;
216  }
217  }
218 
219  /*
220  * If asked, we need to waken the bgwriter. Since we don't want to rely on
221  * a spinlock for this we force a read from shared memory once, and then
222  * set the latch based on that value. We need to go through that length
223  * because otherwise bgwprocno might be reset while/after we check because
224  * the compiler might just reread from memory.
225  *
226  * This can possibly set the latch of the wrong process if the bgwriter
227  * dies in the wrong moment. But since PGPROC->procLatch is never
228  * deallocated the worst consequence of that is that we set the latch of
229  * some arbitrary process.
230  */
232  if (bgwprocno != -1)
233  {
234  /* reset bgwprocno first, before setting the latch */
236 
237  /*
238  * Not acquiring ProcArrayLock here which is slightly icky. It's
239  * actually fine because procLatch isn't ever freed, so we just can
240  * potentially set the wrong process' (or no process') latch.
241  */
242  SetLatch(&ProcGlobal->allProcs[bgwprocno].procLatch);
243  }
244 
245  /*
246  * We count buffer allocation requests so that the bgwriter can estimate
247  * the rate of buffer consumption. Note that buffers recycled by a
248  * strategy object are intentionally not counted here.
249  */
251 
252  /*
253  * First check, without acquiring the lock, whether there's buffers in the
254  * freelist. Since we otherwise don't require the spinlock in every
255  * StrategyGetBuffer() invocation, it'd be sad to acquire it here -
256  * uselessly in most cases. That obviously leaves a race where a buffer is
257  * put on the freelist but we don't see the store yet - but that's pretty
258  * harmless, it'll just get used during the next buffer acquisition.
259  *
260  * If there's buffers on the freelist, acquire the spinlock to pop one
261  * buffer of the freelist. Then check whether that buffer is usable and
262  * repeat if not.
263  *
264  * Note that the freeNext fields are considered to be protected by the
265  * buffer_strategy_lock not the individual buffer spinlocks, so it's OK to
266  * manipulate them without holding the spinlock.
267  */
269  {
270  while (true)
271  {
272  /* Acquire the spinlock to remove element from the freelist */
274 
276  {
278  break;
279  }
280 
282  Assert(buf->freeNext != FREENEXT_NOT_IN_LIST);
283 
284  /* Unconditionally remove buffer from freelist */
285  StrategyControl->firstFreeBuffer = buf->freeNext;
286  buf->freeNext = FREENEXT_NOT_IN_LIST;
287 
288  /*
289  * Release the lock so someone else can access the freelist while
290  * we check out this buffer.
291  */
293 
294  /*
295  * If the buffer is pinned or has a nonzero usage_count, we cannot
296  * use it; discard it and retry. (This can only happen if VACUUM
297  * put a valid buffer in the freelist and then someone else used
298  * it before we got to it. It's probably impossible altogether as
299  * of 8.3, but we'd better check anyway.)
300  */
301  local_buf_state = LockBufHdr(buf);
302  if (BUF_STATE_GET_REFCOUNT(local_buf_state) == 0
303  && BUF_STATE_GET_USAGECOUNT(local_buf_state) == 0)
304  {
305  if (strategy != NULL)
306  AddBufferToRing(strategy, buf);
307  *buf_state = local_buf_state;
308  return buf;
309  }
310  UnlockBufHdr(buf, local_buf_state);
311  }
312  }
313 
314  /* Nothing on the freelist, so run the "clock sweep" algorithm */
315  trycounter = NBuffers;
316  for (;;)
317  {
319 
320  /*
321  * If the buffer is pinned or has a nonzero usage_count, we cannot use
322  * it; decrement the usage_count (unless pinned) and keep scanning.
323  */
324  local_buf_state = LockBufHdr(buf);
325 
326  if (BUF_STATE_GET_REFCOUNT(local_buf_state) == 0)
327  {
328  if (BUF_STATE_GET_USAGECOUNT(local_buf_state) != 0)
329  {
330  local_buf_state -= BUF_USAGECOUNT_ONE;
331 
332  trycounter = NBuffers;
333  }
334  else
335  {
336  /* Found a usable buffer */
337  if (strategy != NULL)
338  AddBufferToRing(strategy, buf);
339  *buf_state = local_buf_state;
340  return buf;
341  }
342  }
343  else if (--trycounter == 0)
344  {
345  /*
346  * We've scanned all the buffers without making any state changes,
347  * so all the buffers are pinned (or were when we looked at them).
348  * We could hope that someone will free one eventually, but it's
349  * probably better to fail than to risk getting stuck in an
350  * infinite loop.
351  */
352  UnlockBufHdr(buf, local_buf_state);
353  elog(ERROR, "no unpinned buffers available");
354  }
355  UnlockBufHdr(buf, local_buf_state);
356  }
357 }
static uint32 pg_atomic_fetch_add_u32(volatile pg_atomic_uint32 *ptr, int32 add_)
Definition: atomics.h:323
static BufferDesc * GetBufferDescriptor(uint32 id)
static void UnlockBufHdr(BufferDesc *desc, uint32 buf_state)
#define BUF_STATE_GET_REFCOUNT(state)
Definition: buf_internals.h:50
uint32 LockBufHdr(BufferDesc *desc)
Definition: bufmgr.c:4822
static uint32 ClockSweepTick(void)
Definition: freelist.c:108
static void AddBufferToRing(BufferAccessStrategy strategy, BufferDesc *buf)
Definition: freelist.c:663
#define INT_ACCESS_ONCE(var)
Definition: freelist.c:24
static BufferDesc * GetBufferFromRing(BufferAccessStrategy strategy, uint32 *buf_state)
Definition: freelist.c:610
int NBuffers
Definition: globals.c:136
void SetLatch(Latch *latch)
Definition: latch.c:607
PROC_HDR * ProcGlobal
Definition: proc.c:78
pg_atomic_uint32 numBufferAllocs
Definition: freelist.c:55
Latch procLatch
Definition: proc.h:170
PGPROC * allProcs
Definition: proc.h:362

References AddBufferToRing(), PROC_HDR::allProcs, Assert(), BufferStrategyControl::bgwprocno, buf, BUF_STATE_GET_REFCOUNT, BUF_STATE_GET_USAGECOUNT, BUF_USAGECOUNT_ONE, BufferStrategyControl::buffer_strategy_lock, ClockSweepTick(), elog(), ERROR, BufferStrategyControl::firstFreeBuffer, FREENEXT_NOT_IN_LIST, GetBufferDescriptor(), GetBufferFromRing(), INT_ACCESS_ONCE, LockBufHdr(), NBuffers, BufferStrategyControl::numBufferAllocs, pg_atomic_fetch_add_u32(), ProcGlobal, PGPROC::procLatch, SetLatch(), SpinLockAcquire, SpinLockRelease, StrategyControl, and UnlockBufHdr().

Referenced by BufferAlloc().

◆ StrategyInitialize()

void StrategyInitialize ( bool  init)

Definition at line 474 of file freelist.c.

475 {
476  bool found;
477 
478  /*
479  * Initialize the shared buffer lookup hashtable.
480  *
481  * Since we can't tolerate running out of lookup table entries, we must be
482  * sure to specify an adequate table size here. The maximum steady-state
483  * usage is of course NBuffers entries, but BufferAlloc() tries to insert
484  * a new entry before deleting the old. In principle this could be
485  * happening in each partition concurrently, so we could need as many as
486  * NBuffers + NUM_BUFFER_PARTITIONS entries.
487  */
489 
490  /*
491  * Get or create the shared strategy control block
492  */
494  ShmemInitStruct("Buffer Strategy Status",
495  sizeof(BufferStrategyControl),
496  &found);
497 
498  if (!found)
499  {
500  /*
501  * Only done once, usually in postmaster
502  */
503  Assert(init);
504 
506 
507  /*
508  * Grab the whole linked list of free buffers for our strategy. We
509  * assume it was previously set up by InitBufferPool().
510  */
513 
514  /* Initialize the clock sweep pointer */
516 
517  /* Clear statistics */
520 
521  /* No pending notification */
523  }
524  else
525  Assert(!init);
526 }
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:218
void InitBufTable(int size)
Definition: buf_table.c:52
int init
Definition: isn.c:75
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:396
#define SpinLockInit(lock)
Definition: spin.h:60
pg_atomic_uint32 nextVictimBuffer
Definition: freelist.c:40

References Assert(), BufferStrategyControl::bgwprocno, BufferStrategyControl::buffer_strategy_lock, BufferStrategyControl::completePasses, BufferStrategyControl::firstFreeBuffer, init, InitBufTable(), BufferStrategyControl::lastFreeBuffer, NBuffers, BufferStrategyControl::nextVictimBuffer, NUM_BUFFER_PARTITIONS, BufferStrategyControl::numBufferAllocs, pg_atomic_init_u32(), ShmemInitStruct(), SpinLockInit, and StrategyControl.

Referenced by InitBufferPool().

◆ StrategyNotifyBgWriter()

void StrategyNotifyBgWriter ( int  bgwprocno)

Definition at line 431 of file freelist.c.

432 {
433  /*
434  * We acquire buffer_strategy_lock just to ensure that the store appears
435  * atomic to StrategyGetBuffer. The bgwriter should call this rather
436  * infrequently, so there's no performance penalty from being safe.
437  */
439  StrategyControl->bgwprocno = bgwprocno;
441 }

References BufferStrategyControl::bgwprocno, BufferStrategyControl::buffer_strategy_lock, SpinLockAcquire, SpinLockRelease, and StrategyControl.

Referenced by BackgroundWriterMain().

◆ StrategyRejectBuffer()

bool StrategyRejectBuffer ( BufferAccessStrategy  strategy,
BufferDesc buf,
bool  from_ring 
)

Definition at line 713 of file freelist.c.

714 {
715  /* We only do this in bulkread mode */
716  if (strategy->btype != BAS_BULKREAD)
717  return false;
718 
719  /* Don't muck with behavior of normal buffer-replacement strategy */
720  if (!from_ring ||
721  strategy->buffers[strategy->current] != BufferDescriptorGetBuffer(buf))
722  return false;
723 
724  /*
725  * Remove the dirty buffer from the ring; necessary to prevent infinite
726  * loop if all ring members are dirty.
727  */
728  strategy->buffers[strategy->current] = InvalidBuffer;
729 
730  return true;
731 }
BufferAccessStrategyType btype
Definition: freelist.c:75
Buffer buffers[FLEXIBLE_ARRAY_MEMBER]
Definition: freelist.c:91

References BAS_BULKREAD, BufferAccessStrategyData::btype, buf, BufferDescriptorGetBuffer(), BufferAccessStrategyData::buffers, BufferAccessStrategyData::current, and InvalidBuffer.

Referenced by BufferAlloc().

◆ StrategyShmemSize()

Size StrategyShmemSize ( void  )

Definition at line 453 of file freelist.c.

454 {
455  Size size = 0;
456 
457  /* size of lookup hash table ... see comment in StrategyInitialize */
459 
460  /* size of the shared replacement strategy control block */
461  size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl)));
462 
463  return size;
464 }
Size BufTableShmemSize(int size)
Definition: buf_table.c:42
#define MAXALIGN(LEN)
Definition: c.h:795
Size add_size(Size s1, Size s2)
Definition: shmem.c:502

References add_size(), BufTableShmemSize(), MAXALIGN, NBuffers, and NUM_BUFFER_PARTITIONS.

Referenced by BufferShmemSize().

◆ StrategySyncStart()

int StrategySyncStart ( uint32 complete_passes,
uint32 num_buf_alloc 
)

Definition at line 394 of file freelist.c.

395 {
396  uint32 nextVictimBuffer;
397  int result;
398 
401  result = nextVictimBuffer % NBuffers;
402 
403  if (complete_passes)
404  {
405  *complete_passes = StrategyControl->completePasses;
406 
407  /*
408  * Additionally add the number of wraparounds that happened before
409  * completePasses could be incremented. C.f. ClockSweepTick().
410  */
411  *complete_passes += nextVictimBuffer / NBuffers;
412  }
413 
414  if (num_buf_alloc)
415  {
417  }
419  return result;
420 }
static uint32 pg_atomic_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 newval)
Definition: atomics.h:287

References BufferStrategyControl::buffer_strategy_lock, BufferStrategyControl::completePasses, NBuffers, BufferStrategyControl::nextVictimBuffer, BufferStrategyControl::numBufferAllocs, pg_atomic_exchange_u32(), pg_atomic_read_u32(), SpinLockAcquire, SpinLockRelease, and StrategyControl.

Referenced by BgBufferSync().

◆ UnlockBufHdr()

◆ WritebackContextInit()

void WritebackContextInit ( WritebackContext context,
int *  max_pending 
)

Definition at line 4962 of file bufmgr.c.

4963 {
4964  Assert(*max_pending <= WRITEBACK_MAX_PENDING_FLUSHES);
4965 
4966  context->max_pending = max_pending;
4967  context->nr_pending = 0;
4968 }

References Assert(), WritebackContext::max_pending, WritebackContext::nr_pending, and WRITEBACK_MAX_PENDING_FLUSHES.

Referenced by BackgroundWriterMain(), BufferSync(), and InitBufferPool().

Variable Documentation

◆ BackendWritebackContext

PGDLLIMPORT WritebackContext BackendWritebackContext
extern

Definition at line 24 of file buf_init.c.

Referenced by BufferAlloc(), and InitBufferPool().

◆ BufferDescriptors

PGDLLIMPORT BufferDescPadded* BufferDescriptors
extern

Definition at line 21 of file buf_init.c.

Referenced by GetBufferDescriptor(), and InitBufferPool().

◆ BufferIOCVArray

Definition at line 23 of file buf_init.c.

Referenced by BufferDescriptorGetIOCV(), and InitBufferPool().

◆ CkptBufferIds

PGDLLIMPORT CkptSortItem* CkptBufferIds
extern

Definition at line 25 of file buf_init.c.

Referenced by BufferSync(), and InitBufferPool().

◆ LocalBufferDescriptors

PGDLLIMPORT BufferDesc* LocalBufferDescriptors
extern

Definition at line 44 of file localbuf.c.

Referenced by GetLocalBufferDescriptor(), and InitLocalBuffers().