mirror of
https://github.com/postgres/postgres.git
synced 2025-11-19 13:42:17 +03:00
Due to concerns raised about the approach, and memory leaks found in sensitive contexts the functionality is reverted. This reverts commits45e7e8ca9,f8c115a6c,d2a1ed172,55ef7abf8and042a66291for v18 with an intent to revisit this patch for v19. Discussion: https://postgr.es/m/594293.1747708165@sss.pgh.pa.us
389 lines
10 KiB
C
389 lines
10 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* ipci.c
|
|
* POSTGRES inter-process communication initialization code.
|
|
*
|
|
* Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
*
|
|
* IDENTIFICATION
|
|
* src/backend/storage/ipc/ipci.c
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#include "postgres.h"
|
|
|
|
#include "access/clog.h"
|
|
#include "access/commit_ts.h"
|
|
#include "access/multixact.h"
|
|
#include "access/nbtree.h"
|
|
#include "access/subtrans.h"
|
|
#include "access/syncscan.h"
|
|
#include "access/transam.h"
|
|
#include "access/twophase.h"
|
|
#include "access/xlogprefetcher.h"
|
|
#include "access/xlogrecovery.h"
|
|
#include "commands/async.h"
|
|
#include "miscadmin.h"
|
|
#include "pgstat.h"
|
|
#include "postmaster/autovacuum.h"
|
|
#include "postmaster/bgworker_internals.h"
|
|
#include "postmaster/bgwriter.h"
|
|
#include "postmaster/walsummarizer.h"
|
|
#include "replication/logicallauncher.h"
|
|
#include "replication/origin.h"
|
|
#include "replication/slot.h"
|
|
#include "replication/slotsync.h"
|
|
#include "replication/walreceiver.h"
|
|
#include "replication/walsender.h"
|
|
#include "storage/aio_subsys.h"
|
|
#include "storage/bufmgr.h"
|
|
#include "storage/dsm.h"
|
|
#include "storage/dsm_registry.h"
|
|
#include "storage/ipc.h"
|
|
#include "storage/pg_shmem.h"
|
|
#include "storage/pmsignal.h"
|
|
#include "storage/predicate.h"
|
|
#include "storage/proc.h"
|
|
#include "storage/procarray.h"
|
|
#include "storage/procsignal.h"
|
|
#include "storage/sinvaladt.h"
|
|
#include "utils/guc.h"
|
|
#include "utils/injection_point.h"
|
|
|
|
/* GUCs */
|
|
int shared_memory_type = DEFAULT_SHARED_MEMORY_TYPE;
|
|
|
|
shmem_startup_hook_type shmem_startup_hook = NULL;
|
|
|
|
static Size total_addin_request = 0;
|
|
|
|
static void CreateOrAttachShmemStructs(void);
|
|
|
|
/*
|
|
* RequestAddinShmemSpace
|
|
* Request that extra shmem space be allocated for use by
|
|
* a loadable module.
|
|
*
|
|
* This may only be called via the shmem_request_hook of a library that is
|
|
* loaded into the postmaster via shared_preload_libraries. Calls from
|
|
* elsewhere will fail.
|
|
*/
|
|
void
|
|
RequestAddinShmemSpace(Size size)
|
|
{
|
|
if (!process_shmem_requests_in_progress)
|
|
elog(FATAL, "cannot request additional shared memory outside shmem_request_hook");
|
|
total_addin_request = add_size(total_addin_request, size);
|
|
}
|
|
|
|
/*
|
|
* CalculateShmemSize
|
|
* Calculates the amount of shared memory and number of semaphores needed.
|
|
*
|
|
* If num_semaphores is not NULL, it will be set to the number of semaphores
|
|
* required.
|
|
*/
|
|
Size
|
|
CalculateShmemSize(int *num_semaphores)
|
|
{
|
|
Size size;
|
|
int numSemas;
|
|
|
|
/* Compute number of semaphores we'll need */
|
|
numSemas = ProcGlobalSemas();
|
|
|
|
/* Return the number of semaphores if requested by the caller */
|
|
if (num_semaphores)
|
|
*num_semaphores = numSemas;
|
|
|
|
/*
|
|
* Size of the Postgres shared-memory block is estimated via moderately-
|
|
* accurate estimates for the big hogs, plus 100K for the stuff that's too
|
|
* small to bother with estimating.
|
|
*
|
|
* We take some care to ensure that the total size request doesn't
|
|
* overflow size_t. If this gets through, we don't need to be so careful
|
|
* during the actual allocation phase.
|
|
*/
|
|
size = 100000;
|
|
size = add_size(size, PGSemaphoreShmemSize(numSemas));
|
|
size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
|
|
sizeof(ShmemIndexEnt)));
|
|
size = add_size(size, dsm_estimate_size());
|
|
size = add_size(size, DSMRegistryShmemSize());
|
|
size = add_size(size, BufferManagerShmemSize());
|
|
size = add_size(size, LockManagerShmemSize());
|
|
size = add_size(size, PredicateLockShmemSize());
|
|
size = add_size(size, ProcGlobalShmemSize());
|
|
size = add_size(size, XLogPrefetchShmemSize());
|
|
size = add_size(size, VarsupShmemSize());
|
|
size = add_size(size, XLOGShmemSize());
|
|
size = add_size(size, XLogRecoveryShmemSize());
|
|
size = add_size(size, CLOGShmemSize());
|
|
size = add_size(size, CommitTsShmemSize());
|
|
size = add_size(size, SUBTRANSShmemSize());
|
|
size = add_size(size, TwoPhaseShmemSize());
|
|
size = add_size(size, BackgroundWorkerShmemSize());
|
|
size = add_size(size, MultiXactShmemSize());
|
|
size = add_size(size, LWLockShmemSize());
|
|
size = add_size(size, ProcArrayShmemSize());
|
|
size = add_size(size, BackendStatusShmemSize());
|
|
size = add_size(size, SharedInvalShmemSize());
|
|
size = add_size(size, PMSignalShmemSize());
|
|
size = add_size(size, ProcSignalShmemSize());
|
|
size = add_size(size, CheckpointerShmemSize());
|
|
size = add_size(size, AutoVacuumShmemSize());
|
|
size = add_size(size, ReplicationSlotsShmemSize());
|
|
size = add_size(size, ReplicationOriginShmemSize());
|
|
size = add_size(size, WalSndShmemSize());
|
|
size = add_size(size, WalRcvShmemSize());
|
|
size = add_size(size, WalSummarizerShmemSize());
|
|
size = add_size(size, PgArchShmemSize());
|
|
size = add_size(size, ApplyLauncherShmemSize());
|
|
size = add_size(size, BTreeShmemSize());
|
|
size = add_size(size, SyncScanShmemSize());
|
|
size = add_size(size, AsyncShmemSize());
|
|
size = add_size(size, StatsShmemSize());
|
|
size = add_size(size, WaitEventCustomShmemSize());
|
|
size = add_size(size, InjectionPointShmemSize());
|
|
size = add_size(size, SlotSyncShmemSize());
|
|
size = add_size(size, AioShmemSize());
|
|
|
|
/* include additional requested shmem from preload libraries */
|
|
size = add_size(size, total_addin_request);
|
|
|
|
/* might as well round it off to a multiple of a typical page size */
|
|
size = add_size(size, 8192 - (size % 8192));
|
|
|
|
return size;
|
|
}
|
|
|
|
#ifdef EXEC_BACKEND
|
|
/*
|
|
* AttachSharedMemoryStructs
|
|
* Initialize a postmaster child process's access to shared memory
|
|
* structures.
|
|
*
|
|
* In !EXEC_BACKEND mode, we inherit everything through the fork, and this
|
|
* isn't needed.
|
|
*/
|
|
void
|
|
AttachSharedMemoryStructs(void)
|
|
{
|
|
/* InitProcess must've been called already */
|
|
Assert(MyProc != NULL);
|
|
Assert(IsUnderPostmaster);
|
|
|
|
/*
|
|
* In EXEC_BACKEND mode, backends don't inherit the number of fast-path
|
|
* groups we calculated before setting the shmem up, so recalculate it.
|
|
*/
|
|
InitializeFastPathLocks();
|
|
|
|
CreateOrAttachShmemStructs();
|
|
|
|
/*
|
|
* Now give loadable modules a chance to set up their shmem allocations
|
|
*/
|
|
if (shmem_startup_hook)
|
|
shmem_startup_hook();
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* CreateSharedMemoryAndSemaphores
|
|
* Creates and initializes shared memory and semaphores.
|
|
*/
|
|
void
|
|
CreateSharedMemoryAndSemaphores(void)
|
|
{
|
|
PGShmemHeader *shim;
|
|
PGShmemHeader *seghdr;
|
|
Size size;
|
|
int numSemas;
|
|
|
|
Assert(!IsUnderPostmaster);
|
|
|
|
/* Compute the size of the shared-memory block */
|
|
size = CalculateShmemSize(&numSemas);
|
|
elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
|
|
|
|
/*
|
|
* Create the shmem segment
|
|
*/
|
|
seghdr = PGSharedMemoryCreate(size, &shim);
|
|
|
|
/*
|
|
* Make sure that huge pages are never reported as "unknown" while the
|
|
* server is running.
|
|
*/
|
|
Assert(strcmp("unknown",
|
|
GetConfigOption("huge_pages_status", false, false)) != 0);
|
|
|
|
InitShmemAccess(seghdr);
|
|
|
|
/*
|
|
* Create semaphores
|
|
*/
|
|
PGReserveSemaphores(numSemas);
|
|
|
|
/*
|
|
* Set up shared memory allocation mechanism
|
|
*/
|
|
InitShmemAllocation();
|
|
|
|
/* Initialize subsystems */
|
|
CreateOrAttachShmemStructs();
|
|
|
|
/* Initialize dynamic shared memory facilities. */
|
|
dsm_postmaster_startup(shim);
|
|
|
|
/*
|
|
* Now give loadable modules a chance to set up their shmem allocations
|
|
*/
|
|
if (shmem_startup_hook)
|
|
shmem_startup_hook();
|
|
}
|
|
|
|
/*
|
|
* Initialize various subsystems, setting up their data structures in
|
|
* shared memory.
|
|
*
|
|
* This is called by the postmaster or by a standalone backend.
|
|
* It is also called by a backend forked from the postmaster in the
|
|
* EXEC_BACKEND case. In the latter case, the shared memory segment
|
|
* already exists and has been physically attached to, but we have to
|
|
* initialize pointers in local memory that reference the shared structures,
|
|
* because we didn't inherit the correct pointer values from the postmaster
|
|
* as we do in the fork() scenario. The easiest way to do that is to run
|
|
* through the same code as before. (Note that the called routines mostly
|
|
* check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case.
|
|
* This is a bit code-wasteful and could be cleaned up.)
|
|
*/
|
|
static void
|
|
CreateOrAttachShmemStructs(void)
|
|
{
|
|
/*
|
|
* Now initialize LWLocks, which do shared memory allocation and are
|
|
* needed for InitShmemIndex.
|
|
*/
|
|
CreateLWLocks();
|
|
|
|
/*
|
|
* Set up shmem.c index hashtable
|
|
*/
|
|
InitShmemIndex();
|
|
|
|
dsm_shmem_init();
|
|
DSMRegistryShmemInit();
|
|
|
|
/*
|
|
* Set up xlog, clog, and buffers
|
|
*/
|
|
VarsupShmemInit();
|
|
XLOGShmemInit();
|
|
XLogPrefetchShmemInit();
|
|
XLogRecoveryShmemInit();
|
|
CLOGShmemInit();
|
|
CommitTsShmemInit();
|
|
SUBTRANSShmemInit();
|
|
MultiXactShmemInit();
|
|
BufferManagerShmemInit();
|
|
|
|
/*
|
|
* Set up lock manager
|
|
*/
|
|
LockManagerShmemInit();
|
|
|
|
/*
|
|
* Set up predicate lock manager
|
|
*/
|
|
PredicateLockShmemInit();
|
|
|
|
/*
|
|
* Set up process table
|
|
*/
|
|
if (!IsUnderPostmaster)
|
|
InitProcGlobal();
|
|
ProcArrayShmemInit();
|
|
BackendStatusShmemInit();
|
|
TwoPhaseShmemInit();
|
|
BackgroundWorkerShmemInit();
|
|
|
|
/*
|
|
* Set up shared-inval messaging
|
|
*/
|
|
SharedInvalShmemInit();
|
|
|
|
/*
|
|
* Set up interprocess signaling mechanisms
|
|
*/
|
|
PMSignalShmemInit();
|
|
ProcSignalShmemInit();
|
|
CheckpointerShmemInit();
|
|
AutoVacuumShmemInit();
|
|
ReplicationSlotsShmemInit();
|
|
ReplicationOriginShmemInit();
|
|
WalSndShmemInit();
|
|
WalRcvShmemInit();
|
|
WalSummarizerShmemInit();
|
|
PgArchShmemInit();
|
|
ApplyLauncherShmemInit();
|
|
SlotSyncShmemInit();
|
|
|
|
/*
|
|
* Set up other modules that need some shared memory space
|
|
*/
|
|
BTreeShmemInit();
|
|
SyncScanShmemInit();
|
|
AsyncShmemInit();
|
|
StatsShmemInit();
|
|
WaitEventCustomShmemInit();
|
|
InjectionPointShmemInit();
|
|
AioShmemInit();
|
|
}
|
|
|
|
/*
|
|
* InitializeShmemGUCs
|
|
*
|
|
* This function initializes runtime-computed GUCs related to the amount of
|
|
* shared memory required for the current configuration.
|
|
*/
|
|
void
|
|
InitializeShmemGUCs(void)
|
|
{
|
|
char buf[64];
|
|
Size size_b;
|
|
Size size_mb;
|
|
Size hp_size;
|
|
int num_semas;
|
|
|
|
/*
|
|
* Calculate the shared memory size and round up to the nearest megabyte.
|
|
*/
|
|
size_b = CalculateShmemSize(&num_semas);
|
|
size_mb = add_size(size_b, (1024 * 1024) - 1) / (1024 * 1024);
|
|
sprintf(buf, "%zu", size_mb);
|
|
SetConfigOption("shared_memory_size", buf,
|
|
PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
|
|
|
|
/*
|
|
* Calculate the number of huge pages required.
|
|
*/
|
|
GetHugePageSize(&hp_size, NULL);
|
|
if (hp_size != 0)
|
|
{
|
|
Size hp_required;
|
|
|
|
hp_required = add_size(size_b / hp_size, 1);
|
|
sprintf(buf, "%zu", hp_required);
|
|
SetConfigOption("shared_memory_size_in_huge_pages", buf,
|
|
PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
|
|
}
|
|
|
|
sprintf(buf, "%d", num_semas);
|
|
SetConfigOption("num_os_semaphores", buf, PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
|
|
}
|