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

Generated by: LCOV version 2.0-1