]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Convert buffer manager to use the new shmem allocation functions
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Sun, 5 Apr 2026 23:13:08 +0000 (02:13 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Sun, 5 Apr 2026 23:13:08 +0000 (02:13 +0300)
This rectifies the initialization functions a little, making the
"buffer strategy" stuff in freelist.c and buffer mapping hash table in
buf_init.c top-level "subsystems" of their own, registered directly in
subsystemlist.h. Previously they were called indirectly from
BufferManagerShmemInit() and BufferManagerShmemSize()

Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Reviewed-by: Matthias van de Meent <boekewurm+postgres@gmail.com>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://www.postgresql.org/message-id/CAExHW5vM1bneLYfg0wGeAa=52UiJ3z4vKd3AJ72X8Fw6k3KKrg@mail.gmail.com

src/backend/storage/buffer/buf_init.c
src/backend/storage/buffer/buf_table.c
src/backend/storage/buffer/freelist.c
src/backend/storage/ipc/ipci.c
src/include/storage/buf_internals.h
src/include/storage/bufmgr.h
src/include/storage/subsystemlist.h

index c0c223b2e32909d3c8a170e84a78178efb868400..1407c930c56af65ce3337f2957c19f14f184e0ab 100644 (file)
@@ -18,6 +18,8 @@
 #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;
@@ -25,6 +27,15 @@ ConditionVariableMinimallyPadded *BufferIOCVArray;
 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:
@@ -60,37 +71,31 @@ CkptSortItem *CkptBufferIds;
 
 
 /*
- * 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
@@ -99,80 +104,50 @@ BufferManagerShmemInit(void)
         * 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);
 }
index d04ef74b850cda94978522f53f83afbb82e05032..347bf267d73feb04ef9ef74ae70af3f24bfd6b4d 100644 (file)
@@ -22,6 +22,7 @@
 #include "postgres.h"
 
 #include "storage/buf_internals.h"
+#include "storage/subsystems.h"
 
 /* entry for buffer lookup hashtable */
 typedef struct
@@ -32,37 +33,42 @@ 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,
+               );
 }
 
 /*
index b76878361881729555f93ad05e3a6207009aeaef..fdb5bad7910a2cee63916b2a6b059adf66b1f5ce 100644 (file)
@@ -20,6 +20,8 @@
 #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))))
 
@@ -56,6 +58,14 @@ typedef struct
 /* 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
@@ -369,80 +379,35 @@ StrategyNotifyBgWriter(int bgwprocno)
 
 
 /*
- * 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;
 }
 
 
index a510c928daaa99faf3485834c96c31efa6685b20..f64c1d59fa3fe7d1bb475133cc711c3d600da8d9 100644 (file)
@@ -39,7 +39,6 @@
 #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"
@@ -99,7 +98,6 @@ CalculateShmemSize(void)
        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());
@@ -263,7 +261,6 @@ CreateOrAttachShmemStructs(void)
        XLOGShmemInit();
        XLogPrefetchShmemInit();
        XLogRecoveryShmemInit();
-       BufferManagerShmemInit();
 
        /*
         * Set up lock manager
index ad1b7b2216a4d9d372ba82554ddd4eeca1a04674..89615a254a3edc94164f888a41e082da9c4ff712 100644 (file)
@@ -587,12 +587,7 @@ extern bool StrategyRejectBuffer(BufferAccessStrategy strategy,
 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);
index aa61a39d9e65ba19c38ad01434da19d46b0c50ce..6837b35fc6d0b8a2f016f8604e43ba3415c8ae40 100644 (file)
@@ -371,10 +371,6 @@ extern void MarkDirtyAllUnpinnedBuffers(int32 *buffers_dirtied,
                                                                                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);
 
index b438794d46d9560f629dc8beff629dc46cb9b162..d8e11756a618b8191c07777869fdf47067d37c69 100644 (file)
@@ -36,6 +36,9 @@ PG_SHMEM_SUBSYSTEM(CLOGShmemCallbacks)
 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)