OSDN Git Service

Simplify Windows implementation of latches. There's no need to keep a
[pg-rex/syncrep.git] / src / backend / storage / ipc / ipci.c
1 /*-------------------------------------------------------------------------
2  *
3  * ipci.c
4  *        POSTGRES inter-process communication initialization code.
5  *
6  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.106 2010/09/15 10:06:21 heikki Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include "access/clog.h"
18 #include "access/heapam.h"
19 #include "access/multixact.h"
20 #include "access/nbtree.h"
21 #include "access/subtrans.h"
22 #include "access/twophase.h"
23 #include "commands/async.h"
24 #include "miscadmin.h"
25 #include "pgstat.h"
26 #include "postmaster/autovacuum.h"
27 #include "postmaster/bgwriter.h"
28 #include "postmaster/postmaster.h"
29 #include "replication/walreceiver.h"
30 #include "replication/walsender.h"
31 #include "storage/bufmgr.h"
32 #include "storage/ipc.h"
33 #include "storage/pg_shmem.h"
34 #include "storage/pmsignal.h"
35 #include "storage/procarray.h"
36 #include "storage/procsignal.h"
37 #include "storage/sinvaladt.h"
38 #include "storage/spin.h"
39
40
41 shmem_startup_hook_type shmem_startup_hook = NULL;
42
43 static Size total_addin_request = 0;
44 static bool addin_request_allowed = true;
45
46
47 /*
48  * RequestAddinShmemSpace
49  *              Request that extra shmem space be allocated for use by
50  *              a loadable module.
51  *
52  * This is only useful if called from the _PG_init hook of a library that
53  * is loaded into the postmaster via shared_preload_libraries.  Once
54  * shared memory has been allocated, calls will be ignored.  (We could
55  * raise an error, but it seems better to make it a no-op, so that
56  * libraries containing such calls can be reloaded if needed.)
57  */
58 void
59 RequestAddinShmemSpace(Size size)
60 {
61         if (IsUnderPostmaster || !addin_request_allowed)
62                 return;                                 /* too late */
63         total_addin_request = add_size(total_addin_request, size);
64 }
65
66
67 /*
68  * CreateSharedMemoryAndSemaphores
69  *              Creates and initializes shared memory and semaphores.
70  *
71  * This is called by the postmaster or by a standalone backend.
72  * It is also called by a backend forked from the postmaster in the
73  * EXEC_BACKEND case.  In the latter case, the shared memory segment
74  * already exists and has been physically attached to, but we have to
75  * initialize pointers in local memory that reference the shared structures,
76  * because we didn't inherit the correct pointer values from the postmaster
77  * as we do in the fork() scenario.  The easiest way to do that is to run
78  * through the same code as before.  (Note that the called routines mostly
79  * check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case.
80  * This is a bit code-wasteful and could be cleaned up.)
81  *
82  * If "makePrivate" is true then we only need private memory, not shared
83  * memory.      This is true for a standalone backend, false for a postmaster.
84  */
85 void
86 CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
87 {
88         if (!IsUnderPostmaster)
89         {
90                 PGShmemHeader *seghdr;
91                 Size            size;
92                 int                     numSemas;
93
94                 /*
95                  * Size of the Postgres shared-memory block is estimated via
96                  * moderately-accurate estimates for the big hogs, plus 100K for the
97                  * stuff that's too small to bother with estimating.
98                  *
99                  * We take some care during this phase to ensure that the total size
100                  * request doesn't overflow size_t.  If this gets through, we don't
101                  * need to be so careful during the actual allocation phase.
102                  */
103                 size = 100000;
104                 size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
105                                                                                                  sizeof(ShmemIndexEnt)));
106                 size = add_size(size, BufferShmemSize());
107                 size = add_size(size, LockShmemSize());
108                 size = add_size(size, ProcGlobalShmemSize());
109                 size = add_size(size, XLOGShmemSize());
110                 size = add_size(size, CLOGShmemSize());
111                 size = add_size(size, SUBTRANSShmemSize());
112                 size = add_size(size, TwoPhaseShmemSize());
113                 size = add_size(size, MultiXactShmemSize());
114                 size = add_size(size, LWLockShmemSize());
115                 size = add_size(size, ProcArrayShmemSize());
116                 size = add_size(size, BackendStatusShmemSize());
117                 size = add_size(size, SInvalShmemSize());
118                 size = add_size(size, PMSignalShmemSize());
119                 size = add_size(size, ProcSignalShmemSize());
120                 size = add_size(size, BgWriterShmemSize());
121                 size = add_size(size, AutoVacuumShmemSize());
122                 size = add_size(size, WalSndShmemSize());
123                 size = add_size(size, WalRcvShmemSize());
124                 size = add_size(size, BTreeShmemSize());
125                 size = add_size(size, SyncScanShmemSize());
126                 size = add_size(size, AsyncShmemSize());
127 #ifdef EXEC_BACKEND
128                 size = add_size(size, ShmemBackendArraySize());
129 #endif
130
131                 /* freeze the addin request size and include it */
132                 addin_request_allowed = false;
133                 size = add_size(size, total_addin_request);
134
135                 /* might as well round it off to a multiple of a typical page size */
136                 size = add_size(size, 8192 - (size % 8192));
137
138                 elog(DEBUG3, "invoking IpcMemoryCreate(size=%lu)",
139                          (unsigned long) size);
140
141                 /*
142                  * Create the shmem segment
143                  */
144                 seghdr = PGSharedMemoryCreate(size, makePrivate, port);
145
146                 InitShmemAccess(seghdr);
147
148                 /*
149                  * Create semaphores
150                  */
151                 numSemas = ProcGlobalSemas();
152                 numSemas += SpinlockSemas();
153                 PGReserveSemaphores(numSemas, port);
154         }
155         else
156         {
157                 /*
158                  * We are reattaching to an existing shared memory segment. This
159                  * should only be reached in the EXEC_BACKEND case, and even then only
160                  * with makePrivate == false.
161                  */
162 #ifdef EXEC_BACKEND
163                 Assert(!makePrivate);
164 #else
165                 elog(PANIC, "should be attached to shared memory already");
166 #endif
167         }
168
169         /*
170          * Set up shared memory allocation mechanism
171          */
172         if (!IsUnderPostmaster)
173                 InitShmemAllocation();
174
175         /*
176          * Now initialize LWLocks, which do shared memory allocation and are
177          * needed for InitShmemIndex.
178          */
179         if (!IsUnderPostmaster)
180                 CreateLWLocks();
181
182         /*
183          * Set up shmem.c index hashtable
184          */
185         InitShmemIndex();
186
187         /*
188          * Set up xlog, clog, and buffers
189          */
190         XLOGShmemInit();
191         CLOGShmemInit();
192         SUBTRANSShmemInit();
193         TwoPhaseShmemInit();
194         MultiXactShmemInit();
195         InitBufferPool();
196
197         /*
198          * Set up lock manager
199          */
200         InitLocks();
201
202         /*
203          * Set up process table
204          */
205         if (!IsUnderPostmaster)
206                 InitProcGlobal();
207         CreateSharedProcArray();
208         CreateSharedBackendStatus();
209
210         /*
211          * Set up shared-inval messaging
212          */
213         CreateSharedInvalidationState();
214
215         /*
216          * Set up interprocess signaling mechanisms
217          */
218         PMSignalShmemInit();
219         ProcSignalShmemInit();
220         BgWriterShmemInit();
221         AutoVacuumShmemInit();
222         WalSndShmemInit();
223         WalRcvShmemInit();
224
225         /*
226          * Set up other modules that need some shared memory space
227          */
228         BTreeShmemInit();
229         SyncScanShmemInit();
230         AsyncShmemInit();
231
232 #ifdef EXEC_BACKEND
233
234         /*
235          * Alloc the win32 shared backend array
236          */
237         if (!IsUnderPostmaster)
238                 ShmemBackendArrayAllocation();
239 #endif
240
241         /*
242          * Now give loadable modules a chance to set up their shmem allocations
243          */
244         if (shmem_startup_hook)
245                 shmem_startup_hook();
246 }