1 /*-------------------------------------------------------------------------
2 *
3 * ipci.c
4 * POSTGRES inter-process communication initialization code.
5 *
6 * Portions Copyright (c) 1996-2018, 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/backend_random.h"
48 #include "utils/snapmgr.h"
49
50
51 shmem_startup_hook_type shmem_startup_hook = NULL;
52
53 static Size total_addin_request = 0;
54 static bool addin_request_allowed = true;
55
56
57 /*
58 * RequestAddinShmemSpace
59 * Request that extra shmem space be allocated for use by
60 * a loadable module.
61 *
62 * This is only useful if called from the _PG_init hook of a library that
63 * is loaded into the postmaster via shared_preload_libraries. Once
64 * shared memory has been allocated, calls will be ignored. (We could
65 * raise an error, but it seems better to make it a no-op, so that
66 * libraries containing such calls can be reloaded if needed.)
67 */
68 void
RequestAddinShmemSpace(Size size)69 RequestAddinShmemSpace(Size size)
70 {
71 if (IsUnderPostmaster || !addin_request_allowed)
72 return; /* too late */
73 total_addin_request = add_size(total_addin_request, size);
74 }
75
76
77 /*
78 * CreateSharedMemoryAndSemaphores
79 * Creates and initializes shared memory and semaphores.
80 *
81 * This is called by the postmaster or by a standalone backend.
82 * It is also called by a backend forked from the postmaster in the
83 * EXEC_BACKEND case. In the latter case, the shared memory segment
84 * already exists and has been physically attached to, but we have to
85 * initialize pointers in local memory that reference the shared structures,
86 * because we didn't inherit the correct pointer values from the postmaster
87 * as we do in the fork() scenario. The easiest way to do that is to run
88 * through the same code as before. (Note that the called routines mostly
89 * check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case.
90 * This is a bit code-wasteful and could be cleaned up.)
91 */
92 void
CreateSharedMemoryAndSemaphores(int port)93 CreateSharedMemoryAndSemaphores(int port)
94 {
95 PGShmemHeader *shim = NULL;
96
97 if (!IsUnderPostmaster)
98 {
99 PGShmemHeader *seghdr;
100 Size size;
101 int numSemas;
102
103 /* Compute number of semaphores we'll need */
104 numSemas = ProcGlobalSemas();
105 numSemas += SpinlockSemas();
106
107 /*
108 * Size of the Postgres shared-memory block is estimated via
109 * moderately-accurate estimates for the big hogs, plus 100K for the
110 * stuff that's too small to bother with estimating.
111 *
112 * We take some care during this phase to ensure that the total size
113 * request doesn't overflow size_t. If this gets through, we don't
114 * need to be so careful during the actual allocation phase.
115 */
116 size = 100000;
117 size = add_size(size, PGSemaphoreShmemSize(numSemas));
118 size = add_size(size, SpinlockSemaSize());
119 size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
120 sizeof(ShmemIndexEnt)));
121 size = add_size(size, BufferShmemSize());
122 size = add_size(size, LockShmemSize());
123 size = add_size(size, PredicateLockShmemSize());
124 size = add_size(size, ProcGlobalShmemSize());
125 size = add_size(size, XLOGShmemSize());
126 size = add_size(size, CLOGShmemSize());
127 size = add_size(size, CommitTsShmemSize());
128 size = add_size(size, SUBTRANSShmemSize());
129 size = add_size(size, TwoPhaseShmemSize());
130 size = add_size(size, BackgroundWorkerShmemSize());
131 size = add_size(size, MultiXactShmemSize());
132 size = add_size(size, LWLockShmemSize());
133 size = add_size(size, ProcArrayShmemSize());
134 size = add_size(size, BackendStatusShmemSize());
135 size = add_size(size, SInvalShmemSize());
136 size = add_size(size, PMSignalShmemSize());
137 size = add_size(size, ProcSignalShmemSize());
138 size = add_size(size, CheckpointerShmemSize());
139 size = add_size(size, AutoVacuumShmemSize());
140 size = add_size(size, ReplicationSlotsShmemSize());
141 size = add_size(size, ReplicationOriginShmemSize());
142 size = add_size(size, WalSndShmemSize());
143 size = add_size(size, WalRcvShmemSize());
144 size = add_size(size, ApplyLauncherShmemSize());
145 size = add_size(size, SnapMgrShmemSize());
146 size = add_size(size, BTreeShmemSize());
147 size = add_size(size, SyncScanShmemSize());
148 size = add_size(size, AsyncShmemSize());
149 size = add_size(size, BackendRandomShmemSize());
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 BackendRandomShmemInit();
267
268 #ifdef EXEC_BACKEND
269
270 /*
271 * Alloc the win32 shared backend array
272 */
273 if (!IsUnderPostmaster)
274 ShmemBackendArrayAllocation();
275 #endif
276
277 /* Initialize dynamic shared memory facilities. */
278 if (!IsUnderPostmaster)
279 dsm_postmaster_startup(shim);
280
281 /*
282 * Now give loadable modules a chance to set up their shmem allocations
283 */
284 if (shmem_startup_hook)
285 shmem_startup_hook();
286 }
287