Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * buf_init.c
4 : : * buffer manager initialization routines
5 : : *
6 : : * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 : : * Portions Copyright (c) 1994, Regents of the University of California
8 : : *
9 : : *
10 : : * IDENTIFICATION
11 : : * src/backend/storage/buffer/buf_init.c
12 : : *
13 : : *-------------------------------------------------------------------------
14 : : */
15 : : #include "postgres.h"
16 : :
17 : : #include "storage/aio.h"
18 : : #include "storage/buf_internals.h"
19 : : #include "storage/bufmgr.h"
20 : : #include "storage/proclist.h"
21 : : #include "storage/shmem.h"
22 : : #include "storage/subsystems.h"
23 : :
24 : : BufferDescPadded *BufferDescriptors;
25 : : char *BufferBlocks;
26 : : ConditionVariableMinimallyPadded *BufferIOCVArray;
27 : : WritebackContext BackendWritebackContext;
28 : : CkptSortItem *CkptBufferIds;
29 : :
30 : : static void BufferManagerShmemRequest(void *arg);
31 : : static void BufferManagerShmemInit(void *arg);
32 : : static void BufferManagerShmemAttach(void *arg);
33 : :
34 : : const ShmemCallbacks BufferManagerShmemCallbacks = {
35 : : .request_fn = BufferManagerShmemRequest,
36 : : .init_fn = BufferManagerShmemInit,
37 : : .attach_fn = BufferManagerShmemAttach,
38 : : };
39 : :
40 : : /*
41 : : * Data Structures:
42 : : * buffers live in a freelist and a lookup data structure.
43 : : *
44 : : *
45 : : * Buffer Lookup:
46 : : * Two important notes. First, the buffer has to be
47 : : * available for lookup BEFORE an IO begins. Otherwise
48 : : * a second process trying to read the buffer will
49 : : * allocate its own copy and the buffer pool will
50 : : * become inconsistent.
51 : : *
52 : : * Buffer Replacement:
53 : : * see freelist.c. A buffer cannot be replaced while in
54 : : * use either by data manager or during IO.
55 : : *
56 : : *
57 : : * Synchronization/Locking:
58 : : *
59 : : * IO_IN_PROGRESS -- this is a flag in the buffer descriptor.
60 : : * It must be set when an IO is initiated and cleared at
61 : : * the end of the IO. It is there to make sure that one
62 : : * process doesn't start to use a buffer while another is
63 : : * faulting it in. see WaitIO and related routines.
64 : : *
65 : : * refcount -- Counts the number of processes holding pins on a buffer.
66 : : * A buffer is pinned during IO and immediately after a BufferAlloc().
67 : : * Pins must be released before end of transaction. For efficiency the
68 : : * shared refcount isn't increased if an individual backend pins a buffer
69 : : * multiple times. Check the PrivateRefCount infrastructure in bufmgr.c.
70 : : */
71 : :
72 : :
73 : : /*
74 : : * Register shared memory area for the buffer pool.
75 : : */
76 : : static void
29 heikki.linnakangas@i 77 :GNC 1244 : BufferManagerShmemRequest(void *arg)
78 : : {
79 : 1244 : ShmemRequestStruct(.name = "Buffer Descriptors",
80 : : .size = NBuffers * sizeof(BufferDescPadded),
81 : : /* Align descriptors to a cacheline boundary. */
82 : : .alignment = PG_CACHE_LINE_SIZE,
83 : : .ptr = (void **) &BufferDescriptors,
84 : : );
85 : :
86 : 1244 : ShmemRequestStruct(.name = "Buffer Blocks",
87 : : .size = NBuffers * (Size) BLCKSZ,
88 : : /* Align buffer pool on IO page size boundary. */
89 : : .alignment = PG_IO_ALIGN_SIZE,
90 : : .ptr = (void **) &BufferBlocks,
91 : : );
92 : :
93 : 1244 : ShmemRequestStruct(.name = "Buffer IO Condition Variables",
94 : : .size = NBuffers * sizeof(ConditionVariableMinimallyPadded),
95 : : /* Align descriptors to a cacheline boundary. */
96 : : .alignment = PG_CACHE_LINE_SIZE,
97 : : .ptr = (void **) &BufferIOCVArray,
98 : : );
99 : :
100 : : /*
101 : : * The array used to sort to-be-checkpointed buffer ids is located in
102 : : * shared memory, to avoid having to allocate significant amounts of
103 : : * memory at runtime. As that'd be in the middle of a checkpoint, or when
104 : : * the checkpointer is restarted, memory allocation failures would be
105 : : * painful.
106 : : */
107 : 1244 : ShmemRequestStruct(.name = "Checkpoint BufferIds",
108 : : .size = NBuffers * sizeof(CkptSortItem),
109 : : .ptr = (void **) &CkptBufferIds,
110 : : );
111 : 1244 : }
112 : :
113 : : /*
114 : : * Initialize shared buffer pool
115 : : *
116 : : * This is called once during shared-memory initialization (either in the
117 : : * postmaster, or in a standalone backend).
118 : : */
119 : : static void
120 : 1241 : BufferManagerShmemInit(void *arg)
121 : : {
122 : : /*
123 : : * Initialize all the buffer headers.
124 : : */
125 [ + + ]: 11832417 : for (int i = 0; i < NBuffers; i++)
126 : : {
127 : 11831176 : BufferDesc *buf = GetBufferDescriptor(i);
128 : :
129 : 11831176 : ClearBufferTag(&buf->tag);
130 : :
131 : 11831176 : pg_atomic_init_u64(&buf->state, 0);
132 : 11831176 : buf->wait_backend_pgprocno = INVALID_PROC_NUMBER;
133 : :
134 : 11831176 : buf->buf_id = i;
135 : :
136 : 11831176 : pgaio_wref_clear(&buf->io_wref);
137 : :
138 : 11831176 : proclist_init(&buf->lock_waiters);
139 : 11831176 : ConditionVariableInit(BufferDescriptorGetIOCV(buf));
140 : : }
141 : :
142 : : /* Initialize per-backend file flush context */
3728 andres@anarazel.de 143 :CBC 1241 : WritebackContextInit(&BackendWritebackContext,
144 : : &backend_flush_after);
9269 tgl@sss.pgh.pa.us 145 : 1241 : }
146 : :
147 : : static void
29 heikki.linnakangas@i 148 :UNC 0 : BufferManagerShmemAttach(void *arg)
149 : : {
150 : : /* Initialize per-backend file flush context */
151 : 0 : WritebackContextInit(&BackendWritebackContext,
152 : : &backend_flush_after);
10892 scrappy@hub.org 153 :UIC 0 : }
|