/* * Compute shmem space needed for LWLocks. */ Size LWLockShmemSize(void) { Size size; int numLocks = NumLWLocks(); /* Space for the LWLock array. */ size = mul_size(numLocks, sizeof(LWLockPadded)); /* Space for dynamic allocation counter, * plus room for alignment of LWLockArray. */ size = add_size(size, 2 * sizeof(int) + LWLOCK_PADDED_SIZE); #if LWLOCK_PART_SIZE > 1 /* Space for the LWLockPart array */ size = add_size(size, mul_size(LWLOCK_PARTS(numLocks), sizeof(LWLockPart))); /* Room for alignment of LWLockPartArray */ size = add_size(size, sizeof(LWLockPart)); #endif return size; }
/* * BufferShmemSize * * compute the size of shared memory for the buffer pool including * data pages, buffer descriptors, hash tables, etc. */ Size BufferShmemSize(void) { Size size = 0; /* size of buffer descriptors */ size = add_size(size, mul_size(NBuffers, sizeof(BufferDescPadded))); /* to allow aligning buffer descriptors */ size = add_size(size, PG_CACHE_LINE_SIZE); /* size of data pages */ size = add_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ size = add_size(size, StrategyShmemSize()); /* * It would be nice to include the I/O locks in the BufferDesc, but that * would increase the size of a BufferDesc to more than one cache line, * and benchmarking has shown that keeping every BufferDesc aligned on a * cache line boundary is important for performance. So, instead, the * array of I/O locks is allocated in a separate tranche. Because those * locks are not highly contentended, we lay out the array with minimal * padding. */ size = add_size(size, mul_size(NBuffers, sizeof(LWLockMinimallyPadded))); /* to allow aligning the above */ size = add_size(size, PG_CACHE_LINE_SIZE); /* size of checkpoint sort array in bufmgr.c */ size = add_size(size, mul_size(NBuffers, sizeof(CkptSortItem))); return size; }
/* * SInvalShmemSize --- return shared-memory space needed */ Size SInvalShmemSize(void) { Size size; size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); size = add_size(size, mul_size(sizeof(LocalTransactionId), MaxBackends)); return size; }
/* * NodeTablesShmemSize * Get the size of shared memory dedicated to node definitions */ Size NodeTablesShmemSize(void) { Size co_size; Size dn_size; co_size = mul_size(sizeof(NodeDefinition), MaxCoords); co_size = add_size(co_size, sizeof(int)); dn_size = mul_size(sizeof(NodeDefinition), MaxDataNodes); dn_size = add_size(dn_size, sizeof(int)); return add_size(co_size, dn_size); }
/* * Report shared-memory space needed by InitProcGlobal. */ Size ProcGlobalShmemSize(void) { Size size = 0; /* ProcGlobal */ size = add_size(size, sizeof(PROC_HDR)); /* AuxiliaryProcs */ size = add_size(size, mul_size(NUM_AUXILIARY_PROCS, sizeof(PGPROC))); /* MyProcs, including autovacuum */ size = add_size(size, mul_size(MaxBackends, sizeof(PGPROC))); return size; }
/* * Initialization of shared memory */ Size TwoPhaseShmemSize(void) { Size size; /* Need the fixed struct, the array of pointers, and the GTD structs */ size = offsetof(TwoPhaseStateData, prepXacts); size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransaction))); size = MAXALIGN(size); size = add_size(size, mul_size(max_prepared_xacts, sizeof(GlobalTransactionData))); return size; }
/* Attach the procArray segment (array of backends) or fail. */ static void attach_procarray() { bool found; /* already attached * * FIXME How could this happen? It's static and attached only once, right? * If this gets called twice, it's probably an error (worth a WARNING * at least, or maybe an ERROR). Maybe while unloading/reloading the * module, somehow? */ if (procArray != NULL) return; /* Create or attach to the ProcArray shared structure */ procArray = (ProcArrayStruct *) ShmemInitStruct("Proc Array", add_size(offsetof(ProcArrayStruct, procs), mul_size(sizeof(int), PROCARRAY_MAXPROCS)), &found); if (! found) elog(FATAL, "the Proc Array shared segment was not found"); }
/* * Estimate how much shared memory will be required to store a TOC and its * dependent data structures. */ Size shm_toc_estimate(shm_toc_estimator *e) { return add_size(offsetof(shm_toc, toc_entry), add_size(mul_size(e->number_of_keys, sizeof(shm_toc_entry)), e->space_for_chunks)); }
/* * BufferShmemSize * * compute the size of shared memory for the buffer pool including * data pages, buffer descriptors, hash tables, etc. */ Size BufferShmemSize(void) { Size size = 0; /* size of buffer descriptors */ size = add_size(size, mul_size(NBuffers, sizeof(BufferDesc))); /* size of data pages */ size = add_size(size, mul_size(NBuffers, BLCKSZ)); /* size of stuff controlled by freelist.c */ size = add_size(size, StrategyShmemSize()); return size; }
/* * btree_shm_size --- report amount of shared memory space needed */ size_t btree_shm_size(void) { size_t size; size = offsetof(bt_vac_info_s, vacuums[0]); size = add_size(size, mul_size(MAX_NR_BACKENDS, sizeof(bt_one_vac_info_s))); return size; }
/* * BTreeShmemSize --- report amount of shared memory space needed */ Size BTreeShmemSize(void) { Size size; size = offsetof(BTVacInfo, vacuums[0]); size = add_size(size, mul_size(MaxBackends, sizeof(BTOneVacInfo))); return size; }
/* Report shared-memory space needed by WalSndShmemInit */ Size WalSndShmemSize(void) { Size size = 0; size = offsetof(WalSndCtlData, walsnds); size = add_size(size, mul_size(max_wal_senders, sizeof(WalSnd))); return size; }
/* * BackendManagementShmemSize returns the size that should be allocated * on the shared memory for backend management. */ static size_t BackendManagementShmemSize(void) { Size size = 0; size = add_size(size, sizeof(BackendManagementShmemData)); size = add_size(size, mul_size(sizeof(BackendData), MaxBackends)); return size; }
/* * Report amount of shared memory needed for semaphores */ Size PGSemaphoreShmemSize(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)); #endif }
/* * PMSignalShmemSize * Compute space needed for pmsignal.c's shared memory */ Size PMSignalShmemSize(void) { Size size; size = offsetof(PMSignalData, PMChildFlags); size = add_size(size, mul_size(MaxLivePostmasterChildren(), sizeof(sig_atomic_t))); return size; }
/* Returns the size of the SessionState array */ Size SessionState_ShmemSize() { SessionStateArrayEntryCount = MaxBackends; Size size = offsetof(SessionStateArray, data); size = add_size(size, mul_size(sizeof(SessionState), SessionStateArrayEntryCount)); return size; }
static void ProtectMemoryPoolBuffers() { Size bufferBlocksTotalSize = mul_size((Size)NBuffers, (Size) BLCKSZ); if ( ShouldMemoryProtectBufferPool() && mprotect(BufferBlocks, bufferBlocksTotalSize, PROT_NONE )) { ereport(ERROR, (errmsg("Unable to set memory level to %d, error %d, allocation size %ud, ptr %ld", PROT_NONE, errno, (unsigned int) bufferBlocksTotalSize, (long int) BufferBlocks))); } }
/* * Estimate the amount of space required to serialize the current ComboCID * state. */ Size EstimateComboCIDStateSpace(void) { Size size; /* Add space required for saving usedComboCids */ size = sizeof(int); /* Add space required for saving the combocids key */ size = add_size(size, mul_size(sizeof(ComboCidKeyData), usedComboCids)); return size; }
/* * Report shared-memory space needed by CreateSharedSnapshot. */ Size SharedSnapshotShmemSize(void) { Size size; xipEntryCount = MaxBackends + max_prepared_xacts; slotSize = sizeof(SharedSnapshotSlot); slotSize += mul_size(sizeof(TransactionId), (xipEntryCount)); slotSize = MAXALIGN(slotSize); /* * We only really need max_prepared_xacts; but for safety we * multiply that by two (to account for slow de-allocation on * cleanup, for instance). */ slotCount = 2 * max_prepared_xacts; size = offsetof(SharedSnapshotStruct, xips); size = add_size(size, mul_size(slotSize, slotCount)); return MAXALIGN(size); }
/* ---------------------------------------------------------------- * ExecSortEstimate * * Estimate space required to propagate sort statistics. * ---------------------------------------------------------------- */ void ExecSortEstimate(SortState *node, ParallelContext *pcxt) { Size size; /* don't need this if not instrumenting or no workers */ if (!node->ss.ps.instrument || pcxt->nworkers == 0) return; size = mul_size(pcxt->nworkers, sizeof(TuplesortInstrumentation)); size = add_size(size, offsetof(SharedSortInfo, sinstrument)); shm_toc_estimate_chunk(&pcxt->estimator, size); shm_toc_estimate_keys(&pcxt->estimator, 1); }
/* * ApplyLauncherShmemSize * Compute space needed for replication launcher shared memory */ Size ApplyLauncherShmemSize(void) { Size size; /* * Need the fixed struct and the array of LogicalRepWorker. */ size = sizeof(LogicalRepCtxStruct); size = MAXALIGN(size); size = add_size(size, mul_size(max_logical_replication_workers, sizeof(LogicalRepWorker))); return size; }
/* * Compute shmem space needed for LWLocks. */ Size LWLockShmemSize(void) { Size size; int numLocks = NumLWLocks(); /* Space for the LWLock array. */ size = mul_size(numLocks, sizeof(LWLockPadded)); /* Space for dynamic allocation counter, plus room for alignment. */ size = add_size(size, 2 * sizeof(int) + LWLOCK_PADDED_SIZE); return size; }
/* * Report shared-memory space needed by ReplicationSlotShmemInit. */ Size ReplicationSlotsShmemSize(void) { Size size = 0; if (max_replication_slots == 0) return size; size = offsetof(ReplicationSlotCtlData, replication_slots); size = add_size(size, mul_size(max_replication_slots, sizeof(ReplicationSlot))); return size; }
/* * CheckpointerShmemSize * Compute space needed for checkpointer-related shared memory */ Size CheckpointerShmemSize(void) { Size size; /* * Currently, the size of the requests[] array is arbitrarily set equal to * NBuffers. This may prove too large or small ... */ size = offsetof(CheckpointerShmemStruct, requests); size = add_size(size, mul_size(NBuffers, sizeof(CheckpointerRequest))); return size; }
/* * Estimate the space needed for a hashtable containing the given number * of entries of given size. * NOTE: this is used to estimate the footprint of hashtables in shared * memory; therefore it does not count HTAB which is in local memory. * NB: assumes that all hash structure parameters have default values! */ Size hash_estimate_size(long num_entries, Size entrysize) { Size size; long nBuckets, nSegments, nDirEntries, nElementAllocs, elementSize, elementAllocCnt; /* estimate number of buckets wanted */ nBuckets = next_pow2_long((num_entries - 1) / DEF_FFACTOR + 1); /* # of segments needed for nBuckets */ nSegments = next_pow2_long((nBuckets - 1) / DEF_SEGSIZE + 1); /* directory entries */ nDirEntries = DEF_DIRSIZE; while (nDirEntries < nSegments) nDirEntries <<= 1; /* dir_alloc doubles dsize at each call */ /* fixed control info */ size = MAXALIGN(sizeof(HASHHDR)); /* but not HTAB, per above */ /* directory */ size = add_size(size, mul_size(nDirEntries, sizeof(HASHSEGMENT))); /* segments */ size = add_size(size, mul_size(nSegments, MAXALIGN(DEF_SEGSIZE * sizeof(HASHBUCKET)))); /* elements --- allocated in groups of choose_nelem_alloc() entries */ elementAllocCnt = choose_nelem_alloc(entrysize); nElementAllocs = (num_entries - 1) / elementAllocCnt + 1; elementSize = MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(entrysize); size = add_size(size, mul_size(nElementAllocs, mul_size(elementAllocCnt, elementSize))); return size; }
/* * Computes shared memory size needed for this cache */ Size Cache_SharedMemSize(uint32 nEntries, uint32 entryPayloadSize) { Size size = 0; /* Size of anchor hashtable. It has the same number of entries as the cache */ size = add_size(size, hash_estimate_size(nEntries, sizeof(CacheAnchor))); /* Size of cache shared control header */ size = add_size(size, MAXALIGN(sizeof(CacheHdr))); Size entrySize = add_size(CACHE_ENTRY_HEADER_SIZE, MAXALIGN(entryPayloadSize)); size = add_size(size, mul_size(nEntries, entrySize)); return size; }
/* * CreateSharedInvalidationState * Create and initialize the SI message buffer */ void CreateSharedInvalidationState(void) { Size size; int i; bool found; /* Allocate space in shared memory */ size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); shmInvalBuffer = (SISeg *) ShmemInitStruct("shmInvalBuffer", size, &found); if (found) return; /* Clear message counters, save size of procState array, init spinlock */ shmInvalBuffer->minMsgNum = 0; shmInvalBuffer->maxMsgNum = 0; shmInvalBuffer->nextThreshold = CLEANUP_MIN; shmInvalBuffer->lastBackend = 0; shmInvalBuffer->maxBackends = MaxBackends; SpinLockInit(&shmInvalBuffer->msgnumLock); /* The buffer[] array is initially all unused, so we need not fill it */ /* Mark all backends inactive, and initialize nextLXID */ for (i = 0; i < shmInvalBuffer->maxBackends; i++) { shmInvalBuffer->procState[i].procPid = 0; /* inactive */ shmInvalBuffer->procState[i].proc = NULL; shmInvalBuffer->procState[i].nextMsgNum = 0; /* meaningless */ shmInvalBuffer->procState[i].resetState = false; shmInvalBuffer->procState[i].signaled = false; shmInvalBuffer->procState[i].hasMessages = false; shmInvalBuffer->procState[i].nextLXID = InvalidLocalTransactionId; } }
/* * SIBufferInit * Create and initialize a new SI message buffer */ void SIBufferInit(void) { SISeg *segP; Size size; int i; bool found; /* Allocate space in shared memory */ size = offsetof(SISeg, procState); size = add_size(size, mul_size(sizeof(ProcState), MaxBackends)); shmInvalBuffer = segP = (SISeg *) ShmemInitStruct("shmInvalBuffer", size, &found); if (found) return; segP->nextLXID = ShmemAlloc(sizeof(LocalTransactionId) * MaxBackends); /* Clear message counters, save size of procState array */ segP->minMsgNum = 0; segP->maxMsgNum = 0; segP->lastBackend = 0; segP->maxBackends = MaxBackends; segP->freeBackends = MaxBackends; /* The buffer[] array is initially all unused, so we need not fill it */ /* Mark all backends inactive, and initialize nextLXID */ for (i = 0; i < segP->maxBackends; i++) { segP->procState[i].nextMsgNum = -1; /* inactive */ segP->procState[i].resetState = false; segP->nextLXID[i] = InvalidLocalTransactionId; } }
void ContQuerySchedulerShmemInit(void) { bool found; Size size = ContQuerySchedulerShmemSize(); ContQuerySchedulerShmem = ShmemInitStruct("ContQueryScheduler Data", size, &found); if (!found) { HASHCTL info; MemSet(ContQuerySchedulerShmem, 0, ContQuerySchedulerShmemSize()); info.keysize = sizeof(Oid); info.entrysize = MAXALIGN(add_size(sizeof(ContQueryProcGroup), mul_size(sizeof(ContQueryProc), TOTAL_SLOTS))); info.hash = oid_hash; ContQuerySchedulerShmem->proc_table = ShmemInitHash("ContQueryScheduler Proc Table", INIT_PROC_TABLE_SZ, MAX_PROC_TABLE_SZ, &info, HASH_ELEM | HASH_FUNCTION); update_tuning_params(); } }
/* * Report shared-memory space needed by InitProcGlobal. */ Size ProcGlobalShmemSize(void) { Size size = 0; /* ProcGlobal */ size = add_size(size, sizeof(PROC_HDR)); /* MyProcs, including autovacuum workers and launcher */ size = add_size(size, mul_size(MaxBackends, sizeof(PGPROC))); /* AuxiliaryProcs */ size = add_size(size, mul_size(NUM_AUXILIARY_PROCS, sizeof(PGPROC))); /* Prepared xacts */ size = add_size(size, mul_size(max_prepared_xacts, sizeof(PGPROC))); /* ProcStructLock */ size = add_size(size, sizeof(slock_t)); size = add_size(size, mul_size(MaxBackends, sizeof(PGXACT))); size = add_size(size, mul_size(NUM_AUXILIARY_PROCS, sizeof(PGXACT))); size = add_size(size, mul_size(max_prepared_xacts, sizeof(PGXACT))); return size; }