LCOV - code coverage report
Current view: top level - src/backend/storage/ipc - ipci.c (source / functions) Hit Total Coverage
Test: PostgreSQL 15devel Lines: 104 106 98.1 %
Date: 2021-12-04 22:09:09 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * ipci.c
       4             :  *    POSTGRES inter-process communication initialization code.
       5             :  *
       6             :  * Portions Copyright (c) 1996-2021, 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/syncscan.h"
      24             : #include "access/twophase.h"
      25             : #include "commands/async.h"
      26             : #include "miscadmin.h"
      27             : #include "pgstat.h"
      28             : #include "postmaster/autovacuum.h"
      29             : #include "postmaster/bgworker_internals.h"
      30             : #include "postmaster/bgwriter.h"
      31             : #include "postmaster/postmaster.h"
      32             : #include "replication/logicallauncher.h"
      33             : #include "replication/origin.h"
      34             : #include "replication/slot.h"
      35             : #include "replication/walreceiver.h"
      36             : #include "replication/walsender.h"
      37             : #include "storage/bufmgr.h"
      38             : #include "storage/dsm.h"
      39             : #include "storage/ipc.h"
      40             : #include "storage/pg_shmem.h"
      41             : #include "storage/pmsignal.h"
      42             : #include "storage/predicate.h"
      43             : #include "storage/proc.h"
      44             : #include "storage/procarray.h"
      45             : #include "storage/procsignal.h"
      46             : #include "storage/sinvaladt.h"
      47             : #include "storage/spin.h"
      48             : #include "utils/snapmgr.h"
      49             : 
      50             : /* GUCs */
      51             : int         shared_memory_type = DEFAULT_SHARED_MEMORY_TYPE;
      52             : 
      53             : shmem_startup_hook_type shmem_startup_hook = NULL;
      54             : 
      55             : static Size total_addin_request = 0;
      56             : static bool addin_request_allowed = true;
      57             : 
      58             : 
      59             : /*
      60             :  * RequestAddinShmemSpace
      61             :  *      Request that extra shmem space be allocated for use by
      62             :  *      a loadable module.
      63             :  *
      64             :  * This is only useful if called from the _PG_init hook of a library that
      65             :  * is loaded into the postmaster via shared_preload_libraries.  Once
      66             :  * shared memory has been allocated, calls will be ignored.  (We could
      67             :  * raise an error, but it seems better to make it a no-op, so that
      68             :  * libraries containing such calls can be reloaded if needed.)
      69             :  */
      70             : void
      71           2 : RequestAddinShmemSpace(Size size)
      72             : {
      73           2 :     if (IsUnderPostmaster || !addin_request_allowed)
      74           0 :         return;                 /* too late */
      75           2 :     total_addin_request = add_size(total_addin_request, size);
      76             : }
      77             : 
      78             : /*
      79             :  * CalculateShmemSize
      80             :  *      Calculates the amount of shared memory and number of semaphores needed.
      81             :  *
      82             :  * If num_semaphores is not NULL, it will be set to the number of semaphores
      83             :  * required.
      84             :  *
      85             :  * Note that this function freezes the additional shared memory request size
      86             :  * from loadable modules.
      87             :  */
      88             : Size
      89        3842 : CalculateShmemSize(int *num_semaphores)
      90             : {
      91             :     Size        size;
      92             :     int         numSemas;
      93             : 
      94             :     /* Compute number of semaphores we'll need */
      95        3842 :     numSemas = ProcGlobalSemas();
      96        3842 :     numSemas += SpinlockSemas();
      97             : 
      98             :     /* Return the number of semaphores if requested by the caller */
      99        3842 :     if (num_semaphores)
     100        2898 :         *num_semaphores = numSemas;
     101             : 
     102             :     /*
     103             :      * Size of the Postgres shared-memory block is estimated via moderately-
     104             :      * accurate estimates for the big hogs, plus 100K for the stuff that's too
     105             :      * small to bother with estimating.
     106             :      *
     107             :      * We take some care to ensure that the total size request doesn't
     108             :      * overflow size_t.  If this gets through, we don't need to be so careful
     109             :      * during the actual allocation phase.
     110             :      */
     111        3842 :     size = 100000;
     112        3842 :     size = add_size(size, PGSemaphoreShmemSize(numSemas));
     113        3842 :     size = add_size(size, SpinlockSemaSize());
     114        3842 :     size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
     115             :                                              sizeof(ShmemIndexEnt)));
     116        3842 :     size = add_size(size, dsm_estimate_size());
     117        3842 :     size = add_size(size, BufferShmemSize());
     118        3842 :     size = add_size(size, LockShmemSize());
     119        3842 :     size = add_size(size, PredicateLockShmemSize());
     120        3842 :     size = add_size(size, ProcGlobalShmemSize());
     121        3842 :     size = add_size(size, XLOGShmemSize());
     122        3842 :     size = add_size(size, CLOGShmemSize());
     123        3842 :     size = add_size(size, CommitTsShmemSize());
     124        3842 :     size = add_size(size, SUBTRANSShmemSize());
     125        3842 :     size = add_size(size, TwoPhaseShmemSize());
     126        3842 :     size = add_size(size, BackgroundWorkerShmemSize());
     127        3842 :     size = add_size(size, MultiXactShmemSize());
     128        3842 :     size = add_size(size, LWLockShmemSize());
     129        3842 :     size = add_size(size, ProcArrayShmemSize());
     130        3842 :     size = add_size(size, BackendStatusShmemSize());
     131        3842 :     size = add_size(size, SInvalShmemSize());
     132        3842 :     size = add_size(size, PMSignalShmemSize());
     133        3842 :     size = add_size(size, ProcSignalShmemSize());
     134        3842 :     size = add_size(size, CheckpointerShmemSize());
     135        3842 :     size = add_size(size, AutoVacuumShmemSize());
     136        3842 :     size = add_size(size, ReplicationSlotsShmemSize());
     137        3842 :     size = add_size(size, ReplicationOriginShmemSize());
     138        3842 :     size = add_size(size, WalSndShmemSize());
     139        3842 :     size = add_size(size, WalRcvShmemSize());
     140        3842 :     size = add_size(size, PgArchShmemSize());
     141        3842 :     size = add_size(size, ApplyLauncherShmemSize());
     142        3842 :     size = add_size(size, SnapMgrShmemSize());
     143        3842 :     size = add_size(size, BTreeShmemSize());
     144        3842 :     size = add_size(size, SyncScanShmemSize());
     145        3842 :     size = add_size(size, AsyncShmemSize());
     146             : #ifdef EXEC_BACKEND
     147             :     size = add_size(size, ShmemBackendArraySize());
     148             : #endif
     149             : 
     150             :     /* freeze the addin request size and include it */
     151        3842 :     addin_request_allowed = false;
     152        3842 :     size = add_size(size, total_addin_request);
     153             : 
     154             :     /* might as well round it off to a multiple of a typical page size */
     155        3842 :     size = add_size(size, 8192 - (size % 8192));
     156             : 
     157        3842 :     return size;
     158             : }
     159             : 
     160             : /*
     161             :  * CreateSharedMemoryAndSemaphores
     162             :  *      Creates and initializes shared memory and semaphores.
     163             :  *
     164             :  * This is called by the postmaster or by a standalone backend.
     165             :  * It is also called by a backend forked from the postmaster in the
     166             :  * EXEC_BACKEND case.  In the latter case, the shared memory segment
     167             :  * already exists and has been physically attached to, but we have to
     168             :  * initialize pointers in local memory that reference the shared structures,
     169             :  * because we didn't inherit the correct pointer values from the postmaster
     170             :  * as we do in the fork() scenario.  The easiest way to do that is to run
     171             :  * through the same code as before.  (Note that the called routines mostly
     172             :  * check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case.
     173             :  * This is a bit code-wasteful and could be cleaned up.)
     174             :  */
     175             : void
     176        2898 : CreateSharedMemoryAndSemaphores(void)
     177             : {
     178        2898 :     PGShmemHeader *shim = NULL;
     179             : 
     180        2898 :     if (!IsUnderPostmaster)
     181             :     {
     182             :         PGShmemHeader *seghdr;
     183             :         Size        size;
     184             :         int         numSemas;
     185             : 
     186             :         /* Compute the size of the shared-memory block */
     187        2898 :         size = CalculateShmemSize(&numSemas);
     188        2898 :         elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
     189             : 
     190             :         /*
     191             :          * Create the shmem segment
     192             :          */
     193        2898 :         seghdr = PGSharedMemoryCreate(size, &shim);
     194             : 
     195        2894 :         InitShmemAccess(seghdr);
     196             : 
     197             :         /*
     198             :          * Create semaphores
     199             :          */
     200        2894 :         PGReserveSemaphores(numSemas);
     201             : 
     202             :         /*
     203             :          * If spinlocks are disabled, initialize emulation layer (which
     204             :          * depends on semaphores, so the order is important here).
     205             :          */
     206             : #ifndef HAVE_SPINLOCKS
     207             :         SpinlockSemaInit();
     208             : #endif
     209             :     }
     210             :     else
     211             :     {
     212             :         /*
     213             :          * We are reattaching to an existing shared memory segment. This
     214             :          * should only be reached in the EXEC_BACKEND case.
     215             :          */
     216             : #ifndef EXEC_BACKEND
     217           0 :         elog(PANIC, "should be attached to shared memory already");
     218             : #endif
     219             :     }
     220             : 
     221             :     /*
     222             :      * Set up shared memory allocation mechanism
     223             :      */
     224        2894 :     if (!IsUnderPostmaster)
     225        2894 :         InitShmemAllocation();
     226             : 
     227             :     /*
     228             :      * Now initialize LWLocks, which do shared memory allocation and are
     229             :      * needed for InitShmemIndex.
     230             :      */
     231        2894 :     CreateLWLocks();
     232             : 
     233             :     /*
     234             :      * Set up shmem.c index hashtable
     235             :      */
     236        2894 :     InitShmemIndex();
     237             : 
     238        2894 :     dsm_shmem_init();
     239             : 
     240             :     /*
     241             :      * Set up xlog, clog, and buffers
     242             :      */
     243        2894 :     XLOGShmemInit();
     244        2894 :     CLOGShmemInit();
     245        2894 :     CommitTsShmemInit();
     246        2894 :     SUBTRANSShmemInit();
     247        2894 :     MultiXactShmemInit();
     248        2894 :     InitBufferPool();
     249             : 
     250             :     /*
     251             :      * Set up lock manager
     252             :      */
     253        2894 :     InitLocks();
     254             : 
     255             :     /*
     256             :      * Set up predicate lock manager
     257             :      */
     258        2894 :     InitPredicateLocks();
     259             : 
     260             :     /*
     261             :      * Set up process table
     262             :      */
     263        2894 :     if (!IsUnderPostmaster)
     264        2894 :         InitProcGlobal();
     265        2894 :     CreateSharedProcArray();
     266        2894 :     CreateSharedBackendStatus();
     267        2894 :     TwoPhaseShmemInit();
     268        2894 :     BackgroundWorkerShmemInit();
     269             : 
     270             :     /*
     271             :      * Set up shared-inval messaging
     272             :      */
     273        2894 :     CreateSharedInvalidationState();
     274             : 
     275             :     /*
     276             :      * Set up interprocess signaling mechanisms
     277             :      */
     278        2894 :     PMSignalShmemInit();
     279        2894 :     ProcSignalShmemInit();
     280        2894 :     CheckpointerShmemInit();
     281        2894 :     AutoVacuumShmemInit();
     282        2894 :     ReplicationSlotsShmemInit();
     283        2894 :     ReplicationOriginShmemInit();
     284        2894 :     WalSndShmemInit();
     285        2894 :     WalRcvShmemInit();
     286        2894 :     PgArchShmemInit();
     287        2894 :     ApplyLauncherShmemInit();
     288             : 
     289             :     /*
     290             :      * Set up other modules that need some shared memory space
     291             :      */
     292        2894 :     SnapMgrInit();
     293        2894 :     BTreeShmemInit();
     294        2894 :     SyncScanShmemInit();
     295        2894 :     AsyncShmemInit();
     296             : 
     297             : #ifdef EXEC_BACKEND
     298             : 
     299             :     /*
     300             :      * Alloc the win32 shared backend array
     301             :      */
     302             :     if (!IsUnderPostmaster)
     303             :         ShmemBackendArrayAllocation();
     304             : #endif
     305             : 
     306             :     /* Initialize dynamic shared memory facilities. */
     307        2894 :     if (!IsUnderPostmaster)
     308        2894 :         dsm_postmaster_startup(shim);
     309             : 
     310             :     /*
     311             :      * Now give loadable modules a chance to set up their shmem allocations
     312             :      */
     313        2894 :     if (shmem_startup_hook)
     314           2 :         shmem_startup_hook();
     315        2894 : }
     316             : 
     317             : /*
     318             :  * InitializeShmemGUCs
     319             :  *
     320             :  * This function initializes runtime-computed GUCs related to the amount of
     321             :  * shared memory required for the current configuration.
     322             :  */
     323             : void
     324         944 : InitializeShmemGUCs(void)
     325             : {
     326             :     char        buf[64];
     327             :     Size        size_b;
     328             :     Size        size_mb;
     329             :     Size        hp_size;
     330             : 
     331             :     /*
     332             :      * Calculate the shared memory size and round up to the nearest megabyte.
     333             :      */
     334         944 :     size_b = CalculateShmemSize(NULL);
     335         944 :     size_mb = add_size(size_b, (1024 * 1024) - 1) / (1024 * 1024);
     336         944 :     sprintf(buf, "%zu", size_mb);
     337         944 :     SetConfigOption("shared_memory_size", buf, PGC_INTERNAL, PGC_S_OVERRIDE);
     338             : 
     339             :     /*
     340             :      * Calculate the number of huge pages required.
     341             :      */
     342         944 :     GetHugePageSize(&hp_size, NULL);
     343         944 :     if (hp_size != 0)
     344             :     {
     345             :         Size        hp_required;
     346             : 
     347         944 :         hp_required = add_size(size_b / hp_size, 1);
     348         944 :         sprintf(buf, "%zu", hp_required);
     349         944 :         SetConfigOption("shared_memory_size_in_huge_pages", buf, PGC_INTERNAL, PGC_S_OVERRIDE);
     350             :     }
     351         944 : }

Generated by: LCOV version 1.14