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 : : #include "storage/shmem.h"
22 : : #include "storage/subsystems.h"
23 : :
24 : : BufferDescPadded *BufferDescriptors;
25 : : char *BufferBlocks;
26 : : ConditionVariableMinimallyPadded *BufferIOCVArray;
27 : : CkptSortItem *CkptBufferIds;
28 : :
29 : : static void BufferManagerShmemRequest(void *arg);
30 : : static void BufferManagerShmemInit(void *arg);
31 : :
32 : : const ShmemCallbacks BufferManagerShmemCallbacks = {
33 : : .request_fn = BufferManagerShmemRequest,
34 : : .init_fn = BufferManagerShmemInit,
35 : : };
36 : :
37 : : /*
38 : : * Data Structures:
39 : : * buffers live in a freelist and a lookup data structure.
40 : : *
41 : : *
42 : : * Buffer Lookup:
43 : : * Two important notes. First, the buffer has to be
44 : : * available for lookup BEFORE an IO begins. Otherwise
45 : : * a second process trying to read the buffer will
46 : : * allocate its own copy and the buffer pool will
47 : : * become inconsistent.
48 : : *
49 : : * Buffer Replacement:
50 : : * see freelist.c. A buffer cannot be replaced while in
51 : : * use either by data manager or during IO.
52 : : *
53 : : *
54 : : * Synchronization/Locking:
55 : : *
56 : : * IO_IN_PROGRESS -- this is a flag in the buffer descriptor.
57 : : * It must be set when an IO is initiated and cleared at
58 : : * the end of the IO. It is there to make sure that one
59 : : * process doesn't start to use a buffer while another is
60 : : * faulting it in. see WaitIO and related routines.
61 : : *
62 : : * refcount -- Counts the number of processes holding pins on a buffer.
63 : : * A buffer is pinned during IO and immediately after a BufferAlloc().
64 : : * Pins must be released before end of transaction. For efficiency the
65 : : * shared refcount isn't increased if an individual backend pins a buffer
66 : : * multiple times. Check the PrivateRefCount infrastructure in bufmgr.c.
67 : : */
68 : :
69 : :
70 : : /*
71 : : * Register shared memory area for the buffer pool.
72 : : */
73 : : static void
189 heikki.linnakangas@i 74 :CBC 1287 : BufferManagerShmemRequest(void *arg)
75 : : {
76 : 1287 : ShmemRequestStruct(.name = "Buffer Descriptors",
77 : : .size = NBuffers * sizeof(BufferDescPadded),
78 : : /* Align descriptors to a cacheline boundary. */
79 : : .alignment = PG_CACHE_LINE_SIZE,
80 : : .ptr = (void **) &BufferDescriptors,
81 : : );
82 : :
83 : 1287 : ShmemRequestStruct(.name = "Buffer Blocks",
84 : : .size = NBuffers * (Size) BLCKSZ,
85 : : /* Align buffer pool on IO page size boundary. */
86 : : .alignment = PG_IO_ALIGN_SIZE,
87 : : .ptr = (void **) &BufferBlocks,
88 : : );
89 : :
90 : 1287 : ShmemRequestStruct(.name = "Buffer IO Condition Variables",
91 : : .size = NBuffers * sizeof(ConditionVariableMinimallyPadded),
92 : : /* Align descriptors to a cacheline boundary. */
93 : : .alignment = PG_CACHE_LINE_SIZE,
94 : : .ptr = (void **) &BufferIOCVArray,
95 : : );
96 : :
97 : : /*
98 : : * The array used to sort to-be-checkpointed buffer ids is located in
99 : : * shared memory, to avoid having to allocate significant amounts of
100 : : * memory at runtime. As that'd be in the middle of a checkpoint, or when
101 : : * the checkpointer is restarted, memory allocation failures would be
102 : : * painful.
103 : : */
104 : 1287 : ShmemRequestStruct(.name = "Checkpoint BufferIds",
105 : : .size = NBuffers * sizeof(CkptSortItem),
106 : : .ptr = (void **) &CkptBufferIds,
107 : : );
108 : 1287 : }
109 : :
110 : : /*
111 : : * Initialize shared buffer pool
112 : : *
113 : : * This is called once during shared-memory initialization (either in the
114 : : * postmaster, or in a standalone backend).
115 : : */
116 : : static void
117 : 1283 : BufferManagerShmemInit(void *arg)
118 : : {
119 : : /*
120 : : * Initialize all the buffer headers.
121 : : */
122 [ + + ]: 11692403 : for (int i = 0; i < NBuffers; i++)
123 : : {
124 : 11691120 : BufferDesc *buf = GetBufferDescriptor(i);
125 : :
126 : 11691120 : ClearBufferTag(&buf->tag);
127 : :
128 : 11691120 : pg_atomic_init_u64(&buf->state, 0);
129 : 11691120 : buf->wait_backend_pgprocno = INVALID_PROC_NUMBER;
130 : :
131 : 11691120 : buf->buf_id = i;
132 : :
133 : 11691120 : pgaio_wref_clear(&buf->io_wref);
134 : :
135 : 11691120 : proclist_init(&buf->lock_waiters);
136 : 11691120 : ConditionVariableInit(BufferDescriptorGetIOCV(buf));
137 : : }
11052 scrappy@hub.org 138 : 1283 : }
|