Branch data 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 : :
22 : : BufferDescPadded *BufferDescriptors;
23 : : char *BufferBlocks;
24 : : ConditionVariableMinimallyPadded *BufferIOCVArray;
25 : : WritebackContext BackendWritebackContext;
26 : : CkptSortItem *CkptBufferIds;
27 : :
28 : :
29 : : /*
30 : : * Data Structures:
31 : : * buffers live in a freelist and a lookup data structure.
32 : : *
33 : : *
34 : : * Buffer Lookup:
35 : : * Two important notes. First, the buffer has to be
36 : : * available for lookup BEFORE an IO begins. Otherwise
37 : : * a second process trying to read the buffer will
38 : : * allocate its own copy and the buffer pool will
39 : : * become inconsistent.
40 : : *
41 : : * Buffer Replacement:
42 : : * see freelist.c. A buffer cannot be replaced while in
43 : : * use either by data manager or during IO.
44 : : *
45 : : *
46 : : * Synchronization/Locking:
47 : : *
48 : : * IO_IN_PROGRESS -- this is a flag in the buffer descriptor.
49 : : * It must be set when an IO is initiated and cleared at
50 : : * the end of the IO. It is there to make sure that one
51 : : * process doesn't start to use a buffer while another is
52 : : * faulting it in. see WaitIO and related routines.
53 : : *
54 : : * refcount -- Counts the number of processes holding pins on a buffer.
55 : : * A buffer is pinned during IO and immediately after a BufferAlloc().
56 : : * Pins must be released before end of transaction. For efficiency the
57 : : * shared refcount isn't increased if an individual backend pins a buffer
58 : : * multiple times. Check the PrivateRefCount infrastructure in bufmgr.c.
59 : : */
60 : :
61 : :
62 : : /*
63 : : * Initialize shared buffer pool
64 : : *
65 : : * This is called once during shared-memory initialization (either in the
66 : : * postmaster, or in a standalone backend).
67 : : */
68 : : void
69 : 6 : BufferManagerShmemInit(void)
70 : : {
71 : 6 : bool foundBufs,
72 : : foundDescs,
73 : : foundIOCV,
74 : : foundBufCkpt;
75 : :
76 : : /* Align descriptors to a cacheline boundary. */
77 : 6 : BufferDescriptors = (BufferDescPadded *)
78 : 6 : ShmemInitStruct("Buffer Descriptors",
79 : 6 : NBuffers * sizeof(BufferDescPadded),
80 : : &foundDescs);
81 : :
82 : : /* Align buffer pool on IO page size boundary. */
83 : 6 : BufferBlocks = (char *)
84 : 6 : TYPEALIGN(PG_IO_ALIGN_SIZE,
85 : : ShmemInitStruct("Buffer Blocks",
86 : : NBuffers * (Size) BLCKSZ + PG_IO_ALIGN_SIZE,
87 : : &foundBufs));
88 : :
89 : : /* Align condition variables to cacheline boundary. */
90 : 6 : BufferIOCVArray = (ConditionVariableMinimallyPadded *)
91 : 6 : ShmemInitStruct("Buffer IO Condition Variables",
92 : 6 : NBuffers * sizeof(ConditionVariableMinimallyPadded),
93 : : &foundIOCV);
94 : :
95 : : /*
96 : : * The array used to sort to-be-checkpointed buffer ids is located in
97 : : * shared memory, to avoid having to allocate significant amounts of
98 : : * memory at runtime. As that'd be in the middle of a checkpoint, or when
99 : : * the checkpointer is restarted, memory allocation failures would be
100 : : * painful.
101 : : */
102 : 6 : CkptBufferIds = (CkptSortItem *)
103 : 6 : ShmemInitStruct("Checkpoint BufferIds",
104 : 6 : NBuffers * sizeof(CkptSortItem), &foundBufCkpt);
105 : :
106 [ + - + - : 6 : if (foundDescs || foundBufs || foundIOCV || foundBufCkpt)
+ - - + ]
107 : : {
108 : : /* should find all of these, or none of them */
109 [ # # ]: 0 : Assert(foundDescs && foundBufs && foundIOCV && foundBufCkpt);
110 : : /* note: this path is only taken in EXEC_BACKEND case */
111 : 0 : }
112 : : else
113 : : {
114 : 6 : int i;
115 : :
116 : : /*
117 : : * Initialize all the buffer headers.
118 : : */
119 [ + + ]: 82926 : for (i = 0; i < NBuffers; i++)
120 : : {
121 : 82920 : BufferDesc *buf = GetBufferDescriptor(i);
122 : :
123 : 82920 : ClearBufferTag(&buf->tag);
124 : :
125 : 82920 : pg_atomic_init_u64(&buf->state, 0);
126 : 82920 : buf->wait_backend_pgprocno = INVALID_PROC_NUMBER;
127 : :
128 : 82920 : buf->buf_id = i;
129 : :
130 : 82920 : pgaio_wref_clear(&buf->io_wref);
131 : :
132 : 82920 : proclist_init(&buf->lock_waiters);
133 : 82920 : ConditionVariableInit(BufferDescriptorGetIOCV(buf));
134 : 82920 : }
135 : 6 : }
136 : :
137 : : /* Init other shared buffer-management stuff */
138 : 6 : StrategyInitialize(!foundDescs);
139 : :
140 : : /* Initialize per-backend file flush context */
141 : 6 : WritebackContextInit(&BackendWritebackContext,
142 : : &backend_flush_after);
143 : 6 : }
144 : :
145 : : /*
146 : : * BufferManagerShmemSize
147 : : *
148 : : * compute the size of shared memory for the buffer pool including
149 : : * data pages, buffer descriptors, hash tables, etc.
150 : : */
151 : : Size
152 : 9 : BufferManagerShmemSize(void)
153 : : {
154 : 9 : Size size = 0;
155 : :
156 : : /* size of buffer descriptors */
157 : 9 : size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded)));
158 : : /* to allow aligning buffer descriptors */
159 : 9 : size = add_size(size, PG_CACHE_LINE_SIZE);
160 : :
161 : : /* size of data pages, plus alignment padding */
162 : 9 : size = add_size(size, PG_IO_ALIGN_SIZE);
163 : 9 : size = add_size(size, mul_size(NBuffers, BLCKSZ));
164 : :
165 : : /* size of stuff controlled by freelist.c */
166 : 9 : size = add_size(size, StrategyShmemSize());
167 : :
168 : : /* size of I/O condition variables */
169 : 9 : size = add_size(size, mul_size(NBuffers,
170 : : sizeof(ConditionVariableMinimallyPadded)));
171 : : /* to allow aligning the above */
172 : 9 : size = add_size(size, PG_CACHE_LINE_SIZE);
173 : :
174 : : /* size of checkpoint sort array in bufmgr.c */
175 : 9 : size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem)));
176 : :
177 : 18 : return size;
178 : 9 : }
|