1/*-------------------------------------------------------------------------
2 *
3 * ipci.c
4 * POSTGRES inter-process communication initialization code.
5 *
6 * Portions Copyright (c) 1996-2019, 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/twophase.h"
24#include "commands/async.h"
25#include "miscadmin.h"
26#include "pgstat.h"
27#include "postmaster/autovacuum.h"
28#include "postmaster/bgworker_internals.h"
29#include "postmaster/bgwriter.h"
30#include "postmaster/postmaster.h"
31#include "replication/logicallauncher.h"
32#include "replication/slot.h"
33#include "replication/walreceiver.h"
34#include "replication/walsender.h"
35#include "replication/origin.h"
36#include "storage/bufmgr.h"
37#include "storage/dsm.h"
38#include "storage/ipc.h"
39#include "storage/pg_shmem.h"
40#include "storage/pmsignal.h"
41#include "storage/predicate.h"
42#include "storage/proc.h"
43#include "storage/procarray.h"
44#include "storage/procsignal.h"
45#include "storage/sinvaladt.h"
46#include "storage/spin.h"
47#include "utils/snapmgr.h"
48
49/* GUCs */
50int shared_memory_type = DEFAULT_SHARED_MEMORY_TYPE;
51
52shmem_startup_hook_type shmem_startup_hook = NULL;
53
54static Size total_addin_request = 0;
55static bool addin_request_allowed = true;
56
57
58/*
59 * RequestAddinShmemSpace
60 * Request that extra shmem space be allocated for use by
61 * a loadable module.
62 *
63 * This is only useful if called from the _PG_init hook of a library that
64 * is loaded into the postmaster via shared_preload_libraries. Once
65 * shared memory has been allocated, calls will be ignored. (We could
66 * raise an error, but it seems better to make it a no-op, so that
67 * libraries containing such calls can be reloaded if needed.)
68 */
69void
70RequestAddinShmemSpace(Size size)
71{
72 if (IsUnderPostmaster || !addin_request_allowed)
73 return; /* too late */
74 total_addin_request = add_size(total_addin_request, size);
75}
76
77
78/*
79 * CreateSharedMemoryAndSemaphores
80 * Creates and initializes shared memory and semaphores.
81 *
82 * This is called by the postmaster or by a standalone backend.
83 * It is also called by a backend forked from the postmaster in the
84 * EXEC_BACKEND case. In the latter case, the shared memory segment
85 * already exists and has been physically attached to, but we have to
86 * initialize pointers in local memory that reference the shared structures,
87 * because we didn't inherit the correct pointer values from the postmaster
88 * as we do in the fork() scenario. The easiest way to do that is to run
89 * through the same code as before. (Note that the called routines mostly
90 * check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case.
91 * This is a bit code-wasteful and could be cleaned up.)
92 */
93void
94CreateSharedMemoryAndSemaphores(int port)
95{
96 PGShmemHeader *shim = NULL;
97
98 if (!IsUnderPostmaster)
99 {
100 PGShmemHeader *seghdr;
101 Size size;
102 int numSemas;
103
104 /* Compute number of semaphores we'll need */
105 numSemas = ProcGlobalSemas();
106 numSemas += SpinlockSemas();
107
108 /*
109 * Size of the Postgres shared-memory block is estimated via
110 * moderately-accurate estimates for the big hogs, plus 100K for the
111 * stuff that's too small to bother with estimating.
112 *
113 * We take some care during this phase to ensure that the total size
114 * request doesn't overflow size_t. If this gets through, we don't
115 * need to be so careful during the actual allocation phase.
116 */
117 size = 100000;
118 size = add_size(size, PGSemaphoreShmemSize(numSemas));
119 size = add_size(size, SpinlockSemaSize());
120 size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
121 sizeof(ShmemIndexEnt)));
122 size = add_size(size, BufferShmemSize());
123 size = add_size(size, LockShmemSize());
124 size = add_size(size, PredicateLockShmemSize());
125 size = add_size(size, ProcGlobalShmemSize());
126 size = add_size(size, XLOGShmemSize());
127 size = add_size(size, CLOGShmemSize());
128 size = add_size(size, CommitTsShmemSize());
129 size = add_size(size, SUBTRANSShmemSize());
130 size = add_size(size, TwoPhaseShmemSize());
131 size = add_size(size, BackgroundWorkerShmemSize());
132 size = add_size(size, MultiXactShmemSize());
133 size = add_size(size, LWLockShmemSize());
134 size = add_size(size, ProcArrayShmemSize());
135 size = add_size(size, BackendStatusShmemSize());
136 size = add_size(size, SInvalShmemSize());
137 size = add_size(size, PMSignalShmemSize());
138 size = add_size(size, ProcSignalShmemSize());
139 size = add_size(size, CheckpointerShmemSize());
140 size = add_size(size, AutoVacuumShmemSize());
141 size = add_size(size, ReplicationSlotsShmemSize());
142 size = add_size(size, ReplicationOriginShmemSize());
143 size = add_size(size, WalSndShmemSize());
144 size = add_size(size, WalRcvShmemSize());
145 size = add_size(size, ApplyLauncherShmemSize());
146 size = add_size(size, SnapMgrShmemSize());
147 size = add_size(size, BTreeShmemSize());
148 size = add_size(size, SyncScanShmemSize());
149 size = add_size(size, AsyncShmemSize());
150#ifdef EXEC_BACKEND
151 size = add_size(size, ShmemBackendArraySize());
152#endif
153
154 /* freeze the addin request size and include it */
155 addin_request_allowed = false;
156 size = add_size(size, total_addin_request);
157
158 /* might as well round it off to a multiple of a typical page size */
159 size = add_size(size, 8192 - (size % 8192));
160
161 elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
162
163 /*
164 * Create the shmem segment
165 */
166 seghdr = PGSharedMemoryCreate(size, port, &shim);
167
168 InitShmemAccess(seghdr);
169
170 /*
171 * Create semaphores
172 */
173 PGReserveSemaphores(numSemas, port);
174
175 /*
176 * If spinlocks are disabled, initialize emulation layer (which
177 * depends on semaphores, so the order is important here).
178 */
179#ifndef HAVE_SPINLOCKS
180 SpinlockSemaInit();
181#endif
182 }
183 else
184 {
185 /*
186 * We are reattaching to an existing shared memory segment. This
187 * should only be reached in the EXEC_BACKEND case.
188 */
189#ifndef EXEC_BACKEND
190 elog(PANIC, "should be attached to shared memory already");
191#endif
192 }
193
194 /*
195 * Set up shared memory allocation mechanism
196 */
197 if (!IsUnderPostmaster)
198 InitShmemAllocation();
199
200 /*
201 * Now initialize LWLocks, which do shared memory allocation and are
202 * needed for InitShmemIndex.
203 */
204 CreateLWLocks();
205
206 /*
207 * Set up shmem.c index hashtable
208 */
209 InitShmemIndex();
210
211 /*
212 * Set up xlog, clog, and buffers
213 */
214 XLOGShmemInit();
215 CLOGShmemInit();
216 CommitTsShmemInit();
217 SUBTRANSShmemInit();
218 MultiXactShmemInit();
219 InitBufferPool();
220
221 /*
222 * Set up lock manager
223 */
224 InitLocks();
225
226 /*
227 * Set up predicate lock manager
228 */
229 InitPredicateLocks();
230
231 /*
232 * Set up process table
233 */
234 if (!IsUnderPostmaster)
235 InitProcGlobal();
236 CreateSharedProcArray();
237 CreateSharedBackendStatus();
238 TwoPhaseShmemInit();
239 BackgroundWorkerShmemInit();
240
241 /*
242 * Set up shared-inval messaging
243 */
244 CreateSharedInvalidationState();
245
246 /*
247 * Set up interprocess signaling mechanisms
248 */
249 PMSignalShmemInit();
250 ProcSignalShmemInit();
251 CheckpointerShmemInit();
252 AutoVacuumShmemInit();
253 ReplicationSlotsShmemInit();
254 ReplicationOriginShmemInit();
255 WalSndShmemInit();
256 WalRcvShmemInit();
257 ApplyLauncherShmemInit();
258
259 /*
260 * Set up other modules that need some shared memory space
261 */
262 SnapMgrInit();
263 BTreeShmemInit();
264 SyncScanShmemInit();
265 AsyncShmemInit();
266
267#ifdef EXEC_BACKEND
268
269 /*
270 * Alloc the win32 shared backend array
271 */
272 if (!IsUnderPostmaster)
273 ShmemBackendArrayAllocation();
274#endif
275
276 /* Initialize dynamic shared memory facilities. */
277 if (!IsUnderPostmaster)
278 dsm_postmaster_startup(shim);
279
280 /*
281 * Now give loadable modules a chance to set up their shmem allocations
282 */
283 if (shmem_startup_hook)
284 shmem_startup_hook();
285}
286