Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * ipci.c
4 : * POSTGRES inter-process communication initialization code.
5 : *
6 : * Portions Copyright (c) 1996-2017, 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
69 0 : RequestAddinShmemSpace(Size size)
70 : {
71 0 : if (IsUnderPostmaster || !addin_request_allowed)
72 0 : return; /* too late */
73 0 : 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 : * If "makePrivate" is true then we only need private memory, not shared
93 : * memory. This is true for a standalone backend, false for a postmaster.
94 : */
95 : void
96 5 : CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
97 : {
98 5 : PGShmemHeader *shim = NULL;
99 :
100 5 : if (!IsUnderPostmaster)
101 : {
102 : PGShmemHeader *seghdr;
103 : Size size;
104 : int numSemas;
105 :
106 : /* Compute number of semaphores we'll need */
107 5 : numSemas = ProcGlobalSemas();
108 5 : numSemas += SpinlockSemas();
109 :
110 : /*
111 : * Size of the Postgres shared-memory block is estimated via
112 : * moderately-accurate estimates for the big hogs, plus 100K for the
113 : * stuff that's too small to bother with estimating.
114 : *
115 : * We take some care during this phase to ensure that the total size
116 : * request doesn't overflow size_t. If this gets through, we don't
117 : * need to be so careful during the actual allocation phase.
118 : */
119 5 : size = 100000;
120 5 : size = add_size(size, PGSemaphoreShmemSize(numSemas));
121 5 : size = add_size(size, SpinlockSemaSize());
122 5 : size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
123 : sizeof(ShmemIndexEnt)));
124 5 : size = add_size(size, BufferShmemSize());
125 5 : size = add_size(size, LockShmemSize());
126 5 : size = add_size(size, PredicateLockShmemSize());
127 5 : size = add_size(size, ProcGlobalShmemSize());
128 5 : size = add_size(size, XLOGShmemSize());
129 5 : size = add_size(size, CLOGShmemSize());
130 5 : size = add_size(size, CommitTsShmemSize());
131 5 : size = add_size(size, SUBTRANSShmemSize());
132 5 : size = add_size(size, TwoPhaseShmemSize());
133 5 : size = add_size(size, BackgroundWorkerShmemSize());
134 5 : size = add_size(size, MultiXactShmemSize());
135 5 : size = add_size(size, LWLockShmemSize());
136 5 : size = add_size(size, ProcArrayShmemSize());
137 5 : size = add_size(size, BackendStatusShmemSize());
138 5 : size = add_size(size, SInvalShmemSize());
139 5 : size = add_size(size, PMSignalShmemSize());
140 5 : size = add_size(size, ProcSignalShmemSize());
141 5 : size = add_size(size, CheckpointerShmemSize());
142 5 : size = add_size(size, AutoVacuumShmemSize());
143 5 : size = add_size(size, ReplicationSlotsShmemSize());
144 5 : size = add_size(size, ReplicationOriginShmemSize());
145 5 : size = add_size(size, WalSndShmemSize());
146 5 : size = add_size(size, WalRcvShmemSize());
147 5 : size = add_size(size, ApplyLauncherShmemSize());
148 5 : size = add_size(size, SnapMgrShmemSize());
149 5 : size = add_size(size, BTreeShmemSize());
150 5 : size = add_size(size, SyncScanShmemSize());
151 5 : size = add_size(size, AsyncShmemSize());
152 5 : size = add_size(size, BackendRandomShmemSize());
153 : #ifdef EXEC_BACKEND
154 : size = add_size(size, ShmemBackendArraySize());
155 : #endif
156 :
157 : /* freeze the addin request size and include it */
158 5 : addin_request_allowed = false;
159 5 : size = add_size(size, total_addin_request);
160 :
161 : /* might as well round it off to a multiple of a typical page size */
162 5 : size = add_size(size, 8192 - (size % 8192));
163 :
164 5 : elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
165 :
166 : /*
167 : * Create the shmem segment
168 : */
169 5 : seghdr = PGSharedMemoryCreate(size, makePrivate, port, &shim);
170 :
171 5 : InitShmemAccess(seghdr);
172 :
173 : /*
174 : * Create semaphores
175 : */
176 5 : PGReserveSemaphores(numSemas, port);
177 :
178 : /*
179 : * If spinlocks are disabled, initialize emulation layer (which
180 : * depends on semaphores, so the order is important here).
181 : */
182 : #ifndef HAVE_SPINLOCKS
183 : SpinlockSemaInit();
184 : #endif
185 : }
186 : else
187 : {
188 : /*
189 : * We are reattaching to an existing shared memory segment. This
190 : * should only be reached in the EXEC_BACKEND case, and even then only
191 : * with makePrivate == false.
192 : */
193 : #ifdef EXEC_BACKEND
194 : Assert(!makePrivate);
195 : #else
196 0 : elog(PANIC, "should be attached to shared memory already");
197 : #endif
198 : }
199 :
200 : /*
201 : * Set up shared memory allocation mechanism
202 : */
203 5 : if (!IsUnderPostmaster)
204 5 : InitShmemAllocation();
205 :
206 : /*
207 : * Now initialize LWLocks, which do shared memory allocation and are
208 : * needed for InitShmemIndex.
209 : */
210 5 : CreateLWLocks();
211 :
212 : /*
213 : * Set up shmem.c index hashtable
214 : */
215 5 : InitShmemIndex();
216 :
217 : /*
218 : * Set up xlog, clog, and buffers
219 : */
220 5 : XLOGShmemInit();
221 5 : CLOGShmemInit();
222 5 : CommitTsShmemInit();
223 5 : SUBTRANSShmemInit();
224 5 : MultiXactShmemInit();
225 5 : InitBufferPool();
226 :
227 : /*
228 : * Set up lock manager
229 : */
230 5 : InitLocks();
231 :
232 : /*
233 : * Set up predicate lock manager
234 : */
235 5 : InitPredicateLocks();
236 :
237 : /*
238 : * Set up process table
239 : */
240 5 : if (!IsUnderPostmaster)
241 5 : InitProcGlobal();
242 5 : CreateSharedProcArray();
243 5 : CreateSharedBackendStatus();
244 5 : TwoPhaseShmemInit();
245 5 : BackgroundWorkerShmemInit();
246 :
247 : /*
248 : * Set up shared-inval messaging
249 : */
250 5 : CreateSharedInvalidationState();
251 :
252 : /*
253 : * Set up interprocess signaling mechanisms
254 : */
255 5 : PMSignalShmemInit();
256 5 : ProcSignalShmemInit();
257 5 : CheckpointerShmemInit();
258 5 : AutoVacuumShmemInit();
259 5 : ReplicationSlotsShmemInit();
260 5 : ReplicationOriginShmemInit();
261 5 : WalSndShmemInit();
262 5 : WalRcvShmemInit();
263 5 : ApplyLauncherShmemInit();
264 :
265 : /*
266 : * Set up other modules that need some shared memory space
267 : */
268 5 : SnapMgrInit();
269 5 : BTreeShmemInit();
270 5 : SyncScanShmemInit();
271 5 : AsyncShmemInit();
272 5 : BackendRandomShmemInit();
273 :
274 : #ifdef EXEC_BACKEND
275 :
276 : /*
277 : * Alloc the win32 shared backend array
278 : */
279 : if (!IsUnderPostmaster)
280 : ShmemBackendArrayAllocation();
281 : #endif
282 :
283 : /* Initialize dynamic shared memory facilities. */
284 5 : if (!IsUnderPostmaster)
285 5 : dsm_postmaster_startup(shim);
286 :
287 : /*
288 : * Now give loadable modules a chance to set up their shmem allocations
289 : */
290 5 : if (shmem_startup_hook)
291 0 : shmem_startup_hook();
292 5 : }
|