Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * buf_init.c
4 : * buffer manager initialization routines
5 : *
6 : * Portions Copyright (c) 1996-2023, 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
8167 tgl 68 CBC 1826 : InitBufferPool(void)
69 : {
70 : bool foundBufs,
71 : foundDescs,
72 : foundIOCV,
73 : foundBufCkpt;
74 :
75 : /* Align descriptors to a cacheline boundary. */
2672 rhaas 76 1826 : BufferDescriptors = (BufferDescPadded *)
2544 77 1826 : ShmemInitStruct("Buffer Descriptors",
78 : NBuffers * sizeof(BufferDescPadded),
79 : &foundDescs);
80 :
81 : /* Align buffer pool on IO page size boundary. */
8165 tgl 82 GIC 1826 : BufferBlocks = (char *)
1 tmunro 83 GNC 1826 : 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. */
759 tmunro 89 GIC 1826 : BufferIOCVArray = (ConditionVariableMinimallyPadded *)
90 1826 : ShmemInitStruct("Buffer IO Condition Variables",
91 : NBuffers * sizeof(ConditionVariableMinimallyPadded),
759 tmunro 92 ECB : &foundIOCV);
2672 rhaas 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 : */
2606 andres 101 GIC 1826 : CkptBufferIds = (CkptSortItem *)
102 1826 : ShmemInitStruct("Checkpoint BufferIds",
103 : NBuffers * sizeof(CkptSortItem), &foundBufCkpt);
2606 andres 104 ECB :
759 tmunro 105 CBC 1826 : if (foundDescs || foundBufs || foundIOCV || foundBufCkpt)
106 : {
107 : /* should find all of these, or none of them */
759 tmunro 108 LBC 0 : Assert(foundDescs && foundBufs && foundIOCV && foundBufCkpt);
109 : /* note: this path is only taken in EXEC_BACKEND case */
110 : }
9345 bruce 111 EUB : else
112 : {
113 : int i;
114 :
115 : /*
116 : * Initialize all the buffer headers.
117 : */
2992 andres 118 GIC 19878250 : for (i = 0; i < NBuffers; i++)
119 : {
120 19876424 : BufferDesc *buf = GetBufferDescriptor(i);
2992 andres 121 ECB :
256 rhaas 122 GNC 19876424 : ClearBufferTag(&buf->tag);
9345 bruce 123 ECB :
2555 andres 124 GIC 19876424 : pg_atomic_init_u32(&buf->state, 0);
479 tmunro 125 CBC 19876424 : buf->wait_backend_pgprocno = INVALID_PGPROCNO;
126 :
7862 tgl 127 19876424 : buf->buf_id = i;
7862 tgl 128 ECB :
129 : /*
6385 bruce 130 : * Initially link all the buffers together as unused. Subsequent
131 : * management of this list is done by freelist.c.
132 : */
6610 tgl 133 GIC 19876424 : buf->freeNext = i + 1;
134 :
2672 rhaas 135 19876424 : LWLockInitialize(BufferDescriptorGetContentLock(buf),
2672 rhaas 136 ECB : LWTRANCHE_BUFFER_CONTENT);
137 :
759 tmunro 138 CBC 19876424 : ConditionVariableInit(BufferDescriptorGetIOCV(buf));
139 : }
140 :
6639 tgl 141 ECB : /* Correct last entry of linked list */
2992 andres 142 GIC 1826 : GetBufferDescriptor(NBuffers - 1)->freeNext = FREENEXT_END_OF_LIST;
143 : }
144 :
8147 tgl 145 ECB : /* Init other shared buffer-management stuff */
7087 JanWieck 146 GIC 1826 : StrategyInitialize(!foundDescs);
147 :
148 : /* Initialize per-backend file flush context */
2606 andres 149 CBC 1826 : WritebackContextInit(&BackendWritebackContext,
150 : &backend_flush_after);
8147 tgl 151 GIC 1826 : }
8147 tgl 152 ECB :
153 : /*
9770 scrappy 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
8167 tgl 160 GIC 2738 : BufferShmemSize(void)
161 : {
6441 162 2738 : Size size = 0;
8812 tgl 163 ECB :
164 : /* size of buffer descriptors */
2992 andres 165 CBC 2738 : size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded)));
166 : /* to allow aligning buffer descriptors */
2992 andres 167 GIC 2738 : size = add_size(size, PG_CACHE_LINE_SIZE);
7024 JanWieck 168 ECB :
169 : /* size of data pages, plus alignment padding */
1 tmunro 170 GNC 2738 : size = add_size(size, PG_IO_ALIGN_SIZE);
6441 tgl 171 CBC 2738 : size = add_size(size, mul_size(NBuffers, BLCKSZ));
172 :
173 : /* size of stuff controlled by freelist.c */
174 2738 : size = add_size(size, StrategyShmemSize());
6929 tgl 175 ECB :
176 : /* size of I/O condition variables */
759 tmunro 177 GIC 2738 : size = add_size(size, mul_size(NBuffers,
759 tmunro 178 ECB : sizeof(ConditionVariableMinimallyPadded)));
179 : /* to allow aligning the above */
2672 rhaas 180 GIC 2738 : size = add_size(size, PG_CACHE_LINE_SIZE);
2672 rhaas 181 ECB :
182 : /* size of checkpoint sort array in bufmgr.c */
2606 andres 183 GIC 2738 : size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem)));
2606 andres 184 ECB :
9345 bruce 185 GIC 2738 : return size;
186 : }
|