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