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 : :
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
563 heikki.linnakangas@i 69 :CBC 1150 : BufferManagerShmemInit(void)
70 : : {
71 : : bool foundBufs,
72 : : foundDescs,
73 : : foundIOCV,
74 : : foundBufCkpt;
75 : :
76 : : /* Align descriptors to a cacheline boundary. */
3743 rhaas@postgresql.org 77 : 1150 : BufferDescriptors = (BufferDescPadded *)
3615 78 : 1150 : ShmemInitStruct("Buffer Descriptors",
79 : : NBuffers * sizeof(BufferDescPadded),
80 : : &foundDescs);
81 : :
82 : : /* Align buffer pool on IO page size boundary. */
9236 tgl@sss.pgh.pa.us 83 : 1150 : BufferBlocks = (char *)
1072 tmunro@postgresql.or 84 : 1150 : 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. */
1830 90 : 1150 : BufferIOCVArray = (ConditionVariableMinimallyPadded *)
91 : 1150 : ShmemInitStruct("Buffer IO Condition Variables",
92 : : 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 : : */
3677 andres@anarazel.de 102 : 1150 : CkptBufferIds = (CkptSortItem *)
103 : 1150 : ShmemInitStruct("Checkpoint BufferIds",
104 : : NBuffers * sizeof(CkptSortItem), &foundBufCkpt);
105 : :
1830 tmunro@postgresql.or 106 [ + - + - : 1150 : if (foundDescs || foundBufs || foundIOCV || foundBufCkpt)
+ - - + ]
107 : : {
108 : : /* should find all of these, or none of them */
1830 tmunro@postgresql.or 109 [ # # # # :UBC 0 : Assert(foundDescs && foundBufs && foundIOCV && foundBufCkpt);
# # # # ]
110 : : /* note: this path is only taken in EXEC_BACKEND case */
111 : : }
112 : : else
113 : : {
114 : : int i;
115 : :
116 : : /*
117 : : * Initialize all the buffer headers.
118 : : */
4063 andres@anarazel.de 119 [ + + ]:CBC 10726294 : for (i = 0; i < NBuffers; i++)
120 : : {
121 : 10725144 : BufferDesc *buf = GetBufferDescriptor(i);
122 : :
1327 rhaas@postgresql.org 123 : 10725144 : ClearBufferTag(&buf->tag);
124 : :
59 andres@anarazel.de 125 :GNC 10725144 : pg_atomic_init_u64(&buf->state, 0);
742 heikki.linnakangas@i 126 :CBC 10725144 : buf->wait_backend_pgprocno = INVALID_PROC_NUMBER;
127 : :
8933 tgl@sss.pgh.pa.us 128 : 10725144 : buf->buf_id = i;
129 : :
350 andres@anarazel.de 130 : 10725144 : pgaio_wref_clear(&buf->io_wref);
131 : :
59 andres@anarazel.de 132 :GNC 10725144 : proclist_init(&buf->lock_waiters);
1830 tmunro@postgresql.or 133 :CBC 10725144 : ConditionVariableInit(BufferDescriptorGetIOCV(buf));
134 : : }
135 : : }
136 : :
137 : : /* Init other shared buffer-management stuff */
8158 JanWieck@Yahoo.com 138 : 1150 : StrategyInitialize(!foundDescs);
139 : :
140 : : /* Initialize per-backend file flush context */
3677 andres@anarazel.de 141 : 1150 : WritebackContextInit(&BackendWritebackContext,
142 : : &backend_flush_after);
9218 tgl@sss.pgh.pa.us 143 : 1150 : }
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
563 heikki.linnakangas@i 152 : 2147 : BufferManagerShmemSize(void)
153 : : {
7512 tgl@sss.pgh.pa.us 154 : 2147 : Size size = 0;
155 : :
156 : : /* size of buffer descriptors */
4063 andres@anarazel.de 157 : 2147 : size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded)));
158 : : /* to allow aligning buffer descriptors */
159 : 2147 : size = add_size(size, PG_CACHE_LINE_SIZE);
160 : :
161 : : /* size of data pages, plus alignment padding */
1072 tmunro@postgresql.or 162 : 2147 : size = add_size(size, PG_IO_ALIGN_SIZE);
7512 tgl@sss.pgh.pa.us 163 : 2147 : size = add_size(size, mul_size(NBuffers, BLCKSZ));
164 : :
165 : : /* size of stuff controlled by freelist.c */
166 : 2147 : size = add_size(size, StrategyShmemSize());
167 : :
168 : : /* size of I/O condition variables */
1830 tmunro@postgresql.or 169 : 2147 : size = add_size(size, mul_size(NBuffers,
170 : : sizeof(ConditionVariableMinimallyPadded)));
171 : : /* to allow aligning the above */
3743 rhaas@postgresql.org 172 : 2147 : size = add_size(size, PG_CACHE_LINE_SIZE);
173 : :
174 : : /* size of checkpoint sort array in bufmgr.c */
3677 andres@anarazel.de 175 : 2147 : size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem)));
176 : :
10416 bruce@momjian.us 177 : 2147 : return size;
178 : : }
|