Age Owner 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
6020 tgl 70 GIC 6 : RequestAddinShmemSpace(Size size)
6020 tgl 71 ECB : {
331 rhaas 72 GIC 6 : if (!process_shmem_requests_in_progress)
331 rhaas 73 LBC 0 : elog(FATAL, "cannot request additional shared memory outside shmem_request_hook");
6020 tgl 74 GBC 6 : total_addin_request = add_size(total_addin_request, size);
6020 tgl 75 CBC 6 : }
6020 tgl 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
580 michael 85 GIC 2738 : CalculateShmemSize(int *num_semaphores)
580 michael 86 ECB : {
87 : Size size;
88 : int numSemas;
89 :
90 : /* Compute number of semaphores we'll need */
580 michael 91 GIC 2738 : numSemas = ProcGlobalSemas();
580 michael 92 CBC 2738 : numSemas += SpinlockSemas();
580 michael 93 ECB :
94 : /* Return the number of semaphores if requested by the caller */
580 michael 95 GIC 2738 : if (num_semaphores)
580 michael 96 CBC 1828 : *num_semaphores = numSemas;
580 michael 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 : */
580 michael 107 GIC 2738 : size = 100000;
580 michael 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,
580 michael 111 ECB : sizeof(ShmemIndexEnt)));
580 michael 112 GIC 2738 : size = add_size(size, dsm_estimate_size());
580 michael 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());
367 tmunro 117 2738 : size = add_size(size, XLogPrefetchShmemSize());
580 michael 118 2738 : size = add_size(size, XLOGShmemSize());
417 heikki.linnakangas 119 2738 : size = add_size(size, XLogRecoveryShmemSize());
580 michael 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());
368 andres 144 2738 : size = add_size(size, StatsShmemSize());
580 michael 145 ECB : #ifdef EXEC_BACKEND
146 : size = add_size(size, ShmemBackendArraySize());
147 : #endif
148 :
149 : /* include additional requested shmem from preload libraries */
580 michael 150 GIC 2738 : size = add_size(size, total_addin_request);
580 michael 151 ECB :
152 : /* might as well round it off to a multiple of a typical page size */
580 michael 153 GIC 2738 : size = add_size(size, 8192 - (size % 8192));
580 michael 154 ECB :
580 michael 155 GIC 2738 : return size;
580 michael 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
1312 tgl 174 GIC 1828 : CreateSharedMemoryAndSemaphores(void)
9770 scrappy 175 ECB : {
3288 rhaas 176 GIC 1828 : PGShmemHeader *shim = NULL;
3288 rhaas 177 ECB :
6983 bruce 178 GIC 1828 : if (!IsUnderPostmaster)
6983 bruce 179 ECB : {
180 : PGShmemHeader *seghdr;
181 : Size size;
182 : int numSemas;
183 :
184 : /* Compute the size of the shared-memory block */
580 michael 185 GIC 1828 : size = CalculateShmemSize(&numSemas);
3363 tgl 186 CBC 1828 : elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
6983 bruce 187 ECB :
188 : /*
189 : * Create the shmem segment
190 : */
1312 tgl 191 GIC 1828 : seghdr = PGSharedMemoryCreate(size, &shim);
6983 bruce 192 ECB :
6304 tgl 193 GIC 1826 : InitShmemAccess(seghdr);
6304 tgl 194 ECB :
195 : /*
196 : * Create semaphores
197 : */
1312 tgl 198 GIC 1826 : PGReserveSemaphores(numSemas);
2309 tgl 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
6675 tgl 215 UIC 0 : elog(PANIC, "should be attached to shared memory already");
6890 tgl 216 EUB : #endif
217 : }
218 :
219 : /*
220 : * Set up shared memory allocation mechanism
221 : */
6304 tgl 222 GIC 1826 : if (!IsUnderPostmaster)
6304 tgl 223 CBC 1826 : InitShmemAllocation();
9345 bruce 224 ECB :
225 : /*
226 : * Now initialize LWLocks, which do shared memory allocation and are
227 : * needed for InitShmemIndex.
228 : */
3359 rhaas 229 GIC 1826 : CreateLWLocks();
7862 tgl 230 ECB :
231 : /*
232 : * Set up shmem.c index hashtable
233 : */
7862 tgl 234 GIC 1826 : InitShmemIndex();
7862 tgl 235 ECB :
982 tmunro 236 GIC 1826 : dsm_shmem_init();
982 tmunro 237 ECB :
238 : /*
239 : * Set up xlog, clog, and buffers
240 : */
8167 tgl 241 GIC 1826 : XLOGShmemInit();
367 tmunro 242 CBC 1826 : XLogPrefetchShmemInit();
417 heikki.linnakangas 243 1826 : XLogRecoveryShmemInit();
7897 tgl 244 1826 : CLOGShmemInit();
3049 alvherre 245 1826 : CommitTsShmemInit();
6856 tgl 246 1826 : SUBTRANSShmemInit();
6555 247 1826 : MultiXactShmemInit();
8167 248 1826 : InitBufferPool();
9345 bruce 249 ECB :
250 : /*
251 : * Set up lock manager
252 : */
9345 bruce 253 GIC 1826 : InitLocks();
8167 tgl 254 ECB :
255 : /*
256 : * Set up predicate lock manager
257 : */
4444 heikki.linnakangas 258 GIC 1826 : InitPredicateLocks();
4444 heikki.linnakangas 259 ECB :
260 : /*
261 : * Set up process table
262 : */
6304 tgl 263 GIC 1826 : if (!IsUnderPostmaster)
6304 tgl 264 CBC 1826 : InitProcGlobal();
6505 265 1826 : CreateSharedProcArray();
6138 266 1826 : CreateSharedBackendStatus();
4153 rhaas 267 1826 : TwoPhaseShmemInit();
3554 268 1826 : BackgroundWorkerShmemInit();
9345 bruce 269 ECB :
270 : /*
271 : * Set up shared-inval messaging
272 : */
6441 tgl 273 GIC 1826 : CreateSharedInvalidationState();
7956 tgl 274 ECB :
275 : /*
276 : * Set up interprocess signaling mechanisms
277 : */
5087 tgl 278 GIC 1826 : PMSignalShmemInit();
5000 tgl 279 CBC 1826 : ProcSignalShmemInit();
3987 simon 280 1826 : CheckpointerShmemInit();
5897 alvherre 281 1826 : AutoVacuumShmemInit();
3355 rhaas 282 1826 : ReplicationSlotsShmemInit();
2902 andres 283 1826 : ReplicationOriginShmemInit();
4832 heikki.linnakangas 284 1826 : WalSndShmemInit();
285 1826 : WalRcvShmemInit();
755 fujii 286 1826 : PgArchShmemInit();
2271 peter_e 287 1826 : ApplyLauncherShmemInit();
7013 bruce 288 ECB :
289 : /*
290 : * Set up other modules that need some shared memory space
291 : */
2557 kgrittn 292 GIC 1826 : SnapMgrInit();
6180 tgl 293 CBC 1826 : BTreeShmemInit();
5784 294 1826 : SyncScanShmemInit();
4800 295 1826 : AsyncShmemInit();
368 andres 296 1826 : StatsShmemInit();
6180 tgl 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. */
3469 rhaas 308 GIC 1826 : if (!IsUnderPostmaster)
3288 rhaas 309 CBC 1826 : dsm_postmaster_startup(shim);
3469 rhaas 310 ECB :
311 : /*
312 : * Now give loadable modules a chance to set up their shmem allocations
313 : */
5209 tgl 314 GIC 1826 : if (shmem_startup_hook)
5209 tgl 315 CBC 4 : shmem_startup_hook();
9770 scrappy 316 1826 : }
578 michael 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
578 michael 325 GIC 910 : InitializeShmemGUCs(void)
578 michael 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 : */
578 michael 335 GIC 910 : size_b = CalculateShmemSize(NULL);
578 michael 336 CBC 910 : size_mb = add_size(size_b, (1024 * 1024) - 1) / (1024 * 1024);
337 910 : sprintf(buf, "%zu", size_mb);
305 tgl 338 910 : SetConfigOption("shared_memory_size", buf,
305 tgl 339 ECB : PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
340 :
341 : /*
342 : * Calculate the number of huge pages required.
343 : */
565 michael 344 GIC 910 : GetHugePageSize(&hp_size, NULL);
565 michael 345 CBC 910 : if (hp_size != 0)
565 michael 346 ECB : {
347 : Size hp_required;
348 :
565 michael 349 GIC 910 : hp_required = add_size(size_b / hp_size, 1);
565 michael 350 CBC 910 : sprintf(buf, "%zu", hp_required);
305 tgl 351 910 : SetConfigOption("shared_memory_size_in_huge_pages", buf,
305 tgl 352 ECB : PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
353 : }
578 michael 354 GIC 910 : }
|