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