1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-19 13:42:17 +03:00
Files
postgres/src/backend/storage/ipc/ipci.c
Daniel Gustafsson fb844b9f06 Revert function to get memory context stats for processes
Due to concerns raised about the approach, and memory leaks found
in sensitive contexts the functionality is reverted. This reverts
commits 45e7e8ca9, f8c115a6c, d2a1ed172, 55ef7abf8 and 042a66291
for v18 with an intent to revisit this patch for v19.

Discussion: https://postgr.es/m/594293.1747708165@sss.pgh.pa.us
2025-05-23 15:44:54 +02:00

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);
}