Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * ipci.c
4 : * POSTGRES inter-process communication initialization code.
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/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 "access/xlogwait.h"
28 : #include "commands/async.h"
29 : #include "miscadmin.h"
30 : #include "pgstat.h"
31 : #include "postmaster/autovacuum.h"
32 : #include "postmaster/bgworker_internals.h"
33 : #include "postmaster/bgwriter.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/aio_subsys.h"
42 : #include "storage/bufmgr.h"
43 : #include "storage/dsm.h"
44 : #include "storage/dsm_registry.h"
45 : #include "storage/ipc.h"
46 : #include "storage/pg_shmem.h"
47 : #include "storage/pmsignal.h"
48 : #include "storage/predicate.h"
49 : #include "storage/proc.h"
50 : #include "storage/procarray.h"
51 : #include "storage/procsignal.h"
52 : #include "storage/sinvaladt.h"
53 : #include "utils/guc.h"
54 : #include "utils/injection_point.h"
55 : #include "utils/wait_event.h"
56 :
57 : /* GUCs */
58 : int shared_memory_type = DEFAULT_SHARED_MEMORY_TYPE;
59 :
60 : shmem_startup_hook_type shmem_startup_hook = NULL;
61 :
62 : static Size total_addin_request = 0;
63 :
64 : static void CreateOrAttachShmemStructs(void);
65 :
66 : /*
67 : * RequestAddinShmemSpace
68 : * Request that extra shmem space be allocated for use by
69 : * a loadable module.
70 : *
71 : * This may only be called via the shmem_request_hook of a library that is
72 : * loaded into the postmaster via shared_preload_libraries. Calls from
73 : * elsewhere will fail.
74 : */
75 : void
76 16 : RequestAddinShmemSpace(Size size)
77 : {
78 16 : if (!process_shmem_requests_in_progress)
79 0 : elog(FATAL, "cannot request additional shared memory outside shmem_request_hook");
80 16 : total_addin_request = add_size(total_addin_request, size);
81 16 : }
82 :
83 : /*
84 : * CalculateShmemSize
85 : * Calculates the amount of shared memory needed.
86 : */
87 : Size
88 2207 : CalculateShmemSize(void)
89 : {
90 : Size size;
91 :
92 : /*
93 : * Size of the Postgres shared-memory block is estimated via moderately-
94 : * accurate estimates for the big hogs, plus 100K for the stuff that's too
95 : * small to bother with estimating.
96 : *
97 : * We take some care to ensure that the total size request doesn't
98 : * overflow size_t. If this gets through, we don't need to be so careful
99 : * during the actual allocation phase.
100 : */
101 2207 : size = 100000;
102 2207 : size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
103 : sizeof(ShmemIndexEnt)));
104 2207 : size = add_size(size, dsm_estimate_size());
105 2207 : size = add_size(size, DSMRegistryShmemSize());
106 2207 : size = add_size(size, BufferManagerShmemSize());
107 2207 : size = add_size(size, LockManagerShmemSize());
108 2207 : size = add_size(size, PredicateLockShmemSize());
109 2207 : size = add_size(size, ProcGlobalShmemSize());
110 2207 : size = add_size(size, XLogPrefetchShmemSize());
111 2207 : size = add_size(size, VarsupShmemSize());
112 2207 : size = add_size(size, XLOGShmemSize());
113 2207 : size = add_size(size, XLogRecoveryShmemSize());
114 2207 : size = add_size(size, CLOGShmemSize());
115 2207 : size = add_size(size, CommitTsShmemSize());
116 2207 : size = add_size(size, SUBTRANSShmemSize());
117 2207 : size = add_size(size, TwoPhaseShmemSize());
118 2207 : size = add_size(size, BackgroundWorkerShmemSize());
119 2207 : size = add_size(size, MultiXactShmemSize());
120 2207 : size = add_size(size, LWLockShmemSize());
121 2207 : size = add_size(size, ProcArrayShmemSize());
122 2207 : size = add_size(size, BackendStatusShmemSize());
123 2207 : size = add_size(size, SharedInvalShmemSize());
124 2207 : size = add_size(size, PMSignalShmemSize());
125 2207 : size = add_size(size, ProcSignalShmemSize());
126 2207 : size = add_size(size, CheckpointerShmemSize());
127 2207 : size = add_size(size, AutoVacuumShmemSize());
128 2207 : size = add_size(size, ReplicationSlotsShmemSize());
129 2207 : size = add_size(size, ReplicationOriginShmemSize());
130 2207 : size = add_size(size, WalSndShmemSize());
131 2207 : size = add_size(size, WalRcvShmemSize());
132 2207 : size = add_size(size, WalSummarizerShmemSize());
133 2207 : size = add_size(size, PgArchShmemSize());
134 2207 : size = add_size(size, ApplyLauncherShmemSize());
135 2207 : size = add_size(size, BTreeShmemSize());
136 2207 : size = add_size(size, SyncScanShmemSize());
137 2207 : size = add_size(size, AsyncShmemSize());
138 2207 : size = add_size(size, StatsShmemSize());
139 2207 : size = add_size(size, WaitEventCustomShmemSize());
140 2207 : size = add_size(size, InjectionPointShmemSize());
141 2207 : size = add_size(size, SlotSyncShmemSize());
142 2207 : size = add_size(size, AioShmemSize());
143 2207 : size = add_size(size, WaitLSNShmemSize());
144 2207 : size = add_size(size, LogicalDecodingCtlShmemSize());
145 :
146 : /* include additional requested shmem from preload libraries */
147 2207 : size = add_size(size, total_addin_request);
148 :
149 : /* might as well round it off to a multiple of a typical page size */
150 2207 : size = add_size(size, 8192 - (size % 8192));
151 :
152 2207 : return size;
153 : }
154 :
155 : #ifdef EXEC_BACKEND
156 : /*
157 : * AttachSharedMemoryStructs
158 : * Initialize a postmaster child process's access to shared memory
159 : * structures.
160 : *
161 : * In !EXEC_BACKEND mode, we inherit everything through the fork, and this
162 : * isn't needed.
163 : */
164 : void
165 : AttachSharedMemoryStructs(void)
166 : {
167 : /* InitProcess must've been called already */
168 : Assert(MyProc != NULL);
169 : Assert(IsUnderPostmaster);
170 :
171 : /*
172 : * In EXEC_BACKEND mode, backends don't inherit the number of fast-path
173 : * groups we calculated before setting the shmem up, so recalculate it.
174 : */
175 : InitializeFastPathLocks();
176 :
177 : CreateOrAttachShmemStructs();
178 :
179 : /*
180 : * Now give loadable modules a chance to set up their shmem allocations
181 : */
182 : if (shmem_startup_hook)
183 : shmem_startup_hook();
184 : }
185 : #endif
186 :
187 : /*
188 : * CreateSharedMemoryAndSemaphores
189 : * Creates and initializes shared memory and semaphores.
190 : */
191 : void
192 1182 : CreateSharedMemoryAndSemaphores(void)
193 : {
194 : PGShmemHeader *shim;
195 : PGShmemHeader *seghdr;
196 : Size size;
197 :
198 : Assert(!IsUnderPostmaster);
199 :
200 : /* Compute the size of the shared-memory block */
201 1182 : size = CalculateShmemSize();
202 1182 : elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
203 :
204 : /*
205 : * Create the shmem segment
206 : */
207 1182 : seghdr = PGSharedMemoryCreate(size, &shim);
208 :
209 : /*
210 : * Make sure that huge pages are never reported as "unknown" while the
211 : * server is running.
212 : */
213 : Assert(strcmp("unknown",
214 : GetConfigOption("huge_pages_status", false, false)) != 0);
215 :
216 : /*
217 : * Set up shared memory allocation mechanism
218 : */
219 1180 : InitShmemAllocator(seghdr);
220 :
221 : /* Initialize subsystems */
222 1180 : CreateOrAttachShmemStructs();
223 :
224 : /* Initialize dynamic shared memory facilities. */
225 1180 : dsm_postmaster_startup(shim);
226 :
227 : /*
228 : * Now give loadable modules a chance to set up their shmem allocations
229 : */
230 1180 : if (shmem_startup_hook)
231 14 : shmem_startup_hook();
232 1180 : }
233 :
234 : /*
235 : * Initialize various subsystems, setting up their data structures in
236 : * shared memory.
237 : *
238 : * This is called by the postmaster or by a standalone backend.
239 : * It is also called by a backend forked from the postmaster in the
240 : * EXEC_BACKEND case. In the latter case, the shared memory segment
241 : * already exists and has been physically attached to, but we have to
242 : * initialize pointers in local memory that reference the shared structures,
243 : * because we didn't inherit the correct pointer values from the postmaster
244 : * as we do in the fork() scenario. The easiest way to do that is to run
245 : * through the same code as before. (Note that the called routines mostly
246 : * check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case.
247 : * This is a bit code-wasteful and could be cleaned up.)
248 : */
249 : static void
250 1180 : CreateOrAttachShmemStructs(void)
251 : {
252 : /*
253 : * Now initialize LWLocks, which do shared memory allocation and are
254 : * needed for InitShmemIndex.
255 : */
256 1180 : CreateLWLocks();
257 :
258 : /*
259 : * Set up shmem.c index hashtable
260 : */
261 1180 : InitShmemIndex();
262 :
263 1180 : dsm_shmem_init();
264 1180 : DSMRegistryShmemInit();
265 :
266 : /*
267 : * Set up xlog, clog, and buffers
268 : */
269 1180 : VarsupShmemInit();
270 1180 : XLOGShmemInit();
271 1180 : XLogPrefetchShmemInit();
272 1180 : XLogRecoveryShmemInit();
273 1180 : CLOGShmemInit();
274 1180 : CommitTsShmemInit();
275 1180 : SUBTRANSShmemInit();
276 1180 : MultiXactShmemInit();
277 1180 : BufferManagerShmemInit();
278 :
279 : /*
280 : * Set up lock manager
281 : */
282 1180 : LockManagerShmemInit();
283 :
284 : /*
285 : * Set up predicate lock manager
286 : */
287 1180 : PredicateLockShmemInit();
288 :
289 : /*
290 : * Set up process table
291 : */
292 1180 : if (!IsUnderPostmaster)
293 1180 : InitProcGlobal();
294 1180 : ProcArrayShmemInit();
295 1180 : BackendStatusShmemInit();
296 1180 : TwoPhaseShmemInit();
297 1180 : BackgroundWorkerShmemInit();
298 :
299 : /*
300 : * Set up shared-inval messaging
301 : */
302 1180 : SharedInvalShmemInit();
303 :
304 : /*
305 : * Set up interprocess signaling mechanisms
306 : */
307 1180 : PMSignalShmemInit();
308 1180 : ProcSignalShmemInit();
309 1180 : CheckpointerShmemInit();
310 1180 : AutoVacuumShmemInit();
311 1180 : ReplicationSlotsShmemInit();
312 1180 : ReplicationOriginShmemInit();
313 1180 : WalSndShmemInit();
314 1180 : WalRcvShmemInit();
315 1180 : WalSummarizerShmemInit();
316 1180 : PgArchShmemInit();
317 1180 : ApplyLauncherShmemInit();
318 1180 : SlotSyncShmemInit();
319 :
320 : /*
321 : * Set up other modules that need some shared memory space
322 : */
323 1180 : BTreeShmemInit();
324 1180 : SyncScanShmemInit();
325 1180 : AsyncShmemInit();
326 1180 : StatsShmemInit();
327 1180 : WaitEventCustomShmemInit();
328 1180 : InjectionPointShmemInit();
329 1180 : AioShmemInit();
330 1180 : WaitLSNShmemInit();
331 1180 : LogicalDecodingCtlShmemInit();
332 1180 : }
333 :
334 : /*
335 : * InitializeShmemGUCs
336 : *
337 : * This function initializes runtime-computed GUCs related to the amount of
338 : * shared memory required for the current configuration.
339 : */
340 : void
341 1025 : InitializeShmemGUCs(void)
342 : {
343 : char buf[64];
344 : Size size_b;
345 : Size size_mb;
346 : Size hp_size;
347 :
348 : /*
349 : * Calculate the shared memory size and round up to the nearest megabyte.
350 : */
351 1025 : size_b = CalculateShmemSize();
352 1025 : size_mb = add_size(size_b, (1024 * 1024) - 1) / (1024 * 1024);
353 1025 : sprintf(buf, "%zu", size_mb);
354 1025 : SetConfigOption("shared_memory_size", buf,
355 : PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
356 :
357 : /*
358 : * Calculate the number of huge pages required.
359 : */
360 1025 : GetHugePageSize(&hp_size, NULL);
361 1025 : if (hp_size != 0)
362 : {
363 : Size hp_required;
364 :
365 1025 : hp_required = size_b / hp_size;
366 1025 : if (size_b % hp_size != 0)
367 1025 : hp_required = add_size(hp_required, 1);
368 1025 : sprintf(buf, "%zu", hp_required);
369 1025 : SetConfigOption("shared_memory_size_in_huge_pages", buf,
370 : PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
371 : }
372 :
373 1025 : sprintf(buf, "%d", ProcGlobalSemas());
374 1025 : SetConfigOption("num_os_semaphores", buf, PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
375 1025 : }
|