LCOV - code coverage report
Current view: top level - src/backend/storage/ipc - ipci.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 122 123 99.2 %
Date: 2026-01-28 01:17:35 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-2026, 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 "access/xlogwait.h"
      28             : #include "commands/async.h"
      29             : #include "miscadmin.h"
      30             : #include "pgstat.h"
      31             : #include "postmaster/autovacuum.h"
      32             : #include "postmaster/bgworker_internals.h"
      33             : #include "postmaster/bgwriter.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/aio_subsys.h"
      42             : #include "storage/bufmgr.h"
      43             : #include "storage/dsm.h"
      44             : #include "storage/dsm_registry.h"
      45             : #include "storage/ipc.h"
      46             : #include "storage/pg_shmem.h"
      47             : #include "storage/pmsignal.h"
      48             : #include "storage/predicate.h"
      49             : #include "storage/proc.h"
      50             : #include "storage/procarray.h"
      51             : #include "storage/procsignal.h"
      52             : #include "storage/sinvaladt.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          32 : RequestAddinShmemSpace(Size size)
      76             : {
      77          32 :     if (!process_shmem_requests_in_progress)
      78           0 :         elog(FATAL, "cannot request additional shared memory outside shmem_request_hook");
      79          32 :     total_addin_request = add_size(total_addin_request, size);
      80          32 : }
      81             : 
      82             : /*
      83             :  * CalculateShmemSize
      84             :  *      Calculates the amount of shared memory needed.
      85             :  */
      86             : Size
      87        4254 : CalculateShmemSize(void)
      88             : {
      89             :     Size        size;
      90             : 
      91             :     /*
      92             :      * Size of the Postgres shared-memory block is estimated via moderately-
      93             :      * accurate estimates for the big hogs, plus 100K for the stuff that's too
      94             :      * small to bother with estimating.
      95             :      *
      96             :      * We take some care to ensure that the total size request doesn't
      97             :      * overflow size_t.  If this gets through, we don't need to be so careful
      98             :      * during the actual allocation phase.
      99             :      */
     100        4254 :     size = 100000;
     101        4254 :     size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
     102             :                                              sizeof(ShmemIndexEnt)));
     103        4254 :     size = add_size(size, dsm_estimate_size());
     104        4254 :     size = add_size(size, DSMRegistryShmemSize());
     105        4254 :     size = add_size(size, BufferManagerShmemSize());
     106        4254 :     size = add_size(size, LockManagerShmemSize());
     107        4254 :     size = add_size(size, PredicateLockShmemSize());
     108        4254 :     size = add_size(size, ProcGlobalShmemSize());
     109        4254 :     size = add_size(size, XLogPrefetchShmemSize());
     110        4254 :     size = add_size(size, VarsupShmemSize());
     111        4254 :     size = add_size(size, XLOGShmemSize());
     112        4254 :     size = add_size(size, XLogRecoveryShmemSize());
     113        4254 :     size = add_size(size, CLOGShmemSize());
     114        4254 :     size = add_size(size, CommitTsShmemSize());
     115        4254 :     size = add_size(size, SUBTRANSShmemSize());
     116        4254 :     size = add_size(size, TwoPhaseShmemSize());
     117        4254 :     size = add_size(size, BackgroundWorkerShmemSize());
     118        4254 :     size = add_size(size, MultiXactShmemSize());
     119        4254 :     size = add_size(size, LWLockShmemSize());
     120        4254 :     size = add_size(size, ProcArrayShmemSize());
     121        4254 :     size = add_size(size, BackendStatusShmemSize());
     122        4254 :     size = add_size(size, SharedInvalShmemSize());
     123        4254 :     size = add_size(size, PMSignalShmemSize());
     124        4254 :     size = add_size(size, ProcSignalShmemSize());
     125        4254 :     size = add_size(size, CheckpointerShmemSize());
     126        4254 :     size = add_size(size, AutoVacuumShmemSize());
     127        4254 :     size = add_size(size, ReplicationSlotsShmemSize());
     128        4254 :     size = add_size(size, ReplicationOriginShmemSize());
     129        4254 :     size = add_size(size, WalSndShmemSize());
     130        4254 :     size = add_size(size, WalRcvShmemSize());
     131        4254 :     size = add_size(size, WalSummarizerShmemSize());
     132        4254 :     size = add_size(size, PgArchShmemSize());
     133        4254 :     size = add_size(size, ApplyLauncherShmemSize());
     134        4254 :     size = add_size(size, BTreeShmemSize());
     135        4254 :     size = add_size(size, SyncScanShmemSize());
     136        4254 :     size = add_size(size, AsyncShmemSize());
     137        4254 :     size = add_size(size, StatsShmemSize());
     138        4254 :     size = add_size(size, WaitEventCustomShmemSize());
     139        4254 :     size = add_size(size, InjectionPointShmemSize());
     140        4254 :     size = add_size(size, SlotSyncShmemSize());
     141        4254 :     size = add_size(size, AioShmemSize());
     142        4254 :     size = add_size(size, WaitLSNShmemSize());
     143        4254 :     size = add_size(size, LogicalDecodingCtlShmemSize());
     144             : 
     145             :     /* include additional requested shmem from preload libraries */
     146        4254 :     size = add_size(size, total_addin_request);
     147             : 
     148             :     /* might as well round it off to a multiple of a typical page size */
     149        4254 :     size = add_size(size, 8192 - (size % 8192));
     150             : 
     151        4254 :     return size;
     152             : }
     153             : 
     154             : #ifdef EXEC_BACKEND
     155             : /*
     156             :  * AttachSharedMemoryStructs
     157             :  *      Initialize a postmaster child process's access to shared memory
     158             :  *      structures.
     159             :  *
     160             :  * In !EXEC_BACKEND mode, we inherit everything through the fork, and this
     161             :  * isn't needed.
     162             :  */
     163             : void
     164             : AttachSharedMemoryStructs(void)
     165             : {
     166             :     /* InitProcess must've been called already */
     167             :     Assert(MyProc != NULL);
     168             :     Assert(IsUnderPostmaster);
     169             : 
     170             :     /*
     171             :      * In EXEC_BACKEND mode, backends don't inherit the number of fast-path
     172             :      * groups we calculated before setting the shmem up, so recalculate it.
     173             :      */
     174             :     InitializeFastPathLocks();
     175             : 
     176             :     CreateOrAttachShmemStructs();
     177             : 
     178             :     /*
     179             :      * Now give loadable modules a chance to set up their shmem allocations
     180             :      */
     181             :     if (shmem_startup_hook)
     182             :         shmem_startup_hook();
     183             : }
     184             : #endif
     185             : 
     186             : /*
     187             :  * CreateSharedMemoryAndSemaphores
     188             :  *      Creates and initializes shared memory and semaphores.
     189             :  */
     190             : void
     191        2284 : CreateSharedMemoryAndSemaphores(void)
     192             : {
     193             :     PGShmemHeader *shim;
     194             :     PGShmemHeader *seghdr;
     195             :     Size        size;
     196             : 
     197             :     Assert(!IsUnderPostmaster);
     198             : 
     199             :     /* Compute the size of the shared-memory block */
     200        2284 :     size = CalculateShmemSize();
     201        2284 :     elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
     202             : 
     203             :     /*
     204             :      * Create the shmem segment
     205             :      */
     206        2284 :     seghdr = PGSharedMemoryCreate(size, &shim);
     207             : 
     208             :     /*
     209             :      * Make sure that huge pages are never reported as "unknown" while the
     210             :      * server is running.
     211             :      */
     212             :     Assert(strcmp("unknown",
     213             :                   GetConfigOption("huge_pages_status", false, false)) != 0);
     214             : 
     215        2280 :     InitShmemAccess(seghdr);
     216             : 
     217             :     /*
     218             :      * Set up shared memory allocation mechanism
     219             :      */
     220        2280 :     InitShmemAllocation();
     221             : 
     222             :     /* Initialize subsystems */
     223        2280 :     CreateOrAttachShmemStructs();
     224             : 
     225             :     /* Initialize dynamic shared memory facilities. */
     226        2280 :     dsm_postmaster_startup(shim);
     227             : 
     228             :     /*
     229             :      * Now give loadable modules a chance to set up their shmem allocations
     230             :      */
     231        2280 :     if (shmem_startup_hook)
     232          28 :         shmem_startup_hook();
     233        2280 : }
     234             : 
     235             : /*
     236             :  * Initialize various subsystems, setting up their data structures in
     237             :  * shared memory.
     238             :  *
     239             :  * This is called by the postmaster or by a standalone backend.
     240             :  * It is also called by a backend forked from the postmaster in the
     241             :  * EXEC_BACKEND case.  In the latter case, the shared memory segment
     242             :  * already exists and has been physically attached to, but we have to
     243             :  * initialize pointers in local memory that reference the shared structures,
     244             :  * because we didn't inherit the correct pointer values from the postmaster
     245             :  * as we do in the fork() scenario.  The easiest way to do that is to run
     246             :  * through the same code as before.  (Note that the called routines mostly
     247             :  * check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case.
     248             :  * This is a bit code-wasteful and could be cleaned up.)
     249             :  */
     250             : static void
     251        2280 : CreateOrAttachShmemStructs(void)
     252             : {
     253             :     /*
     254             :      * Now initialize LWLocks, which do shared memory allocation and are
     255             :      * needed for InitShmemIndex.
     256             :      */
     257        2280 :     CreateLWLocks();
     258             : 
     259             :     /*
     260             :      * Set up shmem.c index hashtable
     261             :      */
     262        2280 :     InitShmemIndex();
     263             : 
     264        2280 :     dsm_shmem_init();
     265        2280 :     DSMRegistryShmemInit();
     266             : 
     267             :     /*
     268             :      * Set up xlog, clog, and buffers
     269             :      */
     270        2280 :     VarsupShmemInit();
     271        2280 :     XLOGShmemInit();
     272        2280 :     XLogPrefetchShmemInit();
     273        2280 :     XLogRecoveryShmemInit();
     274        2280 :     CLOGShmemInit();
     275        2280 :     CommitTsShmemInit();
     276        2280 :     SUBTRANSShmemInit();
     277        2280 :     MultiXactShmemInit();
     278        2280 :     BufferManagerShmemInit();
     279             : 
     280             :     /*
     281             :      * Set up lock manager
     282             :      */
     283        2280 :     LockManagerShmemInit();
     284             : 
     285             :     /*
     286             :      * Set up predicate lock manager
     287             :      */
     288        2280 :     PredicateLockShmemInit();
     289             : 
     290             :     /*
     291             :      * Set up process table
     292             :      */
     293        2280 :     if (!IsUnderPostmaster)
     294        2280 :         InitProcGlobal();
     295        2280 :     ProcArrayShmemInit();
     296        2280 :     BackendStatusShmemInit();
     297        2280 :     TwoPhaseShmemInit();
     298        2280 :     BackgroundWorkerShmemInit();
     299             : 
     300             :     /*
     301             :      * Set up shared-inval messaging
     302             :      */
     303        2280 :     SharedInvalShmemInit();
     304             : 
     305             :     /*
     306             :      * Set up interprocess signaling mechanisms
     307             :      */
     308        2280 :     PMSignalShmemInit();
     309        2280 :     ProcSignalShmemInit();
     310        2280 :     CheckpointerShmemInit();
     311        2280 :     AutoVacuumShmemInit();
     312        2280 :     ReplicationSlotsShmemInit();
     313        2280 :     ReplicationOriginShmemInit();
     314        2280 :     WalSndShmemInit();
     315        2280 :     WalRcvShmemInit();
     316        2280 :     WalSummarizerShmemInit();
     317        2280 :     PgArchShmemInit();
     318        2280 :     ApplyLauncherShmemInit();
     319        2280 :     SlotSyncShmemInit();
     320             : 
     321             :     /*
     322             :      * Set up other modules that need some shared memory space
     323             :      */
     324        2280 :     BTreeShmemInit();
     325        2280 :     SyncScanShmemInit();
     326        2280 :     AsyncShmemInit();
     327        2280 :     StatsShmemInit();
     328        2280 :     WaitEventCustomShmemInit();
     329        2280 :     InjectionPointShmemInit();
     330        2280 :     AioShmemInit();
     331        2280 :     WaitLSNShmemInit();
     332        2280 :     LogicalDecodingCtlShmemInit();
     333        2280 : }
     334             : 
     335             : /*
     336             :  * InitializeShmemGUCs
     337             :  *
     338             :  * This function initializes runtime-computed GUCs related to the amount of
     339             :  * shared memory required for the current configuration.
     340             :  */
     341             : void
     342        1970 : InitializeShmemGUCs(void)
     343             : {
     344             :     char        buf[64];
     345             :     Size        size_b;
     346             :     Size        size_mb;
     347             :     Size        hp_size;
     348             : 
     349             :     /*
     350             :      * Calculate the shared memory size and round up to the nearest megabyte.
     351             :      */
     352        1970 :     size_b = CalculateShmemSize();
     353        1970 :     size_mb = add_size(size_b, (1024 * 1024) - 1) / (1024 * 1024);
     354        1970 :     sprintf(buf, "%zu", size_mb);
     355        1970 :     SetConfigOption("shared_memory_size", buf,
     356             :                     PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
     357             : 
     358             :     /*
     359             :      * Calculate the number of huge pages required.
     360             :      */
     361        1970 :     GetHugePageSize(&hp_size, NULL);
     362        1970 :     if (hp_size != 0)
     363             :     {
     364             :         Size        hp_required;
     365             : 
     366        1970 :         hp_required = size_b / hp_size;
     367        1970 :         if (size_b % hp_size != 0)
     368        1970 :             hp_required = add_size(hp_required, 1);
     369        1970 :         sprintf(buf, "%zu", hp_required);
     370        1970 :         SetConfigOption("shared_memory_size_in_huge_pages", buf,
     371             :                         PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
     372             :     }
     373             : 
     374        1970 :     sprintf(buf, "%d", ProcGlobalSemas());
     375        1970 :     SetConfigOption("num_os_semaphores", buf, PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
     376        1970 : }

Generated by: LCOV version 1.16