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-03 14:15:12 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              : 
      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           16 : RequestAddinShmemSpace(Size size)
      76              : {
      77           16 :     if (!process_shmem_requests_in_progress)
      78            0 :         elog(FATAL, "cannot request additional shared memory outside shmem_request_hook");
      79           16 :     total_addin_request = add_size(total_addin_request, size);
      80           16 : }
      81              : 
      82              : /*
      83              :  * CalculateShmemSize
      84              :  *      Calculates the amount of shared memory needed.
      85              :  */
      86              : Size
      87         2149 : 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         2149 :     size = 100000;
     101         2149 :     size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
     102              :                                              sizeof(ShmemIndexEnt)));
     103         2149 :     size = add_size(size, dsm_estimate_size());
     104         2149 :     size = add_size(size, DSMRegistryShmemSize());
     105         2149 :     size = add_size(size, BufferManagerShmemSize());
     106         2149 :     size = add_size(size, LockManagerShmemSize());
     107         2149 :     size = add_size(size, PredicateLockShmemSize());
     108         2149 :     size = add_size(size, ProcGlobalShmemSize());
     109         2149 :     size = add_size(size, XLogPrefetchShmemSize());
     110         2149 :     size = add_size(size, VarsupShmemSize());
     111         2149 :     size = add_size(size, XLOGShmemSize());
     112         2149 :     size = add_size(size, XLogRecoveryShmemSize());
     113         2149 :     size = add_size(size, CLOGShmemSize());
     114         2149 :     size = add_size(size, CommitTsShmemSize());
     115         2149 :     size = add_size(size, SUBTRANSShmemSize());
     116         2149 :     size = add_size(size, TwoPhaseShmemSize());
     117         2149 :     size = add_size(size, BackgroundWorkerShmemSize());
     118         2149 :     size = add_size(size, MultiXactShmemSize());
     119         2149 :     size = add_size(size, LWLockShmemSize());
     120         2149 :     size = add_size(size, ProcArrayShmemSize());
     121         2149 :     size = add_size(size, BackendStatusShmemSize());
     122         2149 :     size = add_size(size, SharedInvalShmemSize());
     123         2149 :     size = add_size(size, PMSignalShmemSize());
     124         2149 :     size = add_size(size, ProcSignalShmemSize());
     125         2149 :     size = add_size(size, CheckpointerShmemSize());
     126         2149 :     size = add_size(size, AutoVacuumShmemSize());
     127         2149 :     size = add_size(size, ReplicationSlotsShmemSize());
     128         2149 :     size = add_size(size, ReplicationOriginShmemSize());
     129         2149 :     size = add_size(size, WalSndShmemSize());
     130         2149 :     size = add_size(size, WalRcvShmemSize());
     131         2149 :     size = add_size(size, WalSummarizerShmemSize());
     132         2149 :     size = add_size(size, PgArchShmemSize());
     133         2149 :     size = add_size(size, ApplyLauncherShmemSize());
     134         2149 :     size = add_size(size, BTreeShmemSize());
     135         2149 :     size = add_size(size, SyncScanShmemSize());
     136         2149 :     size = add_size(size, AsyncShmemSize());
     137         2149 :     size = add_size(size, StatsShmemSize());
     138         2149 :     size = add_size(size, WaitEventCustomShmemSize());
     139         2149 :     size = add_size(size, InjectionPointShmemSize());
     140         2149 :     size = add_size(size, SlotSyncShmemSize());
     141         2149 :     size = add_size(size, AioShmemSize());
     142         2149 :     size = add_size(size, WaitLSNShmemSize());
     143         2149 :     size = add_size(size, LogicalDecodingCtlShmemSize());
     144              : 
     145              :     /* include additional requested shmem from preload libraries */
     146         2149 :     size = add_size(size, total_addin_request);
     147              : 
     148              :     /* might as well round it off to a multiple of a typical page size */
     149         2149 :     size = add_size(size, 8192 - (size % 8192));
     150              : 
     151         2149 :     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         1153 : 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         1153 :     size = CalculateShmemSize();
     201         1153 :     elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
     202              : 
     203              :     /*
     204              :      * Create the shmem segment
     205              :      */
     206         1153 :     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              :     /*
     216              :      * Set up shared memory allocation mechanism
     217              :      */
     218         1151 :     InitShmemAllocator(seghdr);
     219              : 
     220              :     /* Initialize subsystems */
     221         1151 :     CreateOrAttachShmemStructs();
     222              : 
     223              :     /* Initialize dynamic shared memory facilities. */
     224         1151 :     dsm_postmaster_startup(shim);
     225              : 
     226              :     /*
     227              :      * Now give loadable modules a chance to set up their shmem allocations
     228              :      */
     229         1151 :     if (shmem_startup_hook)
     230           14 :         shmem_startup_hook();
     231         1151 : }
     232              : 
     233              : /*
     234              :  * Initialize various subsystems, setting up their data structures in
     235              :  * shared memory.
     236              :  *
     237              :  * This is called by the postmaster or by a standalone backend.
     238              :  * It is also called by a backend forked from the postmaster in the
     239              :  * EXEC_BACKEND case.  In the latter case, the shared memory segment
     240              :  * already exists and has been physically attached to, but we have to
     241              :  * initialize pointers in local memory that reference the shared structures,
     242              :  * because we didn't inherit the correct pointer values from the postmaster
     243              :  * as we do in the fork() scenario.  The easiest way to do that is to run
     244              :  * through the same code as before.  (Note that the called routines mostly
     245              :  * check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case.
     246              :  * This is a bit code-wasteful and could be cleaned up.)
     247              :  */
     248              : static void
     249         1151 : CreateOrAttachShmemStructs(void)
     250              : {
     251              :     /*
     252              :      * Now initialize LWLocks, which do shared memory allocation and are
     253              :      * needed for InitShmemIndex.
     254              :      */
     255         1151 :     CreateLWLocks();
     256              : 
     257              :     /*
     258              :      * Set up shmem.c index hashtable
     259              :      */
     260         1151 :     InitShmemIndex();
     261              : 
     262         1151 :     dsm_shmem_init();
     263         1151 :     DSMRegistryShmemInit();
     264              : 
     265              :     /*
     266              :      * Set up xlog, clog, and buffers
     267              :      */
     268         1151 :     VarsupShmemInit();
     269         1151 :     XLOGShmemInit();
     270         1151 :     XLogPrefetchShmemInit();
     271         1151 :     XLogRecoveryShmemInit();
     272         1151 :     CLOGShmemInit();
     273         1151 :     CommitTsShmemInit();
     274         1151 :     SUBTRANSShmemInit();
     275         1151 :     MultiXactShmemInit();
     276         1151 :     BufferManagerShmemInit();
     277              : 
     278              :     /*
     279              :      * Set up lock manager
     280              :      */
     281         1151 :     LockManagerShmemInit();
     282              : 
     283              :     /*
     284              :      * Set up predicate lock manager
     285              :      */
     286         1151 :     PredicateLockShmemInit();
     287              : 
     288              :     /*
     289              :      * Set up process table
     290              :      */
     291         1151 :     if (!IsUnderPostmaster)
     292         1151 :         InitProcGlobal();
     293         1151 :     ProcArrayShmemInit();
     294         1151 :     BackendStatusShmemInit();
     295         1151 :     TwoPhaseShmemInit();
     296         1151 :     BackgroundWorkerShmemInit();
     297              : 
     298              :     /*
     299              :      * Set up shared-inval messaging
     300              :      */
     301         1151 :     SharedInvalShmemInit();
     302              : 
     303              :     /*
     304              :      * Set up interprocess signaling mechanisms
     305              :      */
     306         1151 :     PMSignalShmemInit();
     307         1151 :     ProcSignalShmemInit();
     308         1151 :     CheckpointerShmemInit();
     309         1151 :     AutoVacuumShmemInit();
     310         1151 :     ReplicationSlotsShmemInit();
     311         1151 :     ReplicationOriginShmemInit();
     312         1151 :     WalSndShmemInit();
     313         1151 :     WalRcvShmemInit();
     314         1151 :     WalSummarizerShmemInit();
     315         1151 :     PgArchShmemInit();
     316         1151 :     ApplyLauncherShmemInit();
     317         1151 :     SlotSyncShmemInit();
     318              : 
     319              :     /*
     320              :      * Set up other modules that need some shared memory space
     321              :      */
     322         1151 :     BTreeShmemInit();
     323         1151 :     SyncScanShmemInit();
     324         1151 :     AsyncShmemInit();
     325         1151 :     StatsShmemInit();
     326         1151 :     WaitEventCustomShmemInit();
     327         1151 :     InjectionPointShmemInit();
     328         1151 :     AioShmemInit();
     329         1151 :     WaitLSNShmemInit();
     330         1151 :     LogicalDecodingCtlShmemInit();
     331         1151 : }
     332              : 
     333              : /*
     334              :  * InitializeShmemGUCs
     335              :  *
     336              :  * This function initializes runtime-computed GUCs related to the amount of
     337              :  * shared memory required for the current configuration.
     338              :  */
     339              : void
     340          996 : InitializeShmemGUCs(void)
     341              : {
     342              :     char        buf[64];
     343              :     Size        size_b;
     344              :     Size        size_mb;
     345              :     Size        hp_size;
     346              : 
     347              :     /*
     348              :      * Calculate the shared memory size and round up to the nearest megabyte.
     349              :      */
     350          996 :     size_b = CalculateShmemSize();
     351          996 :     size_mb = add_size(size_b, (1024 * 1024) - 1) / (1024 * 1024);
     352          996 :     sprintf(buf, "%zu", size_mb);
     353          996 :     SetConfigOption("shared_memory_size", buf,
     354              :                     PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
     355              : 
     356              :     /*
     357              :      * Calculate the number of huge pages required.
     358              :      */
     359          996 :     GetHugePageSize(&hp_size, NULL);
     360          996 :     if (hp_size != 0)
     361              :     {
     362              :         Size        hp_required;
     363              : 
     364          996 :         hp_required = size_b / hp_size;
     365          996 :         if (size_b % hp_size != 0)
     366          996 :             hp_required = add_size(hp_required, 1);
     367          996 :         sprintf(buf, "%zu", hp_required);
     368          996 :         SetConfigOption("shared_memory_size_in_huge_pages", buf,
     369              :                         PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
     370              :     }
     371              : 
     372          996 :     sprintf(buf, "%d", ProcGlobalSemas());
     373          996 :     SetConfigOption("num_os_semaphores", buf, PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
     374          996 : }
        

Generated by: LCOV version 2.0-1