gxacts[i].next = TwoPhaseState->freeGXacts;
TwoPhaseState->freeGXacts = &gxacts[i];
- /* associate it with a PGPROC assigned by InitProcGlobal */
+ /* associate it with a PGPROC assigned by ProcGlobalShmemInit */
gxacts[i].pgprocno = GetNumberFromPGProc(&PreparedXactProcs[i]);
}
}
#include "postmaster/autovacuum.h"
#include "storage/pmsignal.h"
#include "storage/proc.h"
+#include "storage/subsystems.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
/* Number of OIDs to prefetch (preallocate) per XLOG write */
#define VAR_OID_PREFETCH 8192
+static void VarsupShmemRequest(void *arg);
+
/* pointer to variables struct in shared memory */
TransamVariablesData *TransamVariables = NULL;
+const ShmemCallbacks VarsupShmemCallbacks = {
+ .request_fn = VarsupShmemRequest,
+};
/*
- * Initialization of shared memory for TransamVariables.
+ * Request shared memory for TransamVariables.
*/
-Size
-VarsupShmemSize(void)
-{
- return sizeof(TransamVariablesData);
-}
-
-void
-VarsupShmemInit(void)
+static void
+VarsupShmemRequest(void *arg)
{
- bool found;
-
- /* Initialize our shared state struct */
- TransamVariables = ShmemInitStruct("TransamVariables",
- sizeof(TransamVariablesData),
- &found);
- if (!IsUnderPostmaster)
- {
- Assert(!found);
- memset(TransamVariables, 0, sizeof(TransamVariablesData));
- }
- else
- Assert(found);
+ ShmemRequestStruct(.name = "TransamVariables",
+ .size = sizeof(TransamVariablesData),
+ .ptr = (void **) &TransamVariables,
+ );
}
/*
/*
- * Report amount of shared memory needed for semaphores
+ * Request shared memory needed for semaphores
*/
-Size
-PGSemaphoreShmemSize(int maxSemas)
+void
+PGSemaphoreShmemRequest(int maxSemas)
{
#ifdef USE_NAMED_POSIX_SEMAPHORES
/* No shared memory needed in this case */
- return 0;
#else
/* Need a PGSemaphoreData per semaphore */
- return mul_size(maxSemas, sizeof(PGSemaphoreData));
+ ShmemRequestStruct(.name = "Semaphores",
+ .size = mul_size(maxSemas, sizeof(PGSemaphoreData)),
+ .ptr = (void **) &sharedSemas,
+ );
#endif
}
/*
- * PGReserveSemaphores --- initialize semaphore support
+ * PGSemaphoreInit --- initialize semaphore support
*
* This is called during postmaster start or shared memory reinitialization.
* It should do whatever is needed to be able to support up to maxSemas
* we don't have to expose the counters to other processes.)
*/
void
-PGReserveSemaphores(int maxSemas)
+PGSemaphoreInit(int maxSemas)
{
struct stat statbuf;
- bool found;
/*
* We use the data directory's inode number to seed the search for free
mySemPointers = (sem_t **) malloc(maxSemas * sizeof(sem_t *));
if (mySemPointers == NULL)
elog(PANIC, "out of memory");
-#else
-
- sharedSemas = (PGSemaphore)
- ShmemInitStruct("Semaphores", PGSemaphoreShmemSize(maxSemas), &found);
- Assert(!found);
#endif
numSems = 0;
/*
- * Report amount of shared memory needed for semaphores
+ * Request shared memory needed for semaphores
*/
-Size
-PGSemaphoreShmemSize(int maxSemas)
+void
+PGSemaphoreShmemRequest(int maxSemas)
{
- return mul_size(maxSemas, sizeof(PGSemaphoreData));
+ /* Need a PGSemaphoreData per semaphore */
+ ShmemRequestStruct(.name = "Semaphores",
+ .size = mul_size(maxSemas, sizeof(PGSemaphoreData)),
+ .ptr = (void **) &sharedSemas,
+ );
}
/*
- * PGReserveSemaphores --- initialize semaphore support
+ * PGSemaphoreInit --- initialize semaphore support
*
* This is called during postmaster start or shared memory reinitialization.
* It should do whatever is needed to be able to support up to maxSemas
* have clobbered.)
*/
void
-PGReserveSemaphores(int maxSemas)
+PGSemaphoreInit(int maxSemas)
{
struct stat statbuf;
- bool found;
/*
* We use the data directory's inode number to seed the search for free
errmsg("could not stat data directory \"%s\": %m",
DataDir)));
- sharedSemas = (PGSemaphore)
- ShmemInitStruct("Semaphores", PGSemaphoreShmemSize(maxSemas), &found);
- Assert(!found);
-
numSharedSemas = 0;
maxSharedSemas = maxSemas;
/*
- * Report amount of shared memory needed for semaphores
+ * Request shared memory needed for semaphores
*/
-Size
-PGSemaphoreShmemSize(int maxSemas)
+void
+PGSemaphoreShmemRequest(int maxSemas)
{
/* No shared memory needed on Windows */
- return 0;
}
/*
- * PGReserveSemaphores --- initialize semaphore support
+ * PGSemaphoreInit --- initialize semaphore support
*
* In the Win32 implementation, we acquire semaphores on-demand; the
* maxSemas parameter is just used to size the array that keeps track of
* process exits.
*/
void
-PGReserveSemaphores(int maxSemas)
+PGSemaphoreInit(int maxSemas)
{
mySemSet = (HANDLE *) malloc(maxSemas * sizeof(HANDLE));
if (mySemSet == NULL)
#include "storage/lwlock.h"
#include "storage/pg_shmem.h"
#include "storage/shmem.h"
+#include "storage/subsystems.h"
#include "utils/freepage.h"
#include "utils/memutils.h"
#include "utils/resowner.h"
/* Preallocated DSM space in the main shared memory region. */
static void *dsm_main_space_begin = NULL;
+static size_t dsm_main_space_size;
+
+static void dsm_main_space_request(void *arg);
+static void dsm_main_space_init(void *arg);
+
+const ShmemCallbacks dsm_shmem_callbacks = {
+ .request_fn = dsm_main_space_request,
+ .init_fn = dsm_main_space_init,
+};
/*
* List of dynamic shared memory segments used by this backend.
#endif
/*
- * Reserve some space in the main shared memory segment for DSM segments.
+ * Reserve space in the main shared memory segment for DSM segments.
*/
-size_t
-dsm_estimate_size(void)
+static void
+dsm_main_space_request(void *arg)
{
- return 1024 * 1024 * (size_t) min_dynamic_shared_memory;
+ dsm_main_space_size = 1024 * 1024 * (size_t) min_dynamic_shared_memory;
+
+ if (dsm_main_space_size == 0)
+ return;
+
+ ShmemRequestStruct(.name = "Preallocated DSM",
+ .size = dsm_main_space_size,
+ .ptr = &dsm_main_space_begin,
+ );
}
-/*
- * Initialize space in the main shared memory segment for DSM segments.
- */
-void
-dsm_shmem_init(void)
+static void
+dsm_main_space_init(void *arg)
{
- size_t size = dsm_estimate_size();
- bool found;
+ FreePageManager *fpm = (FreePageManager *) dsm_main_space_begin;
+ size_t first_page = 0;
+ size_t pages;
- if (size == 0)
+ if (dsm_main_space_size == 0)
return;
- dsm_main_space_begin = ShmemInitStruct("Preallocated DSM", size, &found);
- if (!found)
- {
- FreePageManager *fpm = (FreePageManager *) dsm_main_space_begin;
- size_t first_page = 0;
- size_t pages;
-
- /* Reserve space for the FreePageManager. */
- while (first_page * FPM_PAGE_SIZE < sizeof(FreePageManager))
- ++first_page;
-
- /* Initialize it and give it all the rest of the space. */
- FreePageManagerInitialize(fpm, dsm_main_space_begin);
- pages = (size / FPM_PAGE_SIZE) - first_page;
- FreePageManagerPut(fpm, first_page, pages);
- }
+ /* Reserve space for the FreePageManager. */
+ while (first_page * FPM_PAGE_SIZE < sizeof(FreePageManager))
+ ++first_page;
+
+ /* Initialize it and give it all the rest of the space. */
+ FreePageManagerInitialize(fpm, dsm_main_space_begin);
+ pages = (dsm_main_space_size / FPM_PAGE_SIZE) - first_page;
+ FreePageManagerPut(fpm, first_page, pages);
}
/*
#include "storage/dsm_registry.h"
#include "storage/lwlock.h"
#include "storage/shmem.h"
+#include "storage/subsystems.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/tuplestore.h"
static DSMRegistryCtxStruct *DSMRegistryCtx;
+static void DSMRegistryShmemRequest(void *arg);
+static void DSMRegistryShmemInit(void *arg);
+
+const ShmemCallbacks DSMRegistryShmemCallbacks = {
+ .request_fn = DSMRegistryShmemRequest,
+ .init_fn = DSMRegistryShmemInit,
+};
+
typedef struct NamedDSMState
{
dsm_handle handle;
static dsa_area *dsm_registry_dsa;
static dshash_table *dsm_registry_table;
-Size
-DSMRegistryShmemSize(void)
+static void
+DSMRegistryShmemRequest(void *arg)
{
- return MAXALIGN(sizeof(DSMRegistryCtxStruct));
+ ShmemRequestStruct(.name = "DSM Registry Data",
+ .size = sizeof(DSMRegistryCtxStruct),
+ .ptr = (void **) &DSMRegistryCtx,
+ );
}
-void
-DSMRegistryShmemInit(void)
+static void
+DSMRegistryShmemInit(void *arg)
{
- bool found;
-
- DSMRegistryCtx = (DSMRegistryCtxStruct *)
- ShmemInitStruct("DSM Registry Data",
- DSMRegistryShmemSize(),
- &found);
-
- if (!found)
- {
- DSMRegistryCtx->dsah = DSA_HANDLE_INVALID;
- DSMRegistryCtx->dshh = DSHASH_HANDLE_INVALID;
- }
+ DSMRegistryCtx->dsah = DSA_HANDLE_INVALID;
+ DSMRegistryCtx->dshh = DSHASH_HANDLE_INVALID;
}
/*
#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 "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/shmem_internal.h"
-#include "storage/sinvaladt.h"
#include "storage/subsystems.h"
#include "utils/guc.h"
#include "utils/injection_point.h"
size = add_size(size, ShmemGetRequestedSize());
/* legacy subsystems */
- 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, TwoPhaseShmemSize());
size = add_size(size, BackgroundWorkerShmemSize());
size = add_size(size, MultiXactShmemSize());
- 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());
static void
CreateOrAttachShmemStructs(void)
{
- dsm_shmem_init();
- DSMRegistryShmemInit();
-
/*
* Set up xlog, clog, and buffers
*/
- VarsupShmemInit();
XLOGShmemInit();
XLogPrefetchShmemInit();
XLogRecoveryShmemInit();
/*
* 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();
* current process.
*
* InitSharedLatch needs to be called in postmaster before forking child
- * processes, usually right after allocating the shared memory block
- * containing the latch with ShmemInitStruct. (The Unix implementation
- * doesn't actually require that, but the Windows one does.) Because of
- * this restriction, we have no concurrency issues to worry about here.
+ * processes, usually right after initializing the shared memory block
+ * containing the latch. (The Unix implementation doesn't actually require
+ * that, but the Windows one does.) Because of this restriction, we have no
+ * concurrency issues to worry about here.
*
* Note that other handles created in this module are never marked as
* inheritable. Thus we do not need to worry about cleaning up child
#include "storage/ipc.h"
#include "storage/pmsignal.h"
#include "storage/shmem.h"
+#include "storage/subsystems.h"
#include "utils/memutils.h"
/* PMSignalState pointer is valid in both postmaster and child processes */
NON_EXEC_STATIC volatile PMSignalData *PMSignalState = NULL;
+static void PMSignalShmemRequest(void *);
+static void PMSignalShmemInit(void *);
+
+const ShmemCallbacks PMSignalShmemCallbacks = {
+ .request_fn = PMSignalShmemRequest,
+ .init_fn = PMSignalShmemInit,
+};
+
/*
* Local copy of PMSignalState->num_child_flags, only valid in the
* postmaster. Postmaster keeps a local copy so that it doesn't need to
static void MarkPostmasterChildInactive(int code, Datum arg);
/*
- * PMSignalShmemSize
- * Compute space needed for pmsignal.c's shared memory
+ * PMSignalShmemRequest - Register pmsignal.c's shared memory needs
*/
-Size
-PMSignalShmemSize(void)
+static void
+PMSignalShmemRequest(void *arg)
{
- Size size;
+ size_t size;
- size = offsetof(PMSignalData, PMChildFlags);
- size = add_size(size, mul_size(MaxLivePostmasterChildren(),
- sizeof(sig_atomic_t)));
+ num_child_flags = MaxLivePostmasterChildren();
- return size;
+ size = add_size(offsetof(PMSignalData, PMChildFlags),
+ mul_size(num_child_flags, sizeof(sig_atomic_t)));
+ ShmemRequestStruct(.name = "PMSignalState",
+ .size = size,
+ .ptr = (void **) &PMSignalState,
+ );
}
-/*
- * PMSignalShmemInit - initialize during shared-memory creation
- */
-void
-PMSignalShmemInit(void)
+static void
+PMSignalShmemInit(void *arg)
{
- bool found;
-
- PMSignalState = (PMSignalData *)
- ShmemInitStruct("PMSignalState", PMSignalShmemSize(), &found);
-
- if (!found)
- {
- /* initialize all flags to zeroes */
- MemSet(unvolatize(PMSignalData *, PMSignalState), 0, PMSignalShmemSize());
- num_child_flags = MaxLivePostmasterChildren();
- PMSignalState->num_child_flags = num_child_flags;
- }
+ Assert(PMSignalState);
+ Assert(num_child_flags > 0);
+ PMSignalState->num_child_flags = num_child_flags;
}
/*
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/procsignal.h"
+#include "storage/subsystems.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/injection_point.h"
int pgprocnos[FLEXIBLE_ARRAY_MEMBER];
} ProcArrayStruct;
+static void ProcArrayShmemRequest(void *arg);
+static void ProcArrayShmemInit(void *arg);
+static void ProcArrayShmemAttach(void *arg);
+
+static ProcArrayStruct *procArray;
+
+const struct ShmemCallbacks ProcArrayShmemCallbacks = {
+ .request_fn = ProcArrayShmemRequest,
+ .init_fn = ProcArrayShmemInit,
+ .attach_fn = ProcArrayShmemAttach,
+};
+
/*
* State for the GlobalVisTest* family of functions. Those functions can
* e.g. be used to decide if a deleted row can be removed without violating
KAX_STARTUP_PROCESS_IDLE, /* startup process is about to sleep */
} KAXCompressReason;
-
-static ProcArrayStruct *procArray;
-
static PGPROC *allProcs;
/*
/*
* Bookkeeping for tracking emulated transactions in recovery
*/
+
static TransactionId *KnownAssignedXids;
+
static bool *KnownAssignedXidsValid;
+
static TransactionId latestObservedXid = InvalidTransactionId;
/*
static void GlobalVisUpdateApply(ComputeXidHorizonsResult *horizons);
/*
- * Report shared-memory space needed by ProcArrayShmemInit
+ * Register the shared PGPROC array during postmaster startup.
*/
-Size
-ProcArrayShmemSize(void)
+static void
+ProcArrayShmemRequest(void *arg)
{
- Size size;
-
- /* Size of the ProcArray structure itself */
#define PROCARRAY_MAXPROCS (MaxBackends + max_prepared_xacts)
- size = offsetof(ProcArrayStruct, pgprocnos);
- size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS));
-
/*
* During Hot Standby processing we have a data structure called
* KnownAssignedXids, created in shared memory. Local data structures are
if (EnableHotStandby)
{
- size = add_size(size,
- mul_size(sizeof(TransactionId),
- TOTAL_MAX_CACHED_SUBXIDS));
- size = add_size(size,
- mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS));
+ ShmemRequestStruct(.name = "KnownAssignedXids",
+ .size = mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS),
+ .ptr = (void **) &KnownAssignedXids,
+ );
+
+ ShmemRequestStruct(.name = "KnownAssignedXidsValid",
+ .size = mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
+ .ptr = (void **) &KnownAssignedXidsValid,
+ );
}
- return size;
+ /* Register the ProcArray shared structure */
+ ShmemRequestStruct(.name = "Proc Array",
+ .size = add_size(offsetof(ProcArrayStruct, pgprocnos),
+ mul_size(sizeof(int), PROCARRAY_MAXPROCS)),
+ .ptr = (void **) &procArray,
+ );
}
/*
* Initialize the shared PGPROC array during postmaster startup.
*/
-void
-ProcArrayShmemInit(void)
+static void
+ProcArrayShmemInit(void *arg)
{
- bool found;
-
- /* Create or attach to the ProcArray shared structure */
- procArray = (ProcArrayStruct *)
- ShmemInitStruct("Proc Array",
- add_size(offsetof(ProcArrayStruct, pgprocnos),
- mul_size(sizeof(int),
- PROCARRAY_MAXPROCS)),
- &found);
-
- if (!found)
- {
- /*
- * We're the first - initialize.
- */
- procArray->numProcs = 0;
- procArray->maxProcs = PROCARRAY_MAXPROCS;
- procArray->maxKnownAssignedXids = TOTAL_MAX_CACHED_SUBXIDS;
- procArray->numKnownAssignedXids = 0;
- procArray->tailKnownAssignedXids = 0;
- procArray->headKnownAssignedXids = 0;
- procArray->lastOverflowedXid = InvalidTransactionId;
- procArray->replication_slot_xmin = InvalidTransactionId;
- procArray->replication_slot_catalog_xmin = InvalidTransactionId;
- TransamVariables->xactCompletionCount = 1;
- }
+ procArray->numProcs = 0;
+ procArray->maxProcs = PROCARRAY_MAXPROCS;
+ procArray->maxKnownAssignedXids = TOTAL_MAX_CACHED_SUBXIDS;
+ procArray->numKnownAssignedXids = 0;
+ procArray->tailKnownAssignedXids = 0;
+ procArray->headKnownAssignedXids = 0;
+ procArray->lastOverflowedXid = InvalidTransactionId;
+ procArray->replication_slot_xmin = InvalidTransactionId;
+ procArray->replication_slot_catalog_xmin = InvalidTransactionId;
+ TransamVariables->xactCompletionCount = 1;
allProcs = ProcGlobal->allProcs;
+}
- /* Create or attach to the KnownAssignedXids arrays too, if needed */
- if (EnableHotStandby)
- {
- KnownAssignedXids = (TransactionId *)
- ShmemInitStruct("KnownAssignedXids",
- mul_size(sizeof(TransactionId),
- TOTAL_MAX_CACHED_SUBXIDS),
- &found);
- KnownAssignedXidsValid = (bool *)
- ShmemInitStruct("KnownAssignedXidsValid",
- mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
- &found);
- }
+static void
+ProcArrayShmemAttach(void *arg)
+{
+ allProcs = ProcGlobal->allProcs;
}
/*
#include "storage/shmem.h"
#include "storage/sinval.h"
#include "storage/smgr.h"
+#include "storage/subsystems.h"
#include "tcop/tcopprot.h"
#include "utils/memutils.h"
#include "utils/wait_event.h"
#define BARRIER_CLEAR_BIT(flags, type) \
((flags) &= ~(((uint32) 1) << (uint32) (type)))
+static void ProcSignalShmemRequest(void *arg);
+static void ProcSignalShmemInit(void *arg);
+
+const ShmemCallbacks ProcSignalShmemCallbacks = {
+ .request_fn = ProcSignalShmemRequest,
+ .init_fn = ProcSignalShmemInit,
+};
+
NON_EXEC_STATIC ProcSignalHeader *ProcSignal = NULL;
+
static ProcSignalSlot *MyProcSignalSlot = NULL;
static bool CheckProcSignal(ProcSignalReason reason);
static void ResetProcSignalBarrierBits(uint32 flags);
/*
- * ProcSignalShmemSize
- * Compute space needed for ProcSignal's shared memory
+ * ProcSignalShmemRequest
+ * Register ProcSignal's shared memory needs at postmaster startup
*/
-Size
-ProcSignalShmemSize(void)
+static void
+ProcSignalShmemRequest(void *arg)
{
Size size;
size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot));
size = add_size(size, offsetof(ProcSignalHeader, psh_slot));
- return size;
+
+ ShmemRequestStruct(.name = "ProcSignal",
+ .size = size,
+ .ptr = (void **) &ProcSignal,
+ );
}
-/*
- * ProcSignalShmemInit
- * Allocate and initialize ProcSignal's shared memory
- */
-void
-ProcSignalShmemInit(void)
+static void
+ProcSignalShmemInit(void *arg)
{
- Size size = ProcSignalShmemSize();
- bool found;
+ pg_atomic_init_u64(&ProcSignal->psh_barrierGeneration, 0);
- ProcSignal = (ProcSignalHeader *)
- ShmemInitStruct("ProcSignal", size, &found);
-
- /* If we're first, initialize. */
- if (!found)
+ for (int i = 0; i < NumProcSignalSlots; ++i)
{
- int i;
-
- pg_atomic_init_u64(&ProcSignal->psh_barrierGeneration, 0);
+ ProcSignalSlot *slot = &ProcSignal->psh_slot[i];
- for (i = 0; i < NumProcSignalSlots; ++i)
- {
- ProcSignalSlot *slot = &ProcSignal->psh_slot[i];
-
- SpinLockInit(&slot->pss_mutex);
- pg_atomic_init_u32(&slot->pss_pid, 0);
- slot->pss_cancel_key_len = 0;
- MemSet(slot->pss_signalFlags, 0, sizeof(slot->pss_signalFlags));
- pg_atomic_init_u64(&slot->pss_barrierGeneration, PG_UINT64_MAX);
- pg_atomic_init_u32(&slot->pss_barrierCheckMask, 0);
- ConditionVariableInit(&slot->pss_barrierCV);
- }
+ SpinLockInit(&slot->pss_mutex);
+ pg_atomic_init_u32(&slot->pss_pid, 0);
+ slot->pss_cancel_key_len = 0;
+ MemSet(slot->pss_signalFlags, 0, sizeof(slot->pss_signalFlags));
+ pg_atomic_init_u64(&slot->pss_barrierGeneration, PG_UINT64_MAX);
+ pg_atomic_init_u32(&slot->pss_barrierCheckMask, 0);
+ ConditionVariableInit(&slot->pss_barrierCV);
}
}
#include "storage/shmem.h"
#include "storage/sinvaladt.h"
#include "storage/spin.h"
+#include "storage/subsystems.h"
/*
* Conceptually, the shared cache invalidation messages are stored in an
static SISeg *shmInvalBuffer; /* pointer to the shared inval buffer */
+static void SharedInvalShmemRequest(void *arg);
+static void SharedInvalShmemInit(void *arg);
+
+const ShmemCallbacks SharedInvalShmemCallbacks = {
+ .request_fn = SharedInvalShmemRequest,
+ .init_fn = SharedInvalShmemInit,
+};
+
static LocalTransactionId nextLocalTransactionId;
/*
- * SharedInvalShmemSize --- return shared-memory space needed
+ * SharedInvalShmemRequest
+ * Register shared memory needs for the SI message buffer
*/
-Size
-SharedInvalShmemSize(void)
+static void
+SharedInvalShmemRequest(void *arg)
{
Size size;
size = add_size(size, mul_size(sizeof(ProcState), NumProcStateSlots)); /* procState */
size = add_size(size, mul_size(sizeof(int), NumProcStateSlots)); /* pgprocnos */
- return size;
+ ShmemRequestStruct(.name = "shmInvalBuffer",
+ .size = size,
+ .ptr = (void **) &shmInvalBuffer,
+ );
}
-/*
- * SharedInvalShmemInit
- * Create and initialize the SI message buffer
- */
-void
-SharedInvalShmemInit(void)
+static void
+SharedInvalShmemInit(void *arg)
{
int i;
- bool found;
-
- /* Allocate space in shared memory */
- shmInvalBuffer = (SISeg *)
- ShmemInitStruct("shmInvalBuffer", SharedInvalShmemSize(), &found);
- if (found)
- return;
- /* Clear message counters, save size of procState array, init spinlock */
+ /* Clear message counters, init spinlock */
shmInvalBuffer->minMsgNum = 0;
shmInvalBuffer->maxMsgNum = 0;
shmInvalBuffer->nextThreshold = CLEANUP_MIN;
#include "storage/procsignal.h"
#include "storage/spin.h"
#include "storage/standby.h"
+#include "storage/subsystems.h"
#include "utils/timeout.h"
#include "utils/timestamp.h"
#include "utils/wait_event.h"
/* Pointers to shared-memory structures */
PROC_HDR *ProcGlobal = NULL;
+static void *AllProcsShmemPtr;
+static void *FastPathLockArrayShmemPtr;
NON_EXEC_STATIC PGPROC *AuxiliaryProcs = NULL;
PGPROC *PreparedXactProcs = NULL;
+static void ProcGlobalShmemRequest(void *arg);
+static void ProcGlobalShmemInit(void *arg);
+
+const ShmemCallbacks ProcGlobalShmemCallbacks = {
+ .request_fn = ProcGlobalShmemRequest,
+ .init_fn = ProcGlobalShmemInit,
+};
+
+static uint32 TotalProcs;
+static size_t ProcGlobalAllProcsShmemSize;
+static size_t FastPathLockArrayShmemSize;
+
/* Is a deadlock check pending? */
static volatile sig_atomic_t got_deadlock_timeout;
/*
- * Report shared-memory space needed by PGPROC.
+ * Calculate shared-memory space needed by Fast-Path locks.
*/
static Size
-PGProcShmemSize(void)
+CalculateFastPathLockShmemSize(void)
{
Size size = 0;
- Size TotalProcs =
- add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts));
-
- size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC)));
- size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids)));
- size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates)));
- size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags)));
-
- return size;
-}
-
-/*
- * Report shared-memory space needed by Fast-Path locks.
- */
-static Size
-FastPathLockShmemSize(void)
-{
- Size size = 0;
- Size TotalProcs =
- add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts));
Size fpLockBitsSize,
fpRelIdSize;
}
/*
- * Report shared-memory space needed by InitProcGlobal.
- */
-Size
-ProcGlobalShmemSize(void)
-{
- Size size = 0;
-
- /* ProcGlobal */
- size = add_size(size, sizeof(PROC_HDR));
- size = add_size(size, sizeof(slock_t));
-
- size = add_size(size, PGSemaphoreShmemSize(ProcGlobalSemas()));
- size = add_size(size, PGProcShmemSize());
- size = add_size(size, FastPathLockShmemSize());
-
- return size;
-}
-
-/*
- * Report number of semaphores needed by InitProcGlobal.
+ * Report number of semaphores needed by ProcGlobalShmemInit.
*/
int
ProcGlobalSemas(void)
}
/*
- * InitProcGlobal -
+ * ProcGlobalShmemRequest
+ * Register shared memory needs.
+ *
+ * This is called during postmaster or standalone backend startup, and also
+ * during backend startup in EXEC_BACKEND mode.
+ */
+static void
+ProcGlobalShmemRequest(void *arg)
+{
+ Size size;
+
+ /*
+ * Reserve all the PGPROC structures we'll need. There are six separate
+ * consumers: (1) normal backends, (2) autovacuum workers and special
+ * workers, (3) background workers, (4) walsenders, (5) auxiliary
+ * processes, and (6) prepared transactions. (For largely-historical
+ * reasons, we combine autovacuum and special workers into one category
+ * with a single freelist.) Each PGPROC structure is dedicated to exactly
+ * one of these purposes, and they do not move between groups.
+ */
+ TotalProcs =
+ add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts));
+
+ size = 0;
+ size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC)));
+ size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids)));
+ size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates)));
+ size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags)));
+ ProcGlobalAllProcsShmemSize = size;
+ ShmemRequestStruct(.name = "PGPROC structures",
+ .size = ProcGlobalAllProcsShmemSize,
+ .ptr = &AllProcsShmemPtr,
+ );
+
+ if (!IsUnderPostmaster)
+ size = FastPathLockArrayShmemSize = CalculateFastPathLockShmemSize();
+ else
+ size = SHMEM_ATTACH_UNKNOWN_SIZE;
+ ShmemRequestStruct(.name = "Fast-Path Lock Array",
+ .size = size,
+ .ptr = &FastPathLockArrayShmemPtr,
+ );
+
+ /*
+ * ProcGlobal is registered here in .ptr as usual, but it needs to be
+ * propagated specially in EXEC_BACKEND mode, because ProcGlobal needs to
+ * be accessed early at backend startup, before ShmemAttachRequested() has
+ * been called.
+ */
+ ShmemRequestStruct(.name = "Proc Header",
+ .size = sizeof(PROC_HDR),
+ .ptr = (void **) &ProcGlobal,
+ );
+
+ /* Let the semaphore implementation register its shared memory needs */
+ PGSemaphoreShmemRequest(ProcGlobalSemas());
+}
+
+
+/*
+ * ProcGlobalShmemInit -
* Initialize the global process table during postmaster or standalone
* backend startup.
*
* Another reason for creating semaphores here is that the semaphore
* implementation typically requires us to create semaphores in the
* postmaster, not in backends.
- *
- * Note: this is NOT called by individual backends under a postmaster,
- * not even in the EXEC_BACKEND case. The ProcGlobal and AuxiliaryProcs
- * pointers must be propagated specially for EXEC_BACKEND operation.
*/
-void
-InitProcGlobal(void)
+static void
+ProcGlobalShmemInit(void *arg)
{
+ char *ptr;
+ size_t requestSize;
PGPROC *procs;
int i,
j;
- bool found;
- uint32 TotalProcs = MaxBackends + NUM_AUXILIARY_PROCS + max_prepared_xacts;
/* Used for setup of per-backend fast-path slots. */
char *fpPtr,
*fpEndPtr PG_USED_FOR_ASSERTS_ONLY;
Size fpLockBitsSize,
fpRelIdSize;
- Size requestSize;
- char *ptr;
- /* Create the ProcGlobal shared structure */
- ProcGlobal = (PROC_HDR *)
- ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found);
- Assert(!found);
-
- /*
- * Initialize the data structures.
- */
+ Assert(ProcGlobal);
ProcGlobal->spins_per_delay = DEFAULT_SPINS_PER_DELAY;
SpinLockInit(&ProcGlobal->freeProcsLock);
dlist_init(&ProcGlobal->freeProcs);
pg_atomic_init_u32(&ProcGlobal->procArrayGroupFirst, INVALID_PROC_NUMBER);
pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER);
- /*
- * Create and initialize all the PGPROC structures we'll need. There are
- * six separate consumers: (1) normal backends, (2) autovacuum workers and
- * special workers, (3) background workers, (4) walsenders, (5) auxiliary
- * processes, and (6) prepared transactions. (For largely-historical
- * reasons, we combine autovacuum and special workers into one category
- * with a single freelist.) Each PGPROC structure is dedicated to exactly
- * one of these purposes, and they do not move between groups.
- */
- requestSize = PGProcShmemSize();
-
- ptr = ShmemInitStruct("PGPROC structures",
- requestSize,
- &found);
-
+ ptr = AllProcsShmemPtr;
+ requestSize = ProcGlobalAllProcsShmemSize;
MemSet(ptr, 0, requestSize);
+ /* Carve out the allProcs array from the shared memory area */
procs = (PGPROC *) ptr;
ptr = ptr + TotalProcs * sizeof(PGPROC);
ProcGlobal->allProcCount = MaxBackends + NUM_AUXILIARY_PROCS;
/*
- * Allocate arrays mirroring PGPROC fields in a dense manner. See
+ * Carve out arrays mirroring PGPROC fields in a dense manner. See
* PROC_HDR.
*
* XXX: It might make sense to increase padding for these arrays, given
ProcGlobal->statusFlags = (uint8 *) ptr;
ptr = ptr + (TotalProcs * sizeof(*ProcGlobal->statusFlags));
- /* make sure wer didn't overflow */
+ /* make sure we didn't overflow */
Assert((ptr > (char *) procs) && (ptr <= (char *) procs + requestSize));
/*
- * Allocate arrays for fast-path locks. Those are variable-length, so
+ * Initialize arrays for fast-path locks. Those are variable-length, so
* can't be included in PGPROC directly. We allocate a separate piece of
* shared memory and then divide that between backends.
*/
fpLockBitsSize = MAXALIGN(FastPathLockGroupsPerBackend * sizeof(uint64));
fpRelIdSize = MAXALIGN(FastPathLockSlotsPerBackend() * sizeof(Oid));
- requestSize = FastPathLockShmemSize();
-
- fpPtr = ShmemInitStruct("Fast-Path Lock Array",
- requestSize,
- &found);
-
- MemSet(fpPtr, 0, requestSize);
+ fpPtr = FastPathLockArrayShmemPtr;
+ requestSize = FastPathLockArrayShmemSize;
+ memset(fpPtr, 0, requestSize);
/* For asserts checking we did not overflow. */
fpEndPtr = fpPtr + requestSize;
- /* Reserve space for semaphores. */
- PGReserveSemaphores(ProcGlobalSemas());
+ /* Initialize semaphores */
+ PGSemaphoreInit(ProcGlobalSemas());
for (i = 0; i < TotalProcs; i++)
{
/*
* Decide which list should supply our PGPROC. This logic must match the
- * way the freelists were constructed in InitProcGlobal().
+ * way the freelists were constructed in ProcGlobalShmemInit().
*/
if (AmAutoVacuumWorkerProcess() || AmSpecialWorkerProcess())
procgloballist = &ProcGlobal->autovacFreeProcs;
/*
* Initialize all fields of MyProc, except for those previously
- * initialized by InitProcGlobal.
+ * initialized by ProcGlobalShmemInit.
*/
dlist_node_init(&MyProc->freeProcsLink);
MyProc->waitStatus = PROC_WAIT_STATUS_OK;
* This is called by bgwriter and similar processes so that they will have a
* MyProc value that's real enough to let them wait for LWLocks. The PGPROC
* and sema that are assigned are one of the extra ones created during
- * InitProcGlobal.
+ * ProcGlobalShmemInit.
*
* Auxiliary processes are presently not expected to wait for real (lockmgr)
* locks, so we need not set up the deadlock checker. They are never added
/*
* Initialize all fields of MyProc, except for those previously
- * initialized by InitProcGlobal.
+ * initialized by ProcGlobalShmemInit.
*/
dlist_node_init(&MyProc->freeProcsLink);
MyProc->waitStatus = PROC_WAIT_STATUS_OK;
* under info->hcxt rather than under TopMemoryContext; the default
* behavior is only suitable for session-lifespan hash tables.
* Other flags bits are special-purpose and seldom used, except for those
- * associated with shared-memory hash tables, for which see ShmemInitHash().
+ * associated with shared-memory hash tables, for which see
+ * ShmemRequestHash().
*
* Fields in *info are read only when the associated flags bit is set.
* It is not necessary to initialize other fields of *info.
extern XLogRecPtr TransactionIdGetCommitLSN(TransactionId xid);
/* in transam/varsup.c */
-extern Size VarsupShmemSize(void);
-extern void VarsupShmemInit(void);
extern FullTransactionId GetNewTransactionId(bool isSubXact);
extern void AdvanceNextFullTransactionIdPastXid(TransactionId xid);
extern FullTransactionId ReadNextFullTransactionId(void);
extern void dsm_backend_shutdown(void);
extern void dsm_detach_all(void);
-extern size_t dsm_estimate_size(void);
-extern void dsm_shmem_init(void);
-
#ifdef EXEC_BACKEND
extern void dsm_set_control_handle(dsm_handle h);
#endif
extern dshash_table *GetNamedDSHash(const char *name,
const dshash_parameters *params,
bool *found);
-extern Size DSMRegistryShmemSize(void);
-extern void DSMRegistryShmemInit(void);
#endif /* DSM_REGISTRY_H */
#endif
-/* Report amount of shared memory needed */
-extern Size PGSemaphoreShmemSize(int maxSemas);
+/* Request shared memory needed for semaphores */
+extern void PGSemaphoreShmemRequest(int maxSemas);
/* Module initialization (called during postmaster start or shmem reinit) */
-extern void PGReserveSemaphores(int maxSemas);
+extern void PGSemaphoreInit(int maxSemas);
/* Allocate a PGSemaphore structure with initial count 1 */
extern PGSemaphore PGSemaphoreCreate(void);
/*
* prototypes for functions in pmsignal.c
*/
-extern Size PMSignalShmemSize(void);
-extern void PMSignalShmemInit(void);
extern void SendPostmasterSignal(PMSignalReason reason);
extern bool CheckPostmasterSignal(PMSignalReason reason);
extern void SetQuitSignalReason(QuitSignalReason reason);
* Function Prototypes
*/
extern int ProcGlobalSemas(void);
-extern Size ProcGlobalShmemSize(void);
-extern void InitProcGlobal(void);
extern void InitProcess(void);
extern void InitProcessPhase2(void);
extern void InitAuxiliaryProcess(void);
#include "utils/snapshot.h"
-extern Size ProcArrayShmemSize(void);
-extern void ProcArrayShmemInit(void);
extern void ProcArrayAdd(PGPROC *proc);
extern void ProcArrayRemove(PGPROC *proc, TransactionId latestXid);
/*
* prototypes for functions in procsignal.c
*/
-extern Size ProcSignalShmemSize(void);
-extern void ProcSignalShmemInit(void);
-
extern void ProcSignalInit(const uint8 *cancel_key, int cancel_key_len);
extern int SendProcSignal(pid_t pid, ProcSignalReason reason,
ProcNumber procNumber);
/*
* prototypes for functions in sinvaladt.c
*/
-extern Size SharedInvalShmemSize(void);
-extern void SharedInvalShmemInit(void);
extern void SharedInvalBackendInit(bool sendOnly);
extern void SIInsertDataEntries(const SharedInvalidationMessage *data, int n);
*/
PG_SHMEM_SUBSYSTEM(LWLockCallbacks)
-/* TODO: nothing else for now */
+PG_SHMEM_SUBSYSTEM(dsm_shmem_callbacks)
+PG_SHMEM_SUBSYSTEM(DSMRegistryShmemCallbacks)
+
+/* xlog, clog, and buffers */
+PG_SHMEM_SUBSYSTEM(VarsupShmemCallbacks)
+
+/* process table */
+PG_SHMEM_SUBSYSTEM(ProcGlobalShmemCallbacks)
+PG_SHMEM_SUBSYSTEM(ProcArrayShmemCallbacks)
+
+/* shared-inval messaging */
+PG_SHMEM_SUBSYSTEM(SharedInvalShmemCallbacks)
+
+/* interprocess signaling mechanisms */
+PG_SHMEM_SUBSYSTEM(PMSignalShmemCallbacks)
+PG_SHMEM_SUBSYSTEM(ProcSignalShmemCallbacks)