Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * ipci.c
4 : : * POSTGRES inter-process communication initialization code.
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/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/multixact.h"
20 : : #include "access/nbtree.h"
21 : : #include "access/subtrans.h"
22 : : #include "access/syncscan.h"
23 : : #include "access/transam.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 "postmaster/walsummarizer.h"
35 : : #include "replication/logicallauncher.h"
36 : : #include "replication/origin.h"
37 : : #include "replication/slot.h"
38 : : #include "replication/slotsync.h"
39 : : #include "replication/walreceiver.h"
40 : : #include "replication/walsender.h"
41 : : #include "storage/bufmgr.h"
42 : : #include "storage/dsm.h"
43 : : #include "storage/dsm_registry.h"
44 : : #include "storage/ipc.h"
45 : : #include "storage/pg_shmem.h"
46 : : #include "storage/pmsignal.h"
47 : : #include "storage/predicate.h"
48 : : #include "storage/proc.h"
49 : : #include "storage/procarray.h"
50 : : #include "storage/procsignal.h"
51 : : #include "storage/sinvaladt.h"
52 : : #include "storage/spin.h"
53 : : #include "utils/guc.h"
54 : : #include "utils/injection_point.h"
55 : :
56 : : /* GUCs */
57 : : int shared_memory_type = DEFAULT_SHARED_MEMORY_TYPE;
58 : :
59 : : shmem_startup_hook_type shmem_startup_hook = NULL;
60 : :
61 : : static Size total_addin_request = 0;
62 : :
63 : : static void CreateOrAttachShmemStructs(void);
64 : :
65 : : /*
66 : : * RequestAddinShmemSpace
67 : : * Request that extra shmem space be allocated for use by
68 : : * a loadable module.
69 : : *
70 : : * This may only be called via the shmem_request_hook of a library that is
71 : : * loaded into the postmaster via shared_preload_libraries. Calls from
72 : : * elsewhere will fail.
73 : : */
74 : : void
6391 tgl@sss.pgh.pa.us 75 :CBC 7 : RequestAddinShmemSpace(Size size)
76 : : {
702 rhaas@postgresql.org 77 [ - + ]: 7 : if (!process_shmem_requests_in_progress)
702 rhaas@postgresql.org 78 [ # # ]:UBC 0 : elog(FATAL, "cannot request additional shared memory outside shmem_request_hook");
6391 tgl@sss.pgh.pa.us 79 :CBC 7 : total_addin_request = add_size(total_addin_request, size);
80 : 7 : }
81 : :
82 : : /*
83 : : * CalculateShmemSize
84 : : * Calculates the amount of shared memory and number of semaphores needed.
85 : : *
86 : : * If num_semaphores is not NULL, it will be set to the number of semaphores
87 : : * required.
88 : : */
89 : : Size
951 michael@paquier.xyz 90 : 1679 : CalculateShmemSize(int *num_semaphores)
91 : : {
92 : : Size size;
93 : : int numSemas;
94 : :
95 : : /* Compute number of semaphores we'll need */
96 : 1679 : numSemas = ProcGlobalSemas();
97 : 1679 : numSemas += SpinlockSemas();
98 : :
99 : : /* Return the number of semaphores if requested by the caller */
100 [ + + ]: 1679 : if (num_semaphores)
101 : 900 : *num_semaphores = numSemas;
102 : :
103 : : /*
104 : : * Size of the Postgres shared-memory block is estimated via moderately-
105 : : * accurate estimates for the big hogs, plus 100K for the stuff that's too
106 : : * small to bother with estimating.
107 : : *
108 : : * We take some care to ensure that the total size request doesn't
109 : : * overflow size_t. If this gets through, we don't need to be so careful
110 : : * during the actual allocation phase.
111 : : */
112 : 1679 : size = 100000;
113 : 1679 : size = add_size(size, PGSemaphoreShmemSize(numSemas));
114 : 1679 : size = add_size(size, SpinlockSemaSize());
115 : 1679 : size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
116 : : sizeof(ShmemIndexEnt)));
117 : 1679 : size = add_size(size, dsm_estimate_size());
86 nathan@postgresql.or 118 :GNC 1679 : size = add_size(size, DSMRegistryShmemSize());
951 michael@paquier.xyz 119 :CBC 1679 : size = add_size(size, BufferShmemSize());
120 : 1679 : size = add_size(size, LockShmemSize());
121 : 1679 : size = add_size(size, PredicateLockShmemSize());
122 : 1679 : size = add_size(size, ProcGlobalShmemSize());
738 tmunro@postgresql.or 123 : 1679 : size = add_size(size, XLogPrefetchShmemSize());
128 heikki.linnakangas@i 124 :GNC 1679 : size = add_size(size, VarsupShmemSize());
951 michael@paquier.xyz 125 :CBC 1679 : size = add_size(size, XLOGShmemSize());
788 heikki.linnakangas@i 126 : 1679 : size = add_size(size, XLogRecoveryShmemSize());
951 michael@paquier.xyz 127 : 1679 : size = add_size(size, CLOGShmemSize());
128 : 1679 : size = add_size(size, CommitTsShmemSize());
129 : 1679 : size = add_size(size, SUBTRANSShmemSize());
130 : 1679 : size = add_size(size, TwoPhaseShmemSize());
131 : 1679 : size = add_size(size, BackgroundWorkerShmemSize());
132 : 1679 : size = add_size(size, MultiXactShmemSize());
133 : 1679 : size = add_size(size, LWLockShmemSize());
134 : 1679 : size = add_size(size, ProcArrayShmemSize());
135 : 1679 : size = add_size(size, BackendStatusShmemSize());
136 : 1679 : size = add_size(size, SInvalShmemSize());
137 : 1679 : size = add_size(size, PMSignalShmemSize());
138 : 1679 : size = add_size(size, ProcSignalShmemSize());
139 : 1679 : size = add_size(size, CheckpointerShmemSize());
140 : 1679 : size = add_size(size, AutoVacuumShmemSize());
141 : 1679 : size = add_size(size, ReplicationSlotsShmemSize());
142 : 1679 : size = add_size(size, ReplicationOriginShmemSize());
143 : 1679 : size = add_size(size, WalSndShmemSize());
144 : 1679 : size = add_size(size, WalRcvShmemSize());
116 rhaas@postgresql.org 145 :GNC 1679 : size = add_size(size, WalSummarizerShmemSize());
951 michael@paquier.xyz 146 :CBC 1679 : size = add_size(size, PgArchShmemSize());
147 : 1679 : size = add_size(size, ApplyLauncherShmemSize());
148 : 1679 : size = add_size(size, BTreeShmemSize());
149 : 1679 : size = add_size(size, SyncScanShmemSize());
150 : 1679 : size = add_size(size, AsyncShmemSize());
739 andres@anarazel.de 151 : 1679 : size = add_size(size, StatsShmemSize());
258 michael@paquier.xyz 152 :GNC 1679 : size = add_size(size, WaitEventExtensionShmemSize());
83 153 : 1679 : size = add_size(size, InjectionPointShmemSize());
60 akapila@postgresql.o 154 : 1679 : size = add_size(size, SlotSyncShmemSize());
155 : : #ifdef EXEC_BACKEND
156 : : size = add_size(size, ShmemBackendArraySize());
157 : : #endif
158 : :
159 : : /* include additional requested shmem from preload libraries */
951 michael@paquier.xyz 160 :CBC 1679 : size = add_size(size, total_addin_request);
161 : :
162 : : /* might as well round it off to a multiple of a typical page size */
163 : 1679 : size = add_size(size, 8192 - (size % 8192));
164 : :
165 : 1679 : return size;
166 : : }
167 : :
168 : : #ifdef EXEC_BACKEND
169 : : /*
170 : : * AttachSharedMemoryStructs
171 : : * Initialize a postmaster child process's access to shared memory
172 : : * structures.
173 : : *
174 : : * In !EXEC_BACKEND mode, we inherit everything through the fork, and this
175 : : * isn't needed.
176 : : */
177 : : void
178 : : AttachSharedMemoryStructs(void)
179 : : {
180 : : /* InitProcess must've been called already */
181 : : Assert(MyProc != NULL);
182 : : Assert(IsUnderPostmaster);
183 : :
184 : : CreateOrAttachShmemStructs();
185 : :
186 : : /*
187 : : * Now give loadable modules a chance to set up their shmem allocations
188 : : */
189 : : if (shmem_startup_hook)
190 : : shmem_startup_hook();
191 : : }
192 : : #endif
193 : :
194 : : /*
195 : : * CreateSharedMemoryAndSemaphores
196 : : * Creates and initializes shared memory and semaphores.
197 : : */
198 : : void
133 heikki.linnakangas@i 199 :GNC 900 : CreateSharedMemoryAndSemaphores(void)
200 : : {
201 : : PGShmemHeader *shim;
202 : : PGShmemHeader *seghdr;
203 : : Size size;
204 : : int numSemas;
205 : :
206 [ - + ]: 900 : Assert(!IsUnderPostmaster);
207 : :
208 : : /* Compute the size of the shared-memory block */
209 : 900 : size = CalculateShmemSize(&numSemas);
210 [ - + ]: 900 : elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
211 : :
212 : : /*
213 : : * Create the shmem segment
214 : : */
215 : 900 : seghdr = PGSharedMemoryCreate(size, &shim);
216 : :
217 : : /*
218 : : * Make sure that huge pages are never reported as "unknown" while the
219 : : * server is running.
220 : : */
221 [ - + ]: 898 : Assert(strcmp("unknown",
222 : : GetConfigOption("huge_pages_status", false, false)) != 0);
223 : :
224 : 898 : InitShmemAccess(seghdr);
225 : :
226 : : /*
227 : : * Create semaphores
228 : : */
229 : 898 : PGReserveSemaphores(numSemas);
230 : :
231 : : /*
232 : : * If spinlocks are disabled, initialize emulation layer (which depends on
233 : : * semaphores, so the order is important here).
234 : : */
235 : : #ifndef HAVE_SPINLOCKS
236 : : SpinlockSemaInit();
237 : : #endif
238 : :
239 : : /*
240 : : * Set up shared memory allocation mechanism
241 : : */
242 : 898 : InitShmemAllocation();
243 : :
244 : : /* Initialize subsystems */
245 : 898 : CreateOrAttachShmemStructs();
246 : :
247 : : #ifdef EXEC_BACKEND
248 : :
249 : : /*
250 : : * Alloc the win32 shared backend array
251 : : */
252 : : ShmemBackendArrayAllocation();
253 : : #endif
254 : :
255 : : /* Initialize dynamic shared memory facilities. */
256 : 898 : dsm_postmaster_startup(shim);
257 : :
258 : : /*
259 : : * Now give loadable modules a chance to set up their shmem allocations
260 : : */
261 [ + + ]: 898 : if (shmem_startup_hook)
262 : 7 : shmem_startup_hook();
263 : 898 : }
264 : :
265 : : /*
266 : : * Initialize various subsystems, setting up their data structures in
267 : : * shared memory.
268 : : *
269 : : * This is called by the postmaster or by a standalone backend.
270 : : * It is also called by a backend forked from the postmaster in the
271 : : * EXEC_BACKEND case. In the latter case, the shared memory segment
272 : : * already exists and has been physically attached to, but we have to
273 : : * initialize pointers in local memory that reference the shared structures,
274 : : * because we didn't inherit the correct pointer values from the postmaster
275 : : * as we do in the fork() scenario. The easiest way to do that is to run
276 : : * through the same code as before. (Note that the called routines mostly
277 : : * check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case.
278 : : * This is a bit code-wasteful and could be cleaned up.)
279 : : */
280 : : static void
281 : 898 : CreateOrAttachShmemStructs(void)
282 : : {
283 : : /*
284 : : * Now initialize LWLocks, which do shared memory allocation and are
285 : : * needed for InitShmemIndex.
286 : : */
3730 rhaas@postgresql.org 287 :CBC 898 : CreateLWLocks();
288 : :
289 : : /*
290 : : * Set up shmem.c index hashtable
291 : : */
8233 tgl@sss.pgh.pa.us 292 : 898 : InitShmemIndex();
293 : :
1353 tmunro@postgresql.or 294 : 898 : dsm_shmem_init();
86 nathan@postgresql.or 295 :GNC 898 : DSMRegistryShmemInit();
296 : :
297 : : /*
298 : : * Set up xlog, clog, and buffers
299 : : */
128 heikki.linnakangas@i 300 : 898 : VarsupShmemInit();
8538 tgl@sss.pgh.pa.us 301 :CBC 898 : XLOGShmemInit();
738 tmunro@postgresql.or 302 : 898 : XLogPrefetchShmemInit();
788 heikki.linnakangas@i 303 : 898 : XLogRecoveryShmemInit();
8268 tgl@sss.pgh.pa.us 304 : 898 : CLOGShmemInit();
3420 alvherre@alvh.no-ip. 305 : 898 : CommitTsShmemInit();
7227 tgl@sss.pgh.pa.us 306 : 898 : SUBTRANSShmemInit();
6926 307 : 898 : MultiXactShmemInit();
8538 308 : 898 : InitBufferPool();
309 : :
310 : : /*
311 : : * Set up lock manager
312 : : */
9716 bruce@momjian.us 313 : 898 : InitLocks();
314 : :
315 : : /*
316 : : * Set up predicate lock manager
317 : : */
4815 heikki.linnakangas@i 318 : 898 : InitPredicateLocks();
319 : :
320 : : /*
321 : : * Set up process table
322 : : */
6675 tgl@sss.pgh.pa.us 323 [ + - ]: 898 : if (!IsUnderPostmaster)
324 : 898 : InitProcGlobal();
6876 325 : 898 : CreateSharedProcArray();
6509 326 : 898 : CreateSharedBackendStatus();
4524 rhaas@postgresql.org 327 : 898 : TwoPhaseShmemInit();
3925 328 : 898 : BackgroundWorkerShmemInit();
329 : :
330 : : /*
331 : : * Set up shared-inval messaging
332 : : */
6812 tgl@sss.pgh.pa.us 333 : 898 : CreateSharedInvalidationState();
334 : :
335 : : /*
336 : : * Set up interprocess signaling mechanisms
337 : : */
5458 338 : 898 : PMSignalShmemInit();
5371 339 : 898 : ProcSignalShmemInit();
4358 simon@2ndQuadrant.co 340 : 898 : CheckpointerShmemInit();
6268 alvherre@alvh.no-ip. 341 : 898 : AutoVacuumShmemInit();
3726 rhaas@postgresql.org 342 : 898 : ReplicationSlotsShmemInit();
3273 andres@anarazel.de 343 : 898 : ReplicationOriginShmemInit();
5203 heikki.linnakangas@i 344 : 898 : WalSndShmemInit();
345 : 898 : WalRcvShmemInit();
116 rhaas@postgresql.org 346 :GNC 898 : WalSummarizerShmemInit();
1126 fujii@postgresql.org 347 :CBC 898 : PgArchShmemInit();
2642 peter_e@gmx.net 348 : 898 : ApplyLauncherShmemInit();
60 akapila@postgresql.o 349 :GNC 898 : SlotSyncShmemInit();
350 : :
351 : : /*
352 : : * Set up other modules that need some shared memory space
353 : : */
6551 tgl@sss.pgh.pa.us 354 :CBC 898 : BTreeShmemInit();
6155 355 : 898 : SyncScanShmemInit();
5171 356 : 898 : AsyncShmemInit();
739 andres@anarazel.de 357 : 898 : StatsShmemInit();
258 michael@paquier.xyz 358 :GNC 898 : WaitEventExtensionShmemInit();
83 359 : 898 : InjectionPointShmemInit();
10141 scrappy@hub.org 360 :CBC 898 : }
361 : :
362 : : /*
363 : : * InitializeShmemGUCs
364 : : *
365 : : * This function initializes runtime-computed GUCs related to the amount of
366 : : * shared memory required for the current configuration.
367 : : */
368 : : void
949 michael@paquier.xyz 369 : 779 : InitializeShmemGUCs(void)
370 : : {
371 : : char buf[64];
372 : : Size size_b;
373 : : Size size_mb;
374 : : Size hp_size;
375 : :
376 : : /*
377 : : * Calculate the shared memory size and round up to the nearest megabyte.
378 : : */
379 : 779 : size_b = CalculateShmemSize(NULL);
380 : 779 : size_mb = add_size(size_b, (1024 * 1024) - 1) / (1024 * 1024);
381 : 779 : sprintf(buf, "%zu", size_mb);
676 tgl@sss.pgh.pa.us 382 : 779 : SetConfigOption("shared_memory_size", buf,
383 : : PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
384 : :
385 : : /*
386 : : * Calculate the number of huge pages required.
387 : : */
936 michael@paquier.xyz 388 : 779 : GetHugePageSize(&hp_size, NULL);
389 [ + - ]: 779 : if (hp_size != 0)
390 : : {
391 : : Size hp_required;
392 : :
393 : 779 : hp_required = add_size(size_b / hp_size, 1);
394 : 779 : sprintf(buf, "%zu", hp_required);
676 tgl@sss.pgh.pa.us 395 : 779 : SetConfigOption("shared_memory_size_in_huge_pages", buf,
396 : : PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
397 : : }
949 michael@paquier.xyz 398 : 779 : }
|