OSDN Git Service

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