LCOV - code coverage report
Current view: top level - src/backend/storage/ipc - ipci.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 119 120 99.2 %
Date: 2024-04-23 08:11:33 Functions: 5 5 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-2024, 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/multixact.h"
      20             : #include "access/nbtree.h"
      21             : #include "access/subtrans.h"
      22             : #include "access/syncscan.h"
      23             : #include "access/transam.h"
      24             : #include "access/twophase.h"
      25             : #include "access/xlogprefetcher.h"
      26             : #include "access/xlogrecovery.h"
      27             : #include "commands/async.h"
      28             : #include "miscadmin.h"
      29             : #include "pgstat.h"
      30             : #include "postmaster/autovacuum.h"
      31             : #include "postmaster/bgworker_internals.h"
      32             : #include "postmaster/bgwriter.h"
      33             : #include "postmaster/postmaster.h"
      34             : #include "postmaster/walsummarizer.h"
      35             : #include "replication/logicallauncher.h"
      36             : #include "replication/origin.h"
      37             : #include "replication/slot.h"
      38             : #include "replication/slotsync.h"
      39             : #include "replication/walreceiver.h"
      40             : #include "replication/walsender.h"
      41             : #include "storage/bufmgr.h"
      42             : #include "storage/dsm.h"
      43             : #include "storage/dsm_registry.h"
      44             : #include "storage/ipc.h"
      45             : #include "storage/pg_shmem.h"
      46             : #include "storage/pmsignal.h"
      47             : #include "storage/predicate.h"
      48             : #include "storage/proc.h"
      49             : #include "storage/procarray.h"
      50             : #include "storage/procsignal.h"
      51             : #include "storage/sinvaladt.h"
      52             : #include "storage/spin.h"
      53             : #include "utils/guc.h"
      54             : #include "utils/injection_point.h"
      55             : 
      56             : /* GUCs */
      57             : int         shared_memory_type = DEFAULT_SHARED_MEMORY_TYPE;
      58             : 
      59             : shmem_startup_hook_type shmem_startup_hook = NULL;
      60             : 
      61             : static Size total_addin_request = 0;
      62             : 
      63             : static void CreateOrAttachShmemStructs(void);
      64             : 
      65             : /*
      66             :  * RequestAddinShmemSpace
      67             :  *      Request that extra shmem space be allocated for use by
      68             :  *      a loadable module.
      69             :  *
      70             :  * This may only be called via the shmem_request_hook of a library that is
      71             :  * loaded into the postmaster via shared_preload_libraries.  Calls from
      72             :  * elsewhere will fail.
      73             :  */
      74             : void
      75          14 : RequestAddinShmemSpace(Size size)
      76             : {
      77          14 :     if (!process_shmem_requests_in_progress)
      78           0 :         elog(FATAL, "cannot request additional shared memory outside shmem_request_hook");
      79          14 :     total_addin_request = add_size(total_addin_request, size);
      80          14 : }
      81             : 
      82             : /*
      83             :  * CalculateShmemSize
      84             :  *      Calculates the amount of shared memory and number of semaphores needed.
      85             :  *
      86             :  * If num_semaphores is not NULL, it will be set to the number of semaphores
      87             :  * required.
      88             :  */
      89             : Size
      90        3298 : CalculateShmemSize(int *num_semaphores)
      91             : {
      92             :     Size        size;
      93             :     int         numSemas;
      94             : 
      95             :     /* Compute number of semaphores we'll need */
      96        3298 :     numSemas = ProcGlobalSemas();
      97        3298 :     numSemas += SpinlockSemas();
      98             : 
      99             :     /* Return the number of semaphores if requested by the caller */
     100        3298 :     if (num_semaphores)
     101        1772 :         *num_semaphores = numSemas;
     102             : 
     103             :     /*
     104             :      * Size of the Postgres shared-memory block is estimated via moderately-
     105             :      * accurate estimates for the big hogs, plus 100K for the stuff that's too
     106             :      * small to bother with estimating.
     107             :      *
     108             :      * We take some care to ensure that the total size request doesn't
     109             :      * overflow size_t.  If this gets through, we don't need to be so careful
     110             :      * during the actual allocation phase.
     111             :      */
     112        3298 :     size = 100000;
     113        3298 :     size = add_size(size, PGSemaphoreShmemSize(numSemas));
     114        3298 :     size = add_size(size, SpinlockSemaSize());
     115        3298 :     size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
     116             :                                              sizeof(ShmemIndexEnt)));
     117        3298 :     size = add_size(size, dsm_estimate_size());
     118        3298 :     size = add_size(size, DSMRegistryShmemSize());
     119        3298 :     size = add_size(size, BufferShmemSize());
     120        3298 :     size = add_size(size, LockShmemSize());
     121        3298 :     size = add_size(size, PredicateLockShmemSize());
     122        3298 :     size = add_size(size, ProcGlobalShmemSize());
     123        3298 :     size = add_size(size, XLogPrefetchShmemSize());
     124        3298 :     size = add_size(size, VarsupShmemSize());
     125        3298 :     size = add_size(size, XLOGShmemSize());
     126        3298 :     size = add_size(size, XLogRecoveryShmemSize());
     127        3298 :     size = add_size(size, CLOGShmemSize());
     128        3298 :     size = add_size(size, CommitTsShmemSize());
     129        3298 :     size = add_size(size, SUBTRANSShmemSize());
     130        3298 :     size = add_size(size, TwoPhaseShmemSize());
     131        3298 :     size = add_size(size, BackgroundWorkerShmemSize());
     132        3298 :     size = add_size(size, MultiXactShmemSize());
     133        3298 :     size = add_size(size, LWLockShmemSize());
     134        3298 :     size = add_size(size, ProcArrayShmemSize());
     135        3298 :     size = add_size(size, BackendStatusShmemSize());
     136        3298 :     size = add_size(size, SInvalShmemSize());
     137        3298 :     size = add_size(size, PMSignalShmemSize());
     138        3298 :     size = add_size(size, ProcSignalShmemSize());
     139        3298 :     size = add_size(size, CheckpointerShmemSize());
     140        3298 :     size = add_size(size, AutoVacuumShmemSize());
     141        3298 :     size = add_size(size, ReplicationSlotsShmemSize());
     142        3298 :     size = add_size(size, ReplicationOriginShmemSize());
     143        3298 :     size = add_size(size, WalSndShmemSize());
     144        3298 :     size = add_size(size, WalRcvShmemSize());
     145        3298 :     size = add_size(size, WalSummarizerShmemSize());
     146        3298 :     size = add_size(size, PgArchShmemSize());
     147        3298 :     size = add_size(size, ApplyLauncherShmemSize());
     148        3298 :     size = add_size(size, BTreeShmemSize());
     149        3298 :     size = add_size(size, SyncScanShmemSize());
     150        3298 :     size = add_size(size, AsyncShmemSize());
     151        3298 :     size = add_size(size, StatsShmemSize());
     152        3298 :     size = add_size(size, WaitEventExtensionShmemSize());
     153        3298 :     size = add_size(size, InjectionPointShmemSize());
     154        3298 :     size = add_size(size, SlotSyncShmemSize());
     155             : #ifdef EXEC_BACKEND
     156             :     size = add_size(size, ShmemBackendArraySize());
     157             : #endif
     158             : 
     159             :     /* include additional requested shmem from preload libraries */
     160        3298 :     size = add_size(size, total_addin_request);
     161             : 
     162             :     /* might as well round it off to a multiple of a typical page size */
     163        3298 :     size = add_size(size, 8192 - (size % 8192));
     164             : 
     165        3298 :     return size;
     166             : }
     167             : 
     168             : #ifdef EXEC_BACKEND
     169             : /*
     170             :  * AttachSharedMemoryStructs
     171             :  *      Initialize a postmaster child process's access to shared memory
     172             :  *      structures.
     173             :  *
     174             :  * In !EXEC_BACKEND mode, we inherit everything through the fork, and this
     175             :  * isn't needed.
     176             :  */
     177             : void
     178             : AttachSharedMemoryStructs(void)
     179             : {
     180             :     /* InitProcess must've been called already */
     181             :     Assert(MyProc != NULL);
     182             :     Assert(IsUnderPostmaster);
     183             : 
     184             :     CreateOrAttachShmemStructs();
     185             : 
     186             :     /*
     187             :      * Now give loadable modules a chance to set up their shmem allocations
     188             :      */
     189             :     if (shmem_startup_hook)
     190             :         shmem_startup_hook();
     191             : }
     192             : #endif
     193             : 
     194             : /*
     195             :  * CreateSharedMemoryAndSemaphores
     196             :  *      Creates and initializes shared memory and semaphores.
     197             :  */
     198             : void
     199        1772 : CreateSharedMemoryAndSemaphores(void)
     200             : {
     201             :     PGShmemHeader *shim;
     202             :     PGShmemHeader *seghdr;
     203             :     Size        size;
     204             :     int         numSemas;
     205             : 
     206             :     Assert(!IsUnderPostmaster);
     207             : 
     208             :     /* Compute the size of the shared-memory block */
     209        1772 :     size = CalculateShmemSize(&numSemas);
     210        1772 :     elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
     211             : 
     212             :     /*
     213             :      * Create the shmem segment
     214             :      */
     215        1772 :     seghdr = PGSharedMemoryCreate(size, &shim);
     216             : 
     217             :     /*
     218             :      * Make sure that huge pages are never reported as "unknown" while the
     219             :      * server is running.
     220             :      */
     221             :     Assert(strcmp("unknown",
     222             :                   GetConfigOption("huge_pages_status", false, false)) != 0);
     223             : 
     224        1768 :     InitShmemAccess(seghdr);
     225             : 
     226             :     /*
     227             :      * Create semaphores
     228             :      */
     229        1768 :     PGReserveSemaphores(numSemas);
     230             : 
     231             :     /*
     232             :      * If spinlocks are disabled, initialize emulation layer (which depends on
     233             :      * semaphores, so the order is important here).
     234             :      */
     235             : #ifndef HAVE_SPINLOCKS
     236             :     SpinlockSemaInit();
     237             : #endif
     238             : 
     239             :     /*
     240             :      * Set up shared memory allocation mechanism
     241             :      */
     242        1768 :     InitShmemAllocation();
     243             : 
     244             :     /* Initialize subsystems */
     245        1768 :     CreateOrAttachShmemStructs();
     246             : 
     247             : #ifdef EXEC_BACKEND
     248             : 
     249             :     /*
     250             :      * Alloc the win32 shared backend array
     251             :      */
     252             :     ShmemBackendArrayAllocation();
     253             : #endif
     254             : 
     255             :     /* Initialize dynamic shared memory facilities. */
     256        1768 :     dsm_postmaster_startup(shim);
     257             : 
     258             :     /*
     259             :      * Now give loadable modules a chance to set up their shmem allocations
     260             :      */
     261        1768 :     if (shmem_startup_hook)
     262          14 :         shmem_startup_hook();
     263        1768 : }
     264             : 
     265             : /*
     266             :  * Initialize various subsystems, setting up their data structures in
     267             :  * shared memory.
     268             :  *
     269             :  * This is called by the postmaster or by a standalone backend.
     270             :  * It is also called by a backend forked from the postmaster in the
     271             :  * EXEC_BACKEND case.  In the latter case, the shared memory segment
     272             :  * already exists and has been physically attached to, but we have to
     273             :  * initialize pointers in local memory that reference the shared structures,
     274             :  * because we didn't inherit the correct pointer values from the postmaster
     275             :  * as we do in the fork() scenario.  The easiest way to do that is to run
     276             :  * through the same code as before.  (Note that the called routines mostly
     277             :  * check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case.
     278             :  * This is a bit code-wasteful and could be cleaned up.)
     279             :  */
     280             : static void
     281        1768 : CreateOrAttachShmemStructs(void)
     282             : {
     283             :     /*
     284             :      * Now initialize LWLocks, which do shared memory allocation and are
     285             :      * needed for InitShmemIndex.
     286             :      */
     287        1768 :     CreateLWLocks();
     288             : 
     289             :     /*
     290             :      * Set up shmem.c index hashtable
     291             :      */
     292        1768 :     InitShmemIndex();
     293             : 
     294        1768 :     dsm_shmem_init();
     295        1768 :     DSMRegistryShmemInit();
     296             : 
     297             :     /*
     298             :      * Set up xlog, clog, and buffers
     299             :      */
     300        1768 :     VarsupShmemInit();
     301        1768 :     XLOGShmemInit();
     302        1768 :     XLogPrefetchShmemInit();
     303        1768 :     XLogRecoveryShmemInit();
     304        1768 :     CLOGShmemInit();
     305        1768 :     CommitTsShmemInit();
     306        1768 :     SUBTRANSShmemInit();
     307        1768 :     MultiXactShmemInit();
     308        1768 :     InitBufferPool();
     309             : 
     310             :     /*
     311             :      * Set up lock manager
     312             :      */
     313        1768 :     InitLocks();
     314             : 
     315             :     /*
     316             :      * Set up predicate lock manager
     317             :      */
     318        1768 :     InitPredicateLocks();
     319             : 
     320             :     /*
     321             :      * Set up process table
     322             :      */
     323        1768 :     if (!IsUnderPostmaster)
     324        1768 :         InitProcGlobal();
     325        1768 :     CreateSharedProcArray();
     326        1768 :     CreateSharedBackendStatus();
     327        1768 :     TwoPhaseShmemInit();
     328        1768 :     BackgroundWorkerShmemInit();
     329             : 
     330             :     /*
     331             :      * Set up shared-inval messaging
     332             :      */
     333        1768 :     CreateSharedInvalidationState();
     334             : 
     335             :     /*
     336             :      * Set up interprocess signaling mechanisms
     337             :      */
     338        1768 :     PMSignalShmemInit();
     339        1768 :     ProcSignalShmemInit();
     340        1768 :     CheckpointerShmemInit();
     341        1768 :     AutoVacuumShmemInit();
     342        1768 :     ReplicationSlotsShmemInit();
     343        1768 :     ReplicationOriginShmemInit();
     344        1768 :     WalSndShmemInit();
     345        1768 :     WalRcvShmemInit();
     346        1768 :     WalSummarizerShmemInit();
     347        1768 :     PgArchShmemInit();
     348        1768 :     ApplyLauncherShmemInit();
     349        1768 :     SlotSyncShmemInit();
     350             : 
     351             :     /*
     352             :      * Set up other modules that need some shared memory space
     353             :      */
     354        1768 :     BTreeShmemInit();
     355        1768 :     SyncScanShmemInit();
     356        1768 :     AsyncShmemInit();
     357        1768 :     StatsShmemInit();
     358        1768 :     WaitEventExtensionShmemInit();
     359        1768 :     InjectionPointShmemInit();
     360        1768 : }
     361             : 
     362             : /*
     363             :  * InitializeShmemGUCs
     364             :  *
     365             :  * This function initializes runtime-computed GUCs related to the amount of
     366             :  * shared memory required for the current configuration.
     367             :  */
     368             : void
     369        1526 : InitializeShmemGUCs(void)
     370             : {
     371             :     char        buf[64];
     372             :     Size        size_b;
     373             :     Size        size_mb;
     374             :     Size        hp_size;
     375             : 
     376             :     /*
     377             :      * Calculate the shared memory size and round up to the nearest megabyte.
     378             :      */
     379        1526 :     size_b = CalculateShmemSize(NULL);
     380        1526 :     size_mb = add_size(size_b, (1024 * 1024) - 1) / (1024 * 1024);
     381        1526 :     sprintf(buf, "%zu", size_mb);
     382        1526 :     SetConfigOption("shared_memory_size", buf,
     383             :                     PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
     384             : 
     385             :     /*
     386             :      * Calculate the number of huge pages required.
     387             :      */
     388        1526 :     GetHugePageSize(&hp_size, NULL);
     389        1526 :     if (hp_size != 0)
     390             :     {
     391             :         Size        hp_required;
     392             : 
     393        1526 :         hp_required = add_size(size_b / hp_size, 1);
     394        1526 :         sprintf(buf, "%zu", hp_required);
     395        1526 :         SetConfigOption("shared_memory_size_in_huge_pages", buf,
     396             :                         PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
     397             :     }
     398        1526 : }

Generated by: LCOV version 1.14