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-2024, 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/buf_internals.h"
18 : : #include "storage/bufmgr.h"
19 : : #include "storage/proc.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
8538 tgl@sss.pgh.pa.us 68 :CBC 898 : InitBufferPool(void)
69 : : {
70 : : bool foundBufs,
71 : : foundDescs,
72 : : foundIOCV,
73 : : foundBufCkpt;
74 : :
75 : : /* Align descriptors to a cacheline boundary. */
3043 rhaas@postgresql.org 76 : 898 : BufferDescriptors = (BufferDescPadded *)
2915 77 : 898 : ShmemInitStruct("Buffer Descriptors",
78 : : NBuffers * sizeof(BufferDescPadded),
79 : : &foundDescs);
80 : :
81 : : /* Align buffer pool on IO page size boundary. */
8536 tgl@sss.pgh.pa.us 82 : 898 : BufferBlocks = (char *)
372 tmunro@postgresql.or 83 : 898 : 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. */
1130 89 : 898 : BufferIOCVArray = (ConditionVariableMinimallyPadded *)
90 : 898 : 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 : : */
2977 andres@anarazel.de 101 : 898 : CkptBufferIds = (CkptSortItem *)
102 : 898 : ShmemInitStruct("Checkpoint BufferIds",
103 : : NBuffers * sizeof(CkptSortItem), &foundBufCkpt);
104 : :
1130 tmunro@postgresql.or 105 [ + - + - : 898 : if (foundDescs || foundBufs || foundIOCV || foundBufCkpt)
+ - - + ]
106 : : {
107 : : /* should find all of these, or none of them */
1130 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 : : */
3363 andres@anarazel.de 118 [ + + ]:CBC 8277434 : for (i = 0; i < NBuffers; i++)
119 : : {
120 : 8276536 : BufferDesc *buf = GetBufferDescriptor(i);
121 : :
627 rhaas@postgresql.org 122 : 8276536 : ClearBufferTag(&buf->tag);
123 : :
2926 andres@anarazel.de 124 : 8276536 : pg_atomic_init_u32(&buf->state, 0);
42 heikki.linnakangas@i 125 :GNC 8276536 : buf->wait_backend_pgprocno = INVALID_PROC_NUMBER;
126 : :
8233 tgl@sss.pgh.pa.us 127 :CBC 8276536 : buf->buf_id = i;
128 : :
129 : : /*
130 : : * Initially link all the buffers together as unused. Subsequent
131 : : * management of this list is done by freelist.c.
132 : : */
6981 133 : 8276536 : buf->freeNext = i + 1;
134 : :
3043 rhaas@postgresql.org 135 : 8276536 : LWLockInitialize(BufferDescriptorGetContentLock(buf),
136 : : LWTRANCHE_BUFFER_CONTENT);
137 : :
1130 tmunro@postgresql.or 138 : 8276536 : ConditionVariableInit(BufferDescriptorGetIOCV(buf));
139 : : }
140 : :
141 : : /* Correct last entry of linked list */
3363 andres@anarazel.de 142 : 898 : GetBufferDescriptor(NBuffers - 1)->freeNext = FREENEXT_END_OF_LIST;
143 : : }
144 : :
145 : : /* Init other shared buffer-management stuff */
7458 JanWieck@Yahoo.com 146 : 898 : StrategyInitialize(!foundDescs);
147 : :
148 : : /* Initialize per-backend file flush context */
2977 andres@anarazel.de 149 : 898 : WritebackContextInit(&BackendWritebackContext,
150 : : &backend_flush_after);
8518 tgl@sss.pgh.pa.us 151 : 898 : }
152 : :
153 : : /*
154 : : * BufferShmemSize
155 : : *
156 : : * compute the size of shared memory for the buffer pool including
157 : : * data pages, buffer descriptors, hash tables, etc.
158 : : */
159 : : Size
8538 160 : 1679 : BufferShmemSize(void)
161 : : {
6812 162 : 1679 : Size size = 0;
163 : :
164 : : /* size of buffer descriptors */
3363 andres@anarazel.de 165 : 1679 : size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded)));
166 : : /* to allow aligning buffer descriptors */
167 : 1679 : size = add_size(size, PG_CACHE_LINE_SIZE);
168 : :
169 : : /* size of data pages, plus alignment padding */
372 tmunro@postgresql.or 170 : 1679 : size = add_size(size, PG_IO_ALIGN_SIZE);
6812 tgl@sss.pgh.pa.us 171 : 1679 : size = add_size(size, mul_size(NBuffers, BLCKSZ));
172 : :
173 : : /* size of stuff controlled by freelist.c */
174 : 1679 : size = add_size(size, StrategyShmemSize());
175 : :
176 : : /* size of I/O condition variables */
1130 tmunro@postgresql.or 177 : 1679 : size = add_size(size, mul_size(NBuffers,
178 : : sizeof(ConditionVariableMinimallyPadded)));
179 : : /* to allow aligning the above */
3043 rhaas@postgresql.org 180 : 1679 : size = add_size(size, PG_CACHE_LINE_SIZE);
181 : :
182 : : /* size of checkpoint sort array in bufmgr.c */
2977 andres@anarazel.de 183 : 1679 : size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem)));
184 : :
9716 bruce@momjian.us 185 : 1679 : return size;
186 : : }
|