TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * ipci.c
4 : * POSTGRES inter-process communication initialization code.
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/ipc/ipci.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
17 : #include "access/clog.h"
18 : #include "access/commit_ts.h"
19 : #include "access/heapam.h"
20 : #include "access/multixact.h"
21 : #include "access/nbtree.h"
22 : #include "access/subtrans.h"
23 : #include "access/syncscan.h"
24 : #include "access/twophase.h"
25 : #include "access/xlogprefetcher.h"
26 : #include "access/xlogrecovery.h"
27 : #include "commands/async.h"
28 : #include "miscadmin.h"
29 : #include "pgstat.h"
30 : #include "postmaster/autovacuum.h"
31 : #include "postmaster/bgworker_internals.h"
32 : #include "postmaster/bgwriter.h"
33 : #include "postmaster/postmaster.h"
34 : #include "replication/logicallauncher.h"
35 : #include "replication/origin.h"
36 : #include "replication/slot.h"
37 : #include "replication/walreceiver.h"
38 : #include "replication/walsender.h"
39 : #include "storage/bufmgr.h"
40 : #include "storage/dsm.h"
41 : #include "storage/ipc.h"
42 : #include "storage/pg_shmem.h"
43 : #include "storage/pmsignal.h"
44 : #include "storage/predicate.h"
45 : #include "storage/proc.h"
46 : #include "storage/procarray.h"
47 : #include "storage/procsignal.h"
48 : #include "storage/sinvaladt.h"
49 : #include "storage/spin.h"
50 : #include "utils/guc.h"
51 : #include "utils/snapmgr.h"
52 :
53 : /* GUCs */
54 : int shared_memory_type = DEFAULT_SHARED_MEMORY_TYPE;
55 :
56 : shmem_startup_hook_type shmem_startup_hook = NULL;
57 :
58 : static Size total_addin_request = 0;
59 :
60 : /*
61 : * RequestAddinShmemSpace
62 : * Request that extra shmem space be allocated for use by
63 : * a loadable module.
64 : *
65 : * This may only be called via the shmem_request_hook of a library that is
66 : * loaded into the postmaster via shared_preload_libraries. Calls from
67 : * elsewhere will fail.
68 : */
69 : void
70 GIC 6 : RequestAddinShmemSpace(Size size)
71 ECB : {
72 GIC 6 : if (!process_shmem_requests_in_progress)
73 LBC 0 : elog(FATAL, "cannot request additional shared memory outside shmem_request_hook");
74 GBC 6 : total_addin_request = add_size(total_addin_request, size);
75 CBC 6 : }
76 ECB :
77 : /*
78 : * CalculateShmemSize
79 : * Calculates the amount of shared memory and number of semaphores needed.
80 : *
81 : * If num_semaphores is not NULL, it will be set to the number of semaphores
82 : * required.
83 : */
84 : Size
85 GIC 2738 : CalculateShmemSize(int *num_semaphores)
86 ECB : {
87 : Size size;
88 : int numSemas;
89 :
90 : /* Compute number of semaphores we'll need */
91 GIC 2738 : numSemas = ProcGlobalSemas();
92 CBC 2738 : numSemas += SpinlockSemas();
93 ECB :
94 : /* Return the number of semaphores if requested by the caller */
95 GIC 2738 : if (num_semaphores)
96 CBC 1828 : *num_semaphores = numSemas;
97 ECB :
98 : /*
99 : * Size of the Postgres shared-memory block is estimated via moderately-
100 : * accurate estimates for the big hogs, plus 100K for the stuff that's too
101 : * small to bother with estimating.
102 : *
103 : * We take some care to ensure that the total size request doesn't
104 : * overflow size_t. If this gets through, we don't need to be so careful
105 : * during the actual allocation phase.
106 : */
107 GIC 2738 : size = 100000;
108 CBC 2738 : size = add_size(size, PGSemaphoreShmemSize(numSemas));
109 2738 : size = add_size(size, SpinlockSemaSize());
110 2738 : size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
111 ECB : sizeof(ShmemIndexEnt)));
112 GIC 2738 : size = add_size(size, dsm_estimate_size());
113 CBC 2738 : size = add_size(size, BufferShmemSize());
114 2738 : size = add_size(size, LockShmemSize());
115 2738 : size = add_size(size, PredicateLockShmemSize());
116 2738 : size = add_size(size, ProcGlobalShmemSize());
117 2738 : size = add_size(size, XLogPrefetchShmemSize());
118 2738 : size = add_size(size, XLOGShmemSize());
119 2738 : size = add_size(size, XLogRecoveryShmemSize());
120 2738 : size = add_size(size, CLOGShmemSize());
121 2738 : size = add_size(size, CommitTsShmemSize());
122 2738 : size = add_size(size, SUBTRANSShmemSize());
123 2738 : size = add_size(size, TwoPhaseShmemSize());
124 2738 : size = add_size(size, BackgroundWorkerShmemSize());
125 2738 : size = add_size(size, MultiXactShmemSize());
126 2738 : size = add_size(size, LWLockShmemSize());
127 2738 : size = add_size(size, ProcArrayShmemSize());
128 2738 : size = add_size(size, BackendStatusShmemSize());
129 2738 : size = add_size(size, SInvalShmemSize());
130 2738 : size = add_size(size, PMSignalShmemSize());
131 2738 : size = add_size(size, ProcSignalShmemSize());
132 2738 : size = add_size(size, CheckpointerShmemSize());
133 2738 : size = add_size(size, AutoVacuumShmemSize());
134 2738 : size = add_size(size, ReplicationSlotsShmemSize());
135 2738 : size = add_size(size, ReplicationOriginShmemSize());
136 2738 : size = add_size(size, WalSndShmemSize());
137 2738 : size = add_size(size, WalRcvShmemSize());
138 2738 : size = add_size(size, PgArchShmemSize());
139 2738 : size = add_size(size, ApplyLauncherShmemSize());
140 2738 : size = add_size(size, SnapMgrShmemSize());
141 2738 : size = add_size(size, BTreeShmemSize());
142 2738 : size = add_size(size, SyncScanShmemSize());
143 2738 : size = add_size(size, AsyncShmemSize());
144 2738 : size = add_size(size, StatsShmemSize());
145 ECB : #ifdef EXEC_BACKEND
146 : size = add_size(size, ShmemBackendArraySize());
147 : #endif
148 :
149 : /* include additional requested shmem from preload libraries */
150 GIC 2738 : size = add_size(size, total_addin_request);
151 ECB :
152 : /* might as well round it off to a multiple of a typical page size */
153 GIC 2738 : size = add_size(size, 8192 - (size % 8192));
154 ECB :
155 GIC 2738 : return size;
156 ECB : }
157 :
158 : /*
159 : * CreateSharedMemoryAndSemaphores
160 : * Creates and initializes shared memory and semaphores.
161 : *
162 : * This is called by the postmaster or by a standalone backend.
163 : * It is also called by a backend forked from the postmaster in the
164 : * EXEC_BACKEND case. In the latter case, the shared memory segment
165 : * already exists and has been physically attached to, but we have to
166 : * initialize pointers in local memory that reference the shared structures,
167 : * because we didn't inherit the correct pointer values from the postmaster
168 : * as we do in the fork() scenario. The easiest way to do that is to run
169 : * through the same code as before. (Note that the called routines mostly
170 : * check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case.
171 : * This is a bit code-wasteful and could be cleaned up.)
172 : */
173 : void
174 GIC 1828 : CreateSharedMemoryAndSemaphores(void)
175 ECB : {
176 GIC 1828 : PGShmemHeader *shim = NULL;
177 ECB :
178 GIC 1828 : if (!IsUnderPostmaster)
179 ECB : {
180 : PGShmemHeader *seghdr;
181 : Size size;
182 : int numSemas;
183 :
184 : /* Compute the size of the shared-memory block */
185 GIC 1828 : size = CalculateShmemSize(&numSemas);
186 CBC 1828 : elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
187 ECB :
188 : /*
189 : * Create the shmem segment
190 : */
191 GIC 1828 : seghdr = PGSharedMemoryCreate(size, &shim);
192 ECB :
193 GIC 1826 : InitShmemAccess(seghdr);
194 ECB :
195 : /*
196 : * Create semaphores
197 : */
198 GIC 1826 : PGReserveSemaphores(numSemas);
199 ECB :
200 : /*
201 : * If spinlocks are disabled, initialize emulation layer (which
202 : * depends on semaphores, so the order is important here).
203 : */
204 : #ifndef HAVE_SPINLOCKS
205 : SpinlockSemaInit();
206 : #endif
207 : }
208 : else
209 : {
210 : /*
211 : * We are reattaching to an existing shared memory segment. This
212 : * should only be reached in the EXEC_BACKEND case.
213 : */
214 : #ifndef EXEC_BACKEND
215 UIC 0 : elog(PANIC, "should be attached to shared memory already");
216 EUB : #endif
217 : }
218 :
219 : /*
220 : * Set up shared memory allocation mechanism
221 : */
222 GIC 1826 : if (!IsUnderPostmaster)
223 CBC 1826 : InitShmemAllocation();
224 ECB :
225 : /*
226 : * Now initialize LWLocks, which do shared memory allocation and are
227 : * needed for InitShmemIndex.
228 : */
229 GIC 1826 : CreateLWLocks();
230 ECB :
231 : /*
232 : * Set up shmem.c index hashtable
233 : */
234 GIC 1826 : InitShmemIndex();
235 ECB :
236 GIC 1826 : dsm_shmem_init();
237 ECB :
238 : /*
239 : * Set up xlog, clog, and buffers
240 : */
241 GIC 1826 : XLOGShmemInit();
242 CBC 1826 : XLogPrefetchShmemInit();
243 1826 : XLogRecoveryShmemInit();
244 1826 : CLOGShmemInit();
245 1826 : CommitTsShmemInit();
246 1826 : SUBTRANSShmemInit();
247 1826 : MultiXactShmemInit();
248 1826 : InitBufferPool();
249 ECB :
250 : /*
251 : * Set up lock manager
252 : */
253 GIC 1826 : InitLocks();
254 ECB :
255 : /*
256 : * Set up predicate lock manager
257 : */
258 GIC 1826 : InitPredicateLocks();
259 ECB :
260 : /*
261 : * Set up process table
262 : */
263 GIC 1826 : if (!IsUnderPostmaster)
264 CBC 1826 : InitProcGlobal();
265 1826 : CreateSharedProcArray();
266 1826 : CreateSharedBackendStatus();
267 1826 : TwoPhaseShmemInit();
268 1826 : BackgroundWorkerShmemInit();
269 ECB :
270 : /*
271 : * Set up shared-inval messaging
272 : */
273 GIC 1826 : CreateSharedInvalidationState();
274 ECB :
275 : /*
276 : * Set up interprocess signaling mechanisms
277 : */
278 GIC 1826 : PMSignalShmemInit();
279 CBC 1826 : ProcSignalShmemInit();
280 1826 : CheckpointerShmemInit();
281 1826 : AutoVacuumShmemInit();
282 1826 : ReplicationSlotsShmemInit();
283 1826 : ReplicationOriginShmemInit();
284 1826 : WalSndShmemInit();
285 1826 : WalRcvShmemInit();
286 1826 : PgArchShmemInit();
287 1826 : ApplyLauncherShmemInit();
288 ECB :
289 : /*
290 : * Set up other modules that need some shared memory space
291 : */
292 GIC 1826 : SnapMgrInit();
293 CBC 1826 : BTreeShmemInit();
294 1826 : SyncScanShmemInit();
295 1826 : AsyncShmemInit();
296 1826 : StatsShmemInit();
297 ECB :
298 : #ifdef EXEC_BACKEND
299 :
300 : /*
301 : * Alloc the win32 shared backend array
302 : */
303 : if (!IsUnderPostmaster)
304 : ShmemBackendArrayAllocation();
305 : #endif
306 :
307 : /* Initialize dynamic shared memory facilities. */
308 GIC 1826 : if (!IsUnderPostmaster)
309 CBC 1826 : dsm_postmaster_startup(shim);
310 ECB :
311 : /*
312 : * Now give loadable modules a chance to set up their shmem allocations
313 : */
314 GIC 1826 : if (shmem_startup_hook)
315 CBC 4 : shmem_startup_hook();
316 1826 : }
317 ECB :
318 : /*
319 : * InitializeShmemGUCs
320 : *
321 : * This function initializes runtime-computed GUCs related to the amount of
322 : * shared memory required for the current configuration.
323 : */
324 : void
325 GIC 910 : InitializeShmemGUCs(void)
326 ECB : {
327 : char buf[64];
328 : Size size_b;
329 : Size size_mb;
330 : Size hp_size;
331 :
332 : /*
333 : * Calculate the shared memory size and round up to the nearest megabyte.
334 : */
335 GIC 910 : size_b = CalculateShmemSize(NULL);
336 CBC 910 : size_mb = add_size(size_b, (1024 * 1024) - 1) / (1024 * 1024);
337 910 : sprintf(buf, "%zu", size_mb);
338 910 : SetConfigOption("shared_memory_size", buf,
339 ECB : PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
340 :
341 : /*
342 : * Calculate the number of huge pages required.
343 : */
344 GIC 910 : GetHugePageSize(&hp_size, NULL);
345 CBC 910 : if (hp_size != 0)
346 ECB : {
347 : Size hp_required;
348 :
349 GIC 910 : hp_required = add_size(size_b / hp_size, 1);
350 CBC 910 : sprintf(buf, "%zu", hp_required);
351 910 : SetConfigOption("shared_memory_size_in_huge_pages", buf,
352 ECB : PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
353 : }
354 GIC 910 : }
|