Header And Logo

PostgreSQL
| The world's most advanced open source database.

ipci.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * ipci.c
00004  *    POSTGRES inter-process communication initialization code.
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/storage/ipc/ipci.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 #include "postgres.h"
00016 
00017 #include "access/clog.h"
00018 #include "access/heapam.h"
00019 #include "access/multixact.h"
00020 #include "access/nbtree.h"
00021 #include "access/subtrans.h"
00022 #include "access/twophase.h"
00023 #include "commands/async.h"
00024 #include "miscadmin.h"
00025 #include "pgstat.h"
00026 #include "postmaster/autovacuum.h"
00027 #include "postmaster/bgwriter.h"
00028 #include "postmaster/postmaster.h"
00029 #include "replication/walreceiver.h"
00030 #include "replication/walsender.h"
00031 #include "storage/bufmgr.h"
00032 #include "storage/ipc.h"
00033 #include "storage/pg_shmem.h"
00034 #include "storage/pmsignal.h"
00035 #include "storage/predicate.h"
00036 #include "storage/proc.h"
00037 #include "storage/procarray.h"
00038 #include "storage/procsignal.h"
00039 #include "storage/sinvaladt.h"
00040 #include "storage/spin.h"
00041 
00042 
00043 shmem_startup_hook_type shmem_startup_hook = NULL;
00044 
00045 static Size total_addin_request = 0;
00046 static bool addin_request_allowed = true;
00047 
00048 
00049 /*
00050  * RequestAddinShmemSpace
00051  *      Request that extra shmem space be allocated for use by
00052  *      a loadable module.
00053  *
00054  * This is only useful if called from the _PG_init hook of a library that
00055  * is loaded into the postmaster via shared_preload_libraries.  Once
00056  * shared memory has been allocated, calls will be ignored.  (We could
00057  * raise an error, but it seems better to make it a no-op, so that
00058  * libraries containing such calls can be reloaded if needed.)
00059  */
00060 void
00061 RequestAddinShmemSpace(Size size)
00062 {
00063     if (IsUnderPostmaster || !addin_request_allowed)
00064         return;                 /* too late */
00065     total_addin_request = add_size(total_addin_request, size);
00066 }
00067 
00068 
00069 /*
00070  * CreateSharedMemoryAndSemaphores
00071  *      Creates and initializes shared memory and semaphores.
00072  *
00073  * This is called by the postmaster or by a standalone backend.
00074  * It is also called by a backend forked from the postmaster in the
00075  * EXEC_BACKEND case.  In the latter case, the shared memory segment
00076  * already exists and has been physically attached to, but we have to
00077  * initialize pointers in local memory that reference the shared structures,
00078  * because we didn't inherit the correct pointer values from the postmaster
00079  * as we do in the fork() scenario.  The easiest way to do that is to run
00080  * through the same code as before.  (Note that the called routines mostly
00081  * check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case.
00082  * This is a bit code-wasteful and could be cleaned up.)
00083  *
00084  * If "makePrivate" is true then we only need private memory, not shared
00085  * memory.  This is true for a standalone backend, false for a postmaster.
00086  */
00087 void
00088 CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
00089 {
00090     if (!IsUnderPostmaster)
00091     {
00092         PGShmemHeader *seghdr;
00093         Size        size;
00094         int         numSemas;
00095 
00096         /*
00097          * Size of the Postgres shared-memory block is estimated via
00098          * moderately-accurate estimates for the big hogs, plus 100K for the
00099          * stuff that's too small to bother with estimating.
00100          *
00101          * We take some care during this phase to ensure that the total size
00102          * request doesn't overflow size_t.  If this gets through, we don't
00103          * need to be so careful during the actual allocation phase.
00104          */
00105         size = 100000;
00106         size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
00107                                                  sizeof(ShmemIndexEnt)));
00108         size = add_size(size, BufferShmemSize());
00109         size = add_size(size, LockShmemSize());
00110         size = add_size(size, PredicateLockShmemSize());
00111         size = add_size(size, ProcGlobalShmemSize());
00112         size = add_size(size, XLOGShmemSize());
00113         size = add_size(size, CLOGShmemSize());
00114         size = add_size(size, SUBTRANSShmemSize());
00115         size = add_size(size, TwoPhaseShmemSize());
00116         size = add_size(size, MultiXactShmemSize());
00117         size = add_size(size, LWLockShmemSize());
00118         size = add_size(size, ProcArrayShmemSize());
00119         size = add_size(size, BackendStatusShmemSize());
00120         size = add_size(size, SInvalShmemSize());
00121         size = add_size(size, PMSignalShmemSize());
00122         size = add_size(size, ProcSignalShmemSize());
00123         size = add_size(size, CheckpointerShmemSize());
00124         size = add_size(size, AutoVacuumShmemSize());
00125         size = add_size(size, WalSndShmemSize());
00126         size = add_size(size, WalRcvShmemSize());
00127         size = add_size(size, BTreeShmemSize());
00128         size = add_size(size, SyncScanShmemSize());
00129         size = add_size(size, AsyncShmemSize());
00130 #ifdef EXEC_BACKEND
00131         size = add_size(size, ShmemBackendArraySize());
00132 #endif
00133 
00134         /* freeze the addin request size and include it */
00135         addin_request_allowed = false;
00136         size = add_size(size, total_addin_request);
00137 
00138         /* might as well round it off to a multiple of a typical page size */
00139         size = add_size(size, 8192 - (size % 8192));
00140 
00141         elog(DEBUG3, "invoking IpcMemoryCreate(size=%lu)",
00142              (unsigned long) size);
00143 
00144         /*
00145          * Create the shmem segment
00146          */
00147         seghdr = PGSharedMemoryCreate(size, makePrivate, port);
00148 
00149         InitShmemAccess(seghdr);
00150 
00151         /*
00152          * Create semaphores
00153          */
00154         numSemas = ProcGlobalSemas();
00155         numSemas += SpinlockSemas();
00156         PGReserveSemaphores(numSemas, port);
00157     }
00158     else
00159     {
00160         /*
00161          * We are reattaching to an existing shared memory segment. This
00162          * should only be reached in the EXEC_BACKEND case, and even then only
00163          * with makePrivate == false.
00164          */
00165 #ifdef EXEC_BACKEND
00166         Assert(!makePrivate);
00167 #else
00168         elog(PANIC, "should be attached to shared memory already");
00169 #endif
00170     }
00171 
00172     /*
00173      * Set up shared memory allocation mechanism
00174      */
00175     if (!IsUnderPostmaster)
00176         InitShmemAllocation();
00177 
00178     /*
00179      * Now initialize LWLocks, which do shared memory allocation and are
00180      * needed for InitShmemIndex.
00181      */
00182     if (!IsUnderPostmaster)
00183         CreateLWLocks();
00184 
00185     /*
00186      * Set up shmem.c index hashtable
00187      */
00188     InitShmemIndex();
00189 
00190     /*
00191      * Set up xlog, clog, and buffers
00192      */
00193     XLOGShmemInit();
00194     CLOGShmemInit();
00195     SUBTRANSShmemInit();
00196     MultiXactShmemInit();
00197     InitBufferPool();
00198 
00199     /*
00200      * Set up lock manager
00201      */
00202     InitLocks();
00203 
00204     /*
00205      * Set up predicate lock manager
00206      */
00207     InitPredicateLocks();
00208 
00209     /*
00210      * Set up process table
00211      */
00212     if (!IsUnderPostmaster)
00213         InitProcGlobal();
00214     CreateSharedProcArray();
00215     CreateSharedBackendStatus();
00216     TwoPhaseShmemInit();
00217 
00218     /*
00219      * Set up shared-inval messaging
00220      */
00221     CreateSharedInvalidationState();
00222 
00223     /*
00224      * Set up interprocess signaling mechanisms
00225      */
00226     PMSignalShmemInit();
00227     ProcSignalShmemInit();
00228     CheckpointerShmemInit();
00229     AutoVacuumShmemInit();
00230     WalSndShmemInit();
00231     WalRcvShmemInit();
00232 
00233     /*
00234      * Set up other modules that need some shared memory space
00235      */
00236     BTreeShmemInit();
00237     SyncScanShmemInit();
00238     AsyncShmemInit();
00239 
00240 #ifdef EXEC_BACKEND
00241 
00242     /*
00243      * Alloc the win32 shared backend array
00244      */
00245     if (!IsUnderPostmaster)
00246         ShmemBackendArrayAllocation();
00247 #endif
00248 
00249     /*
00250      * Now give loadable modules a chance to set up their shmem allocations
00251      */
00252     if (shmem_startup_hook)
00253         shmem_startup_hook();
00254 }