#include "storage/buf_internals.h"
#include "storage/bufmgr.h"
#include "storage/proclist.h"
+#include "storage/shmem.h"
+#include "storage/subsystems.h"
BufferDescPadded *BufferDescriptors;
char *BufferBlocks;
WritebackContext BackendWritebackContext;
CkptSortItem *CkptBufferIds;
+static void BufferManagerShmemRequest(void *arg);
+static void BufferManagerShmemInit(void *arg);
+static void BufferManagerShmemAttach(void *arg);
+
+const ShmemCallbacks BufferManagerShmemCallbacks = {
+ .request_fn = BufferManagerShmemRequest,
+ .init_fn = BufferManagerShmemInit,
+ .attach_fn = BufferManagerShmemAttach,
+};
/*
* Data Structures:
/*
- * Initialize shared buffer pool
- *
- * This is called once during shared-memory initialization (either in the
- * postmaster, or in a standalone backend).
+ * Register shared memory area for the buffer pool.
*/
-void
-BufferManagerShmemInit(void)
+static void
+BufferManagerShmemRequest(void *arg)
{
- bool foundBufs,
- foundDescs,
- foundIOCV,
- foundBufCkpt;
-
+ ShmemRequestStruct(.name = "Buffer Descriptors",
+ .size = NBuffers * sizeof(BufferDescPadded),
/* Align descriptors to a cacheline boundary. */
- BufferDescriptors = (BufferDescPadded *)
- ShmemInitStruct("Buffer Descriptors",
- NBuffers * sizeof(BufferDescPadded),
- &foundDescs);
+ .alignment = PG_CACHE_LINE_SIZE,
+ .ptr = (void **) &BufferDescriptors,
+ );
+ ShmemRequestStruct(.name = "Buffer Blocks",
+ .size = NBuffers * (Size) BLCKSZ,
/* Align buffer pool on IO page size boundary. */
- BufferBlocks = (char *)
- TYPEALIGN(PG_IO_ALIGN_SIZE,
- ShmemInitStruct("Buffer Blocks",
- NBuffers * (Size) BLCKSZ + PG_IO_ALIGN_SIZE,
- &foundBufs));
-
- /* Align condition variables to cacheline boundary. */
- BufferIOCVArray = (ConditionVariableMinimallyPadded *)
- ShmemInitStruct("Buffer IO Condition Variables",
- NBuffers * sizeof(ConditionVariableMinimallyPadded),
- &foundIOCV);
+ .alignment = PG_IO_ALIGN_SIZE,
+ .ptr = (void **) &BufferBlocks,
+ );
+
+ ShmemRequestStruct(.name = "Buffer IO Condition Variables",
+ .size = NBuffers * sizeof(ConditionVariableMinimallyPadded),
+ /* Align descriptors to a cacheline boundary. */
+ .alignment = PG_CACHE_LINE_SIZE,
+ .ptr = (void **) &BufferIOCVArray,
+ );
/*
* The array used to sort to-be-checkpointed buffer ids is located in
* the checkpointer is restarted, memory allocation failures would be
* painful.
*/
- CkptBufferIds = (CkptSortItem *)
- ShmemInitStruct("Checkpoint BufferIds",
- NBuffers * sizeof(CkptSortItem), &foundBufCkpt);
+ ShmemRequestStruct(.name = "Checkpoint BufferIds",
+ .size = NBuffers * sizeof(CkptSortItem),
+ .ptr = (void **) &CkptBufferIds,
+ );
+}
- if (foundDescs || foundBufs || foundIOCV || foundBufCkpt)
- {
- /* should find all of these, or none of them */
- Assert(foundDescs && foundBufs && foundIOCV && foundBufCkpt);
- /* note: this path is only taken in EXEC_BACKEND case */
- }
- else
+/*
+ * Initialize shared buffer pool
+ *
+ * This is called once during shared-memory initialization (either in the
+ * postmaster, or in a standalone backend).
+ */
+static void
+BufferManagerShmemInit(void *arg)
+{
+ /*
+ * Initialize all the buffer headers.
+ */
+ for (int i = 0; i < NBuffers; i++)
{
- int i;
+ BufferDesc *buf = GetBufferDescriptor(i);
- /*
- * Initialize all the buffer headers.
- */
- for (i = 0; i < NBuffers; i++)
- {
- BufferDesc *buf = GetBufferDescriptor(i);
+ ClearBufferTag(&buf->tag);
- ClearBufferTag(&buf->tag);
+ pg_atomic_init_u64(&buf->state, 0);
+ buf->wait_backend_pgprocno = INVALID_PROC_NUMBER;
- pg_atomic_init_u64(&buf->state, 0);
- buf->wait_backend_pgprocno = INVALID_PROC_NUMBER;
+ buf->buf_id = i;
- buf->buf_id = i;
+ pgaio_wref_clear(&buf->io_wref);
- pgaio_wref_clear(&buf->io_wref);
-
- proclist_init(&buf->lock_waiters);
- ConditionVariableInit(BufferDescriptorGetIOCV(buf));
- }
+ proclist_init(&buf->lock_waiters);
+ ConditionVariableInit(BufferDescriptorGetIOCV(buf));
}
- /* Init other shared buffer-management stuff */
- StrategyInitialize(!foundDescs);
-
/* Initialize per-backend file flush context */
WritebackContextInit(&BackendWritebackContext,
&backend_flush_after);
}
-/*
- * BufferManagerShmemSize
- *
- * compute the size of shared memory for the buffer pool including
- * data pages, buffer descriptors, hash tables, etc.
- */
-Size
-BufferManagerShmemSize(void)
+static void
+BufferManagerShmemAttach(void *arg)
{
- Size size = 0;
-
- /* size of buffer descriptors */
- size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded)));
- /* to allow aligning buffer descriptors */
- size = add_size(size, PG_CACHE_LINE_SIZE);
-
- /* size of data pages, plus alignment padding */
- size = add_size(size, PG_IO_ALIGN_SIZE);
- size = add_size(size, mul_size(NBuffers, BLCKSZ));
-
- /* size of stuff controlled by freelist.c */
- size = add_size(size, StrategyShmemSize());
-
- /* size of I/O condition variables */
- size = add_size(size, mul_size(NBuffers,
- sizeof(ConditionVariableMinimallyPadded)));
- /* to allow aligning the above */
- size = add_size(size, PG_CACHE_LINE_SIZE);
-
- /* size of checkpoint sort array in bufmgr.c */
- size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem)));
-
- return size;
+ /* Initialize per-backend file flush context */
+ WritebackContextInit(&BackendWritebackContext,
+ &backend_flush_after);
}
#include "postgres.h"
#include "storage/buf_internals.h"
+#include "storage/subsystems.h"
/* entry for buffer lookup hashtable */
typedef struct
static HTAB *SharedBufHash;
+static void BufTableShmemRequest(void *arg);
-/*
- * Estimate space needed for mapping hashtable
- * size is the desired hash table size (possibly more than NBuffers)
- */
-Size
-BufTableShmemSize(int size)
-{
- return hash_estimate_size(size, sizeof(BufferLookupEnt));
-}
+const ShmemCallbacks BufTableShmemCallbacks = {
+ .request_fn = BufTableShmemRequest,
+ /* no special initialization needed, the hash table will start empty */
+};
/*
- * Initialize shmem hash table for mapping buffers
+ * Register shmem hash table for mapping buffers.
* size is the desired hash table size (possibly more than NBuffers)
*/
void
-InitBufTable(int size)
+BufTableShmemRequest(void *arg)
{
- HASHCTL info;
-
- /* assume no locking is needed yet */
-
- /* BufferTag maps to Buffer */
- info.keysize = sizeof(BufferTag);
- info.entrysize = sizeof(BufferLookupEnt);
- info.num_partitions = NUM_BUFFER_PARTITIONS;
-
- SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
- size,
- &info,
- HASH_ELEM | HASH_BLOBS | HASH_PARTITION | HASH_FIXED_SIZE);
+ int size;
+
+ /*
+ * Request the shared buffer lookup hashtable.
+ *
+ * Since we can't tolerate running out of lookup table entries, we must be
+ * sure to specify an adequate table size here. The maximum steady-state
+ * usage is of course NBuffers entries, but BufferAlloc() tries to insert
+ * a new entry before deleting the old. In principle this could be
+ * happening in each partition concurrently, so we could need as many as
+ * NBuffers + NUM_BUFFER_PARTITIONS entries.
+ */
+ size = NBuffers + NUM_BUFFER_PARTITIONS;
+
+ ShmemRequestHash(.name = "Shared Buffer Lookup Table",
+ .nelems = size,
+ .ptr = &SharedBufHash,
+ .hash_info.keysize = sizeof(BufferTag),
+ .hash_info.entrysize = sizeof(BufferLookupEnt),
+ .hash_info.num_partitions = NUM_BUFFER_PARTITIONS,
+ .hash_flags = HASH_ELEM | HASH_BLOBS | HASH_PARTITION | HASH_FIXED_SIZE,
+ );
}
/*
#include "storage/buf_internals.h"
#include "storage/bufmgr.h"
#include "storage/proc.h"
+#include "storage/shmem.h"
+#include "storage/subsystems.h"
#define INT_ACCESS_ONCE(var) ((int)(*((volatile int *)&(var))))
/* Pointers to shared state */
static BufferStrategyControl *StrategyControl = NULL;
+static void StrategyCtlShmemRequest(void *arg);
+static void StrategyCtlShmemInit(void *arg);
+
+const ShmemCallbacks StrategyCtlShmemCallbacks = {
+ .request_fn = StrategyCtlShmemRequest,
+ .init_fn = StrategyCtlShmemInit,
+};
+
/*
* Private (non-shared) state for managing a ring of shared buffers to re-use.
* This is currently the only kind of BufferAccessStrategy object, but someday
/*
- * StrategyShmemSize
- *
- * estimate the size of shared memory used by the freelist-related structures.
- *
- * Note: for somewhat historical reasons, the buffer lookup hashtable size
- * is also determined here.
+ * StrategyCtlShmemRequest -- request shared memory for the buffer
+ * cache replacement strategy.
*/
-Size
-StrategyShmemSize(void)
+static void
+StrategyCtlShmemRequest(void *arg)
{
- Size size = 0;
-
- /* size of lookup hash table ... see comment in StrategyInitialize */
- size = add_size(size, BufTableShmemSize(NBuffers + NUM_BUFFER_PARTITIONS));
-
- /* size of the shared replacement strategy control block */
- size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl)));
-
- return size;
+ ShmemRequestStruct(.name = "Buffer Strategy Status",
+ .size = sizeof(BufferStrategyControl),
+ .ptr = (void **) &StrategyControl
+ );
}
/*
- * StrategyInitialize -- initialize the buffer cache replacement
- * strategy.
- *
- * Assumes: All of the buffers are already built into a linked list.
- * Only called by postmaster and only during initialization.
+ * StrategyCtlShmemInit -- initialize the buffer cache replacement strategy.
*/
-void
-StrategyInitialize(bool init)
+static void
+StrategyCtlShmemInit(void *arg)
{
- bool found;
+ SpinLockInit(&StrategyControl->buffer_strategy_lock);
- /*
- * Initialize the shared buffer lookup hashtable.
- *
- * Since we can't tolerate running out of lookup table entries, we must be
- * sure to specify an adequate table size here. The maximum steady-state
- * usage is of course NBuffers entries, but BufferAlloc() tries to insert
- * a new entry before deleting the old. In principle this could be
- * happening in each partition concurrently, so we could need as many as
- * NBuffers + NUM_BUFFER_PARTITIONS entries.
- */
- InitBufTable(NBuffers + NUM_BUFFER_PARTITIONS);
-
- /*
- * Get or create the shared strategy control block
- */
- StrategyControl = (BufferStrategyControl *)
- ShmemInitStruct("Buffer Strategy Status",
- sizeof(BufferStrategyControl),
- &found);
-
- if (!found)
- {
- /*
- * Only done once, usually in postmaster
- */
- Assert(init);
-
- SpinLockInit(&StrategyControl->buffer_strategy_lock);
+ /* Initialize the clock-sweep pointer */
+ pg_atomic_init_u32(&StrategyControl->nextVictimBuffer, 0);
- /* Initialize the clock-sweep pointer */
- pg_atomic_init_u32(&StrategyControl->nextVictimBuffer, 0);
+ /* Clear statistics */
+ StrategyControl->completePasses = 0;
+ pg_atomic_init_u32(&StrategyControl->numBufferAllocs, 0);
- /* Clear statistics */
- StrategyControl->completePasses = 0;
- pg_atomic_init_u32(&StrategyControl->numBufferAllocs, 0);
-
- /* No pending notification */
- StrategyControl->bgwprocno = -1;
- }
- else
- Assert(!init);
+ /* No pending notification */
+ StrategyControl->bgwprocno = -1;
}
#include "replication/walreceiver.h"
#include "replication/walsender.h"
#include "storage/aio_subsys.h"
-#include "storage/bufmgr.h"
#include "storage/dsm.h"
#include "storage/ipc.h"
#include "storage/pg_shmem.h"
size = add_size(size, ShmemGetRequestedSize());
/* legacy subsystems */
- size = add_size(size, BufferManagerShmemSize());
size = add_size(size, LockManagerShmemSize());
size = add_size(size, XLogPrefetchShmemSize());
size = add_size(size, XLOGShmemSize());
XLOGShmemInit();
XLogPrefetchShmemInit();
XLogRecoveryShmemInit();
- BufferManagerShmemInit();
/*
* Set up lock manager
extern int StrategySyncStart(uint32 *complete_passes, uint32 *num_buf_alloc);
extern void StrategyNotifyBgWriter(int bgwprocno);
-extern Size StrategyShmemSize(void);
-extern void StrategyInitialize(bool init);
-
/* buf_table.c */
-extern Size BufTableShmemSize(int size);
-extern void InitBufTable(int size);
extern uint32 BufTableHashCode(BufferTag *tagPtr);
extern int BufTableLookup(BufferTag *tagPtr, uint32 hashcode);
extern int BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id);
int32 *buffers_already_dirty,
int32 *buffers_skipped);
-/* in buf_init.c */
-extern void BufferManagerShmemInit(void);
-extern Size BufferManagerShmemSize(void);
-
/* in localbuf.c */
extern void AtProcExit_LocalBuffers(void);
PG_SHMEM_SUBSYSTEM(CommitTsShmemCallbacks)
PG_SHMEM_SUBSYSTEM(SUBTRANSShmemCallbacks)
PG_SHMEM_SUBSYSTEM(MultiXactShmemCallbacks)
+PG_SHMEM_SUBSYSTEM(BufferManagerShmemCallbacks)
+PG_SHMEM_SUBSYSTEM(StrategyCtlShmemCallbacks)
+PG_SHMEM_SUBSYSTEM(BufTableShmemCallbacks)
/* predicate lock manager */
PG_SHMEM_SUBSYSTEM(PredicateLockShmemCallbacks)