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-2025, 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/walsummarizer.h"
34 : : #include "replication/logicallauncher.h"
35 : : #include "replication/origin.h"
36 : : #include "replication/slot.h"
37 : : #include "replication/slotsync.h"
38 : : #include "replication/walreceiver.h"
39 : : #include "replication/walsender.h"
40 : : #include "storage/aio_subsys.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 "utils/guc.h"
53 : : #include "utils/injection_point.h"
54 : :
55 : : /* GUCs */
56 : : int shared_memory_type = DEFAULT_SHARED_MEMORY_TYPE;
57 : :
58 : : shmem_startup_hook_type shmem_startup_hook = NULL;
59 : :
60 : : static Size total_addin_request = 0;
61 : :
62 : : static void CreateOrAttachShmemStructs(void);
63 : :
64 : : /*
65 : : * RequestAddinShmemSpace
66 : : * Request that extra shmem space be allocated for use by
67 : : * a loadable module.
68 : : *
69 : : * This may only be called via the shmem_request_hook of a library that is
70 : : * loaded into the postmaster via shared_preload_libraries. Calls from
71 : : * elsewhere will fail.
72 : : */
73 : : void
6901 tgl@sss.pgh.pa.us 74 :CBC 11 : RequestAddinShmemSpace(Size size)
75 : : {
1212 rhaas@postgresql.org 76 [ - + ]: 11 : if (!process_shmem_requests_in_progress)
1212 rhaas@postgresql.org 77 [ # # ]:UBC 0 : elog(FATAL, "cannot request additional shared memory outside shmem_request_hook");
6901 tgl@sss.pgh.pa.us 78 :CBC 11 : total_addin_request = add_size(total_addin_request, size);
79 : 11 : }
80 : :
81 : : /*
82 : : * CalculateShmemSize
83 : : * Calculates the amount of shared memory and number of semaphores needed.
84 : : *
85 : : * If num_semaphores is not NULL, it will be set to the number of semaphores
86 : : * required.
87 : : */
88 : : Size
1461 michael@paquier.xyz 89 : 1909 : CalculateShmemSize(int *num_semaphores)
90 : : {
91 : : Size size;
92 : : int numSemas;
93 : :
94 : : /* Compute number of semaphores we'll need */
95 : 1909 : numSemas = ProcGlobalSemas();
96 : :
97 : : /* Return the number of semaphores if requested by the caller */
98 [ + - ]: 1909 : if (num_semaphores)
99 : 1909 : *num_semaphores = numSemas;
100 : :
101 : : /*
102 : : * Size of the Postgres shared-memory block is estimated via moderately-
103 : : * accurate estimates for the big hogs, plus 100K for the stuff that's too
104 : : * small to bother with estimating.
105 : : *
106 : : * We take some care to ensure that the total size request doesn't
107 : : * overflow size_t. If this gets through, we don't need to be so careful
108 : : * during the actual allocation phase.
109 : : */
110 : 1909 : size = 100000;
111 : 1909 : size = add_size(size, PGSemaphoreShmemSize(numSemas));
112 : 1909 : size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
113 : : sizeof(ShmemIndexEnt)));
114 : 1909 : size = add_size(size, dsm_estimate_size());
596 nathan@postgresql.or 115 : 1909 : size = add_size(size, DSMRegistryShmemSize());
373 heikki.linnakangas@i 116 : 1909 : size = add_size(size, BufferManagerShmemSize());
117 : 1909 : size = add_size(size, LockManagerShmemSize());
1461 michael@paquier.xyz 118 : 1909 : size = add_size(size, PredicateLockShmemSize());
119 : 1909 : size = add_size(size, ProcGlobalShmemSize());
1248 tmunro@postgresql.or 120 : 1909 : size = add_size(size, XLogPrefetchShmemSize());
638 heikki.linnakangas@i 121 : 1909 : size = add_size(size, VarsupShmemSize());
1461 michael@paquier.xyz 122 : 1909 : size = add_size(size, XLOGShmemSize());
1298 heikki.linnakangas@i 123 : 1909 : size = add_size(size, XLogRecoveryShmemSize());
1461 michael@paquier.xyz 124 : 1909 : size = add_size(size, CLOGShmemSize());
125 : 1909 : size = add_size(size, CommitTsShmemSize());
126 : 1909 : size = add_size(size, SUBTRANSShmemSize());
127 : 1909 : size = add_size(size, TwoPhaseShmemSize());
128 : 1909 : size = add_size(size, BackgroundWorkerShmemSize());
129 : 1909 : size = add_size(size, MultiXactShmemSize());
130 : 1909 : size = add_size(size, LWLockShmemSize());
131 : 1909 : size = add_size(size, ProcArrayShmemSize());
132 : 1909 : size = add_size(size, BackendStatusShmemSize());
373 heikki.linnakangas@i 133 : 1909 : size = add_size(size, SharedInvalShmemSize());
1461 michael@paquier.xyz 134 : 1909 : size = add_size(size, PMSignalShmemSize());
135 : 1909 : size = add_size(size, ProcSignalShmemSize());
136 : 1909 : size = add_size(size, CheckpointerShmemSize());
137 : 1909 : size = add_size(size, AutoVacuumShmemSize());
138 : 1909 : size = add_size(size, ReplicationSlotsShmemSize());
139 : 1909 : size = add_size(size, ReplicationOriginShmemSize());
140 : 1909 : size = add_size(size, WalSndShmemSize());
141 : 1909 : size = add_size(size, WalRcvShmemSize());
626 rhaas@postgresql.org 142 : 1909 : size = add_size(size, WalSummarizerShmemSize());
1461 michael@paquier.xyz 143 : 1909 : size = add_size(size, PgArchShmemSize());
144 : 1909 : size = add_size(size, ApplyLauncherShmemSize());
145 : 1909 : size = add_size(size, BTreeShmemSize());
146 : 1909 : size = add_size(size, SyncScanShmemSize());
147 : 1909 : size = add_size(size, AsyncShmemSize());
1249 andres@anarazel.de 148 : 1909 : size = add_size(size, StatsShmemSize());
436 noah@leadboat.com 149 : 1909 : size = add_size(size, WaitEventCustomShmemSize());
593 michael@paquier.xyz 150 : 1909 : size = add_size(size, InjectionPointShmemSize());
570 akapila@postgresql.o 151 : 1909 : size = add_size(size, SlotSyncShmemSize());
173 andres@anarazel.de 152 : 1909 : size = add_size(size, AioShmemSize());
153 : :
154 : : /* include additional requested shmem from preload libraries */
1461 michael@paquier.xyz 155 : 1909 : size = add_size(size, total_addin_request);
156 : :
157 : : /* might as well round it off to a multiple of a typical page size */
158 : 1909 : size = add_size(size, 8192 - (size % 8192));
159 : :
160 : 1909 : return size;
161 : : }
162 : :
163 : : #ifdef EXEC_BACKEND
164 : : /*
165 : : * AttachSharedMemoryStructs
166 : : * Initialize a postmaster child process's access to shared memory
167 : : * structures.
168 : : *
169 : : * In !EXEC_BACKEND mode, we inherit everything through the fork, and this
170 : : * isn't needed.
171 : : */
172 : : void
173 : : AttachSharedMemoryStructs(void)
174 : : {
175 : : /* InitProcess must've been called already */
176 : : Assert(MyProc != NULL);
177 : : Assert(IsUnderPostmaster);
178 : :
179 : : /*
180 : : * In EXEC_BACKEND mode, backends don't inherit the number of fast-path
181 : : * groups we calculated before setting the shmem up, so recalculate it.
182 : : */
183 : : InitializeFastPathLocks();
184 : :
185 : : CreateOrAttachShmemStructs();
186 : :
187 : : /*
188 : : * Now give loadable modules a chance to set up their shmem allocations
189 : : */
190 : : if (shmem_startup_hook)
191 : : shmem_startup_hook();
192 : : }
193 : : #endif
194 : :
195 : : /*
196 : : * CreateSharedMemoryAndSemaphores
197 : : * Creates and initializes shared memory and semaphores.
198 : : */
199 : : void
643 heikki.linnakangas@i 200 : 1031 : CreateSharedMemoryAndSemaphores(void)
201 : : {
202 : : PGShmemHeader *shim;
203 : : PGShmemHeader *seghdr;
204 : : Size size;
205 : : int numSemas;
206 : :
207 [ - + ]: 1031 : Assert(!IsUnderPostmaster);
208 : :
209 : : /* Compute the size of the shared-memory block */
210 : 1031 : size = CalculateShmemSize(&numSemas);
211 [ + + ]: 1031 : elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
212 : :
213 : : /*
214 : : * Create the shmem segment
215 : : */
216 : 1031 : seghdr = PGSharedMemoryCreate(size, &shim);
217 : :
218 : : /*
219 : : * Make sure that huge pages are never reported as "unknown" while the
220 : : * server is running.
221 : : */
222 [ - + ]: 1029 : Assert(strcmp("unknown",
223 : : GetConfigOption("huge_pages_status", false, false)) != 0);
224 : :
225 : 1029 : InitShmemAccess(seghdr);
226 : :
227 : : /*
228 : : * Create semaphores
229 : : */
230 : 1029 : PGReserveSemaphores(numSemas);
231 : :
232 : : /*
233 : : * Set up shared memory allocation mechanism
234 : : */
235 : 1029 : InitShmemAllocation();
236 : :
237 : : /* Initialize subsystems */
238 : 1029 : CreateOrAttachShmemStructs();
239 : :
240 : : /* Initialize dynamic shared memory facilities. */
241 : 1029 : dsm_postmaster_startup(shim);
242 : :
243 : : /*
244 : : * Now give loadable modules a chance to set up their shmem allocations
245 : : */
246 [ + + ]: 1029 : if (shmem_startup_hook)
247 : 11 : shmem_startup_hook();
248 : 1029 : }
249 : :
250 : : /*
251 : : * Initialize various subsystems, setting up their data structures in
252 : : * shared memory.
253 : : *
254 : : * This is called by the postmaster or by a standalone backend.
255 : : * It is also called by a backend forked from the postmaster in the
256 : : * EXEC_BACKEND case. In the latter case, the shared memory segment
257 : : * already exists and has been physically attached to, but we have to
258 : : * initialize pointers in local memory that reference the shared structures,
259 : : * because we didn't inherit the correct pointer values from the postmaster
260 : : * as we do in the fork() scenario. The easiest way to do that is to run
261 : : * through the same code as before. (Note that the called routines mostly
262 : : * check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case.
263 : : * This is a bit code-wasteful and could be cleaned up.)
264 : : */
265 : : static void
266 : 1029 : CreateOrAttachShmemStructs(void)
267 : : {
268 : : /*
269 : : * Now initialize LWLocks, which do shared memory allocation and are
270 : : * needed for InitShmemIndex.
271 : : */
4240 rhaas@postgresql.org 272 : 1029 : CreateLWLocks();
273 : :
274 : : /*
275 : : * Set up shmem.c index hashtable
276 : : */
8743 tgl@sss.pgh.pa.us 277 : 1029 : InitShmemIndex();
278 : :
1863 tmunro@postgresql.or 279 : 1029 : dsm_shmem_init();
596 nathan@postgresql.or 280 : 1029 : DSMRegistryShmemInit();
281 : :
282 : : /*
283 : : * Set up xlog, clog, and buffers
284 : : */
638 heikki.linnakangas@i 285 : 1029 : VarsupShmemInit();
9048 tgl@sss.pgh.pa.us 286 : 1029 : XLOGShmemInit();
1248 tmunro@postgresql.or 287 : 1029 : XLogPrefetchShmemInit();
1298 heikki.linnakangas@i 288 : 1029 : XLogRecoveryShmemInit();
8778 tgl@sss.pgh.pa.us 289 : 1029 : CLOGShmemInit();
3930 alvherre@alvh.no-ip. 290 : 1029 : CommitTsShmemInit();
7737 tgl@sss.pgh.pa.us 291 : 1029 : SUBTRANSShmemInit();
7436 292 : 1029 : MultiXactShmemInit();
373 heikki.linnakangas@i 293 : 1029 : BufferManagerShmemInit();
294 : :
295 : : /*
296 : : * Set up lock manager
297 : : */
298 : 1029 : LockManagerShmemInit();
299 : :
300 : : /*
301 : : * Set up predicate lock manager
302 : : */
303 : 1029 : PredicateLockShmemInit();
304 : :
305 : : /*
306 : : * Set up process table
307 : : */
7185 tgl@sss.pgh.pa.us 308 [ + - ]: 1029 : if (!IsUnderPostmaster)
309 : 1029 : InitProcGlobal();
373 heikki.linnakangas@i 310 : 1029 : ProcArrayShmemInit();
311 : 1029 : BackendStatusShmemInit();
5034 rhaas@postgresql.org 312 : 1029 : TwoPhaseShmemInit();
4435 313 : 1029 : BackgroundWorkerShmemInit();
314 : :
315 : : /*
316 : : * Set up shared-inval messaging
317 : : */
373 heikki.linnakangas@i 318 : 1029 : SharedInvalShmemInit();
319 : :
320 : : /*
321 : : * Set up interprocess signaling mechanisms
322 : : */
5968 tgl@sss.pgh.pa.us 323 : 1029 : PMSignalShmemInit();
5881 324 : 1029 : ProcSignalShmemInit();
4868 simon@2ndQuadrant.co 325 : 1029 : CheckpointerShmemInit();
6778 alvherre@alvh.no-ip. 326 : 1029 : AutoVacuumShmemInit();
4236 rhaas@postgresql.org 327 : 1029 : ReplicationSlotsShmemInit();
3783 andres@anarazel.de 328 : 1029 : ReplicationOriginShmemInit();
5713 heikki.linnakangas@i 329 : 1029 : WalSndShmemInit();
330 : 1029 : WalRcvShmemInit();
626 rhaas@postgresql.org 331 : 1029 : WalSummarizerShmemInit();
1636 fujii@postgresql.org 332 : 1029 : PgArchShmemInit();
3152 peter_e@gmx.net 333 : 1029 : ApplyLauncherShmemInit();
570 akapila@postgresql.o 334 : 1029 : SlotSyncShmemInit();
335 : :
336 : : /*
337 : : * Set up other modules that need some shared memory space
338 : : */
7061 tgl@sss.pgh.pa.us 339 : 1029 : BTreeShmemInit();
6665 340 : 1029 : SyncScanShmemInit();
5681 341 : 1029 : AsyncShmemInit();
1249 andres@anarazel.de 342 : 1029 : StatsShmemInit();
436 noah@leadboat.com 343 : 1029 : WaitEventCustomShmemInit();
593 michael@paquier.xyz 344 : 1029 : InjectionPointShmemInit();
173 andres@anarazel.de 345 : 1029 : AioShmemInit();
10651 scrappy@hub.org 346 : 1029 : }
347 : :
348 : : /*
349 : : * InitializeShmemGUCs
350 : : *
351 : : * This function initializes runtime-computed GUCs related to the amount of
352 : : * shared memory required for the current configuration.
353 : : */
354 : : void
1459 michael@paquier.xyz 355 : 878 : InitializeShmemGUCs(void)
356 : : {
357 : : char buf[64];
358 : : Size size_b;
359 : : Size size_mb;
360 : : Size hp_size;
361 : : int num_semas;
362 : :
363 : : /*
364 : : * Calculate the shared memory size and round up to the nearest megabyte.
365 : : */
407 nathan@postgresql.or 366 : 878 : size_b = CalculateShmemSize(&num_semas);
1459 michael@paquier.xyz 367 : 878 : size_mb = add_size(size_b, (1024 * 1024) - 1) / (1024 * 1024);
368 : 878 : sprintf(buf, "%zu", size_mb);
1186 tgl@sss.pgh.pa.us 369 : 878 : SetConfigOption("shared_memory_size", buf,
370 : : PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
371 : :
372 : : /*
373 : : * Calculate the number of huge pages required.
374 : : */
1446 michael@paquier.xyz 375 : 878 : GetHugePageSize(&hp_size, NULL);
376 [ + - ]: 878 : if (hp_size != 0)
377 : : {
378 : : Size hp_required;
379 : :
380 : 878 : hp_required = add_size(size_b / hp_size, 1);
381 : 878 : sprintf(buf, "%zu", hp_required);
1186 tgl@sss.pgh.pa.us 382 : 878 : SetConfigOption("shared_memory_size_in_huge_pages", buf,
383 : : PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
384 : : }
385 : :
407 nathan@postgresql.or 386 : 878 : sprintf(buf, "%d", num_semas);
387 : 878 : SetConfigOption("num_os_semaphores", buf, PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
1459 michael@paquier.xyz 388 : 878 : }
|