PostgreSQL Source Code git master
Loading...
Searching...
No Matches
shmem.c File Reference
#include "postgres.h"
#include "common/int.h"
#include "fmgr.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "port/pg_numa.h"
#include "storage/lwlock.h"
#include "storage/pg_shmem.h"
#include "storage/shmem.h"
#include "storage/spin.h"
#include "utils/builtins.h"
Include dependency graph for shmem.c:

Go to the source code of this file.

Macros

#define PG_GET_SHMEM_SIZES_COLS   4
 
#define PG_GET_SHMEM_NUMA_SIZES_COLS   3
 

Functions

static voidShmemAllocRaw (Size size, Size *allocated_size)
 
static voidShmemAllocUnlocked (Size size)
 
Datum pg_numa_available (PG_FUNCTION_ARGS)
 
void InitShmemAccess (PGShmemHeader *seghdr)
 
void InitShmemAllocation (void)
 
voidShmemAlloc (Size size)
 
voidShmemAllocNoError (Size size)
 
bool ShmemAddrIsValid (const void *addr)
 
void InitShmemIndex (void)
 
HTABShmemInitHash (const char *name, int64 init_size, int64 max_size, HASHCTL *infoP, int hash_flags)
 
voidShmemInitStruct (const char *name, Size size, bool *foundPtr)
 
Size add_size (Size s1, Size s2)
 
Size mul_size (Size s1, Size s2)
 
Datum pg_get_shmem_allocations (PG_FUNCTION_ARGS)
 
Datum pg_get_shmem_allocations_numa (PG_FUNCTION_ARGS)
 
Size pg_get_shmem_pagesize (void)
 

Variables

static PGShmemHeaderShmemSegHdr
 
static voidShmemBase
 
static voidShmemEnd
 
slock_tShmemLock
 
static HTABShmemIndex = NULL
 
static bool firstNumaTouch = true
 

Macro Definition Documentation

◆ PG_GET_SHMEM_NUMA_SIZES_COLS

#define PG_GET_SHMEM_NUMA_SIZES_COLS   3

◆ PG_GET_SHMEM_SIZES_COLS

#define PG_GET_SHMEM_SIZES_COLS   4

Function Documentation

◆ add_size()

Size add_size ( Size  s1,
Size  s2 
)

Definition at line 495 of file shmem.c.

496{
497 Size result;
498
499 if (pg_add_size_overflow(s1, s2, &result))
502 errmsg("requested shared memory size overflows size_t")));
503 return result;
504}
size_t Size
Definition c.h:619
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
static bool pg_add_size_overflow(size_t a, size_t b, size_t *result)
Definition int.h:608
static int fb(int x)
char * s1
char * s2

References ereport, errcode(), errmsg(), ERROR, fb(), pg_add_size_overflow(), s1, and s2.

Referenced by _brin_parallel_estimate_shared(), _bt_parallel_estimate_shared(), _gin_parallel_estimate_shared(), AioShmemSize(), ApplyLauncherShmemSize(), AsyncShmemInit(), AsyncShmemSize(), AutoVacuumShmemSize(), BackendStatusShmemSize(), BackgroundWorkerShmemSize(), btestimateparallelscan(), BTreeShmemSize(), BufferManagerShmemSize(), CalculateShmemSize(), CheckpointerShmemSize(), CreateAnonymousSegment(), estimate_variable_size(), EstimateClientConnectionInfoSpace(), EstimateComboCIDStateSpace(), EstimateGUCStateSpace(), EstimateLibraryStateSpace(), EstimateParamExecSpace(), EstimateParamListSpace(), EstimateSnapshotSpace(), EstimateTransactionStateSpace(), ExecAggEstimate(), ExecAppendEstimate(), ExecBitmapHeapEstimate(), ExecBitmapHeapInitializeDSM(), ExecHashEstimate(), ExecIncrementalSortEstimate(), ExecMemoizeEstimate(), ExecSortEstimate(), expand_planner_arrays(), FastPathLockShmemSize(), hash_estimate_size(), index_parallelscan_estimate(), index_parallelscan_initialize(), InitializeShmemGUCs(), InjectionPointShmemSize(), LockManagerShmemSize(), LWLockShmemSize(), MultiXactShmemSize(), pgaio_worker_shmem_size(), PgArchShmemSize(), PGProcShmemSize(), pgss_memsize(), PMSignalShmemSize(), PredicateLockShmemInit(), PredicateLockShmemSize(), ProcArrayShmemInit(), ProcArrayShmemSize(), ProcGlobalShmemSize(), ProcSignalShmemSize(), ReplicationOriginShmemSize(), ReplicationSlotsShmemSize(), RequestAddinShmemSpace(), SerializeTransactionState(), SharedInvalShmemSize(), shm_toc_estimate(), StatsShmemSize(), StrategyShmemSize(), table_parallelscan_estimate(), tuplesort_estimate_shared(), TwoPhaseShmemSize(), WaitEventCustomShmemSize(), WaitLSNShmemSize(), WalRcvShmemSize(), WalSndShmemSize(), and XLOGShmemSize().

◆ InitShmemAccess()

void InitShmemAccess ( PGShmemHeader seghdr)

Definition at line 104 of file shmem.c.

105{
108 ShmemEnd = (char *) ShmemBase + seghdr->totalsize;
109}
static void * ShmemBase
Definition shmem.c:86
static void * ShmemEnd
Definition shmem.c:88
static PGShmemHeader * ShmemSegHdr
Definition shmem.c:84
Size totalsize
Definition pg_shmem.h:34

References fb(), ShmemBase, ShmemEnd, ShmemSegHdr, and PGShmemHeader::totalsize.

Referenced by CreateSharedMemoryAndSemaphores().

◆ InitShmemAllocation()

void InitShmemAllocation ( void  )

Definition at line 117 of file shmem.c.

118{
120 char *aligned;
121
122 Assert(shmhdr != NULL);
123
124 /*
125 * Initialize the spinlock used by ShmemAlloc. We must use
126 * ShmemAllocUnlocked, since obviously ShmemAlloc can't be called yet.
127 */
129
131
132 /*
133 * Allocations after this point should go through ShmemAlloc, which
134 * expects to allocate everything on cache line boundaries. Make sure the
135 * first allocation begins on a cache line boundary.
136 */
137 aligned = (char *)
138 (CACHELINEALIGN((((char *) shmhdr) + shmhdr->freeoffset)));
139 shmhdr->freeoffset = aligned - (char *) shmhdr;
140
141 /* ShmemIndex can't be set up yet (need LWLocks first) */
142 shmhdr->index = NULL;
143 ShmemIndex = (HTAB *) NULL;
144}
#define CACHELINEALIGN(LEN)
Definition c.h:829
#define Assert(condition)
Definition c.h:873
slock_t * ShmemLock
Definition shmem.c:90
static HTAB * ShmemIndex
Definition shmem.c:93
static void * ShmemAllocUnlocked(Size size)
Definition shmem.c:240
#define SpinLockInit(lock)
Definition spin.h:57

References Assert, CACHELINEALIGN, fb(), ShmemAllocUnlocked(), ShmemIndex, ShmemLock, ShmemSegHdr, and SpinLockInit.

Referenced by CreateSharedMemoryAndSemaphores().

◆ InitShmemIndex()

void InitShmemIndex ( void  )

Definition at line 285 of file shmem.c.

286{
287 HASHCTL info;
288
289 /*
290 * Create the shared memory shmem index.
291 *
292 * Since ShmemInitHash calls ShmemInitStruct, which expects the ShmemIndex
293 * hashtable to exist already, we have a bit of a circularity problem in
294 * initializing the ShmemIndex itself. The special "ShmemIndex" hash
295 * table name will tell ShmemInitStruct to fake it.
296 */
298 info.entrysize = sizeof(ShmemIndexEnt);
299
300 ShmemIndex = ShmemInitHash("ShmemIndex",
302 &info,
304}
#define HASH_STRINGS
Definition hsearch.h:96
#define HASH_ELEM
Definition hsearch.h:95
HTAB * ShmemInitHash(const char *name, int64 init_size, int64 max_size, HASHCTL *infoP, int hash_flags)
Definition shmem.c:334
#define SHMEM_INDEX_SIZE
Definition shmem.h:53
#define SHMEM_INDEX_KEYSIZE
Definition shmem.h:51
Size keysize
Definition hsearch.h:75
Size entrysize
Definition hsearch.h:76

References HASHCTL::entrysize, HASH_ELEM, HASH_STRINGS, HASHCTL::keysize, SHMEM_INDEX_KEYSIZE, SHMEM_INDEX_SIZE, ShmemIndex, and ShmemInitHash().

Referenced by CreateOrAttachShmemStructs().

◆ mul_size()

Size mul_size ( Size  s1,
Size  s2 
)

Definition at line 510 of file shmem.c.

511{
512 Size result;
513
514 if (pg_mul_size_overflow(s1, s2, &result))
517 errmsg("requested shared memory size overflows size_t")));
518 return result;
519}
static bool pg_mul_size_overflow(size_t a, size_t b, size_t *result)
Definition int.h:642

References ereport, errcode(), errmsg(), ERROR, fb(), pg_mul_size_overflow(), s1, and s2.

Referenced by _brin_begin_parallel(), _bt_begin_parallel(), _gin_begin_parallel(), AioBackendShmemSize(), AioHandleDataShmemSize(), AioHandleIOVShmemSize(), AioHandleShmemSize(), ApplyLauncherShmemSize(), AsyncShmemInit(), AsyncShmemSize(), AutoVacuumShmemSize(), BackendStatusShmemInit(), BackendStatusShmemSize(), BackgroundWorkerShmemSize(), BTreeShmemSize(), BufferManagerShmemSize(), CheckpointerShmemSize(), EstimateComboCIDStateSpace(), EstimatePendingSyncsSpace(), EstimateReindexStateSpace(), EstimateSnapshotSpace(), EstimateTransactionStateSpace(), ExecAggEstimate(), ExecBitmapHeapEstimate(), ExecBitmapHeapInitializeDSM(), ExecHashEstimate(), ExecIncrementalSortEstimate(), ExecInitParallelPlan(), ExecMemoizeEstimate(), ExecParallelRetrieveInstrumentation(), ExecParallelRetrieveJitInstrumentation(), ExecParallelSetupTupleQueues(), ExecSortEstimate(), FastPathLockShmemSize(), hash_estimate_size(), InitializeParallelDSM(), LWLockShmemSize(), parallel_vacuum_init(), PGProcShmemSize(), PGSemaphoreShmemSize(), PMSignalShmemSize(), PredicateLockShmemInit(), PredicateLockShmemSize(), ProcArrayShmemInit(), ProcArrayShmemSize(), ProcSignalShmemSize(), ReplicationOriginShmemSize(), ReplicationSlotsShmemSize(), SharedInvalShmemSize(), shm_toc_estimate(), tuplesort_estimate_shared(), TwoPhaseShmemSize(), WaitLSNShmemSize(), WalSndShmemSize(), and XLOGShmemSize().

◆ pg_get_shmem_allocations()

Datum pg_get_shmem_allocations ( PG_FUNCTION_ARGS  )

Definition at line 523 of file shmem.c.

524{
525#define PG_GET_SHMEM_SIZES_COLS 4
526 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
531 bool nulls[PG_GET_SHMEM_SIZES_COLS];
532
533 InitMaterializedSRF(fcinfo, 0);
534
536
538
539 /* output all allocated entries */
540 memset(nulls, 0, sizeof(nulls));
541 while ((ent = (ShmemIndexEnt *) hash_seq_search(&hstat)) != NULL)
542 {
543 values[0] = CStringGetTextDatum(ent->key);
544 values[1] = Int64GetDatum((char *) ent->location - (char *) ShmemSegHdr);
545 values[2] = Int64GetDatum(ent->size);
546 values[3] = Int64GetDatum(ent->allocated_size);
547 named_allocated += ent->allocated_size;
548
549 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
550 values, nulls);
551 }
552
553 /* output shared memory allocated but not counted via the shmem index */
554 values[0] = CStringGetTextDatum("<anonymous>");
555 nulls[1] = true;
557 values[3] = values[2];
558 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
559
560 /* output as-of-yet unused shared memory */
561 nulls[0] = true;
563 nulls[1] = false;
565 values[3] = values[2];
566 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
567
569
570 return (Datum) 0;
571}
static Datum values[MAXATTR]
Definition bootstrap.c:155
#define CStringGetTextDatum(s)
Definition builtins.h:97
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition dynahash.c:1415
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition dynahash.c:1380
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition funcapi.c:76
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1176
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1793
@ LW_SHARED
Definition lwlock.h:113
static Datum Int64GetDatum(int64 X)
Definition postgres.h:423
uint64_t Datum
Definition postgres.h:70
#define PG_GET_SHMEM_SIZES_COLS
Size freeoffset
Definition pg_shmem.h:35
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition tuplestore.c:784

References CStringGetTextDatum, fb(), PGShmemHeader::freeoffset, hash_seq_init(), hash_seq_search(), InitMaterializedSRF(), Int64GetDatum(), LW_SHARED, LWLockAcquire(), LWLockRelease(), PG_GET_SHMEM_SIZES_COLS, ShmemIndex, ShmemSegHdr, PGShmemHeader::totalsize, tuplestore_putvalues(), and values.

◆ pg_get_shmem_allocations_numa()

Datum pg_get_shmem_allocations_numa ( PG_FUNCTION_ARGS  )

Definition at line 580 of file shmem.c.

581{
582#define PG_GET_SHMEM_NUMA_SIZES_COLS 3
583 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
589 void **page_ptrs;
590 int *pages_status;
593 max_nodes;
594 Size *nodes;
595
596 if (pg_numa_init() == -1)
597 elog(ERROR, "libnuma initialization failed or NUMA is not supported on this platform");
598
599 InitMaterializedSRF(fcinfo, 0);
600
603
604 /*
605 * Shared memory allocations can vary in size and may not align with OS
606 * memory page boundaries, while NUMA queries work on pages.
607 *
608 * To correctly map each allocation to NUMA nodes, we need to: 1.
609 * Determine the OS memory page size. 2. Align each allocation's start/end
610 * addresses to page boundaries. 3. Query NUMA node information for all
611 * pages spanning the allocation.
612 */
614
615 /*
616 * Allocate memory for page pointers and status based on total shared
617 * memory size. This simplified approach allocates enough space for all
618 * pages in shared memory rather than calculating the exact requirements
619 * for each segment.
620 *
621 * Add 1, because we don't know how exactly the segments align to OS
622 * pages, so the allocation might use one more memory page. In practice
623 * this is not very likely, and moreover we have more entries, each of
624 * them using only fraction of the total pages.
625 */
629
630 if (firstNumaTouch)
631 elog(DEBUG1, "NUMA: page-faulting shared memory segments for proper NUMA readouts");
632
634
636
637 /* output all allocated entries */
638 while ((ent = (ShmemIndexEnt *) hash_seq_search(&hstat)) != NULL)
639 {
640 int i;
641 char *startptr,
642 *endptr;
643 Size total_len;
644
645 /*
646 * Calculate the range of OS pages used by this segment. The segment
647 * may start / end half-way through a page, we want to count these
648 * pages too. So we align the start/end pointers down/up, and then
649 * calculate the number of pages from that.
650 */
651 startptr = (char *) TYPEALIGN_DOWN(os_page_size, ent->location);
652 endptr = (char *) TYPEALIGN(os_page_size,
653 (char *) ent->location + ent->allocated_size);
654 total_len = (endptr - startptr);
655
656 shm_ent_page_count = total_len / os_page_size;
657
658 /*
659 * If we ever get 0xff (-1) back from kernel inquiry, then we probably
660 * have a bug in mapping buffers to OS pages.
661 */
662 memset(pages_status, 0xff, sizeof(int) * shm_ent_page_count);
663
664 /*
665 * Setup page_ptrs[] with pointers to all OS pages for this segment,
666 * and get the NUMA status using pg_numa_query_pages.
667 *
668 * In order to get reliable results we also need to touch memory
669 * pages, so that inquiry about NUMA memory node doesn't return -2
670 * (ENOENT, which indicates unmapped/unallocated pages).
671 */
672 for (i = 0; i < shm_ent_page_count; i++)
673 {
674 page_ptrs[i] = startptr + (i * os_page_size);
675
676 if (firstNumaTouch)
678
680 }
681
683 elog(ERROR, "failed NUMA pages inquiry status: %m");
684
685 /* Count number of NUMA nodes used for this shared memory entry */
686 memset(nodes, 0, sizeof(Size) * (max_nodes + 2));
687
688 for (i = 0; i < shm_ent_page_count; i++)
689 {
690 int s = pages_status[i];
691
692 /* Ensure we are adding only valid index to the array */
693 if (s >= 0 && s <= max_nodes)
694 {
695 /* valid NUMA node */
696 nodes[s]++;
697 continue;
698 }
699 else if (s == -2)
700 {
701 /* -2 means ENOENT (e.g. page was moved to swap) */
702 nodes[max_nodes + 1]++;
703 continue;
704 }
705
706 elog(ERROR, "invalid NUMA node id outside of allowed range "
707 "[0, " UINT64_FORMAT "]: %d", max_nodes, s);
708 }
709
710 /* no NULLs for regular nodes */
711 memset(nulls, 0, sizeof(nulls));
712
713 /*
714 * Add one entry for each NUMA node, including those without allocated
715 * memory for this segment.
716 */
717 for (i = 0; i <= max_nodes; i++)
718 {
719 values[0] = CStringGetTextDatum(ent->key);
720 values[1] = Int32GetDatum(i);
722
723 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
724 values, nulls);
725 }
726
727 /* The last entry is used for pages without a NUMA node. */
728 nulls[1] = true;
729 values[0] = CStringGetTextDatum(ent->key);
731
732 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
733 values, nulls);
734 }
735
737 firstNumaTouch = false;
738
739 return (Datum) 0;
740}
#define TYPEALIGN(ALIGNVAL, LEN)
Definition c.h:819
#define UINT64_FORMAT
Definition c.h:565
uint64_t uint64
Definition c.h:547
#define TYPEALIGN_DOWN(ALIGNVAL, LEN)
Definition c.h:831
#define DEBUG1
Definition elog.h:30
#define elog(elevel,...)
Definition elog.h:226
#define palloc_array(type, count)
Definition fe_memutils.h:76
#define palloc0_array(type, count)
Definition fe_memutils.h:77
int i
Definition isn.c:77
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
PGDLLIMPORT int pg_numa_get_max_node(void)
Definition pg_numa.c:136
#define pg_numa_touch_mem_if_required(ptr)
Definition pg_numa.h:37
PGDLLIMPORT int pg_numa_query_pages(int pid, unsigned long count, void **pages, int *status)
Definition pg_numa.c:130
PGDLLIMPORT int pg_numa_init(void)
Definition pg_numa.c:123
static Datum Int32GetDatum(int32 X)
Definition postgres.h:222
Size pg_get_shmem_pagesize(void)
Definition shmem.c:751
#define PG_GET_SHMEM_NUMA_SIZES_COLS
static bool firstNumaTouch
Definition shmem.c:96

References CHECK_FOR_INTERRUPTS, CStringGetTextDatum, DEBUG1, elog, ERROR, fb(), firstNumaTouch, hash_seq_init(), hash_seq_search(), i, InitMaterializedSRF(), Int32GetDatum(), Int64GetDatum(), LW_SHARED, LWLockAcquire(), LWLockRelease(), palloc0_array, palloc_array, PG_GET_SHMEM_NUMA_SIZES_COLS, pg_get_shmem_pagesize(), pg_numa_get_max_node(), pg_numa_init(), pg_numa_query_pages(), pg_numa_touch_mem_if_required, ShmemIndex, ShmemSegHdr, PGShmemHeader::totalsize, tuplestore_putvalues(), TYPEALIGN, TYPEALIGN_DOWN, UINT64_FORMAT, and values.

◆ pg_get_shmem_pagesize()

Size pg_get_shmem_pagesize ( void  )

Definition at line 751 of file shmem.c.

752{
754#ifdef WIN32
756
758 os_page_size = sysinfo.dwPageSize;
759#else
761#endif
762
765
768
769 return os_page_size;
770}
bool IsUnderPostmaster
Definition globals.c:120
int huge_pages_status
Definition guc_tables.c:582
@ HUGE_PAGES_UNKNOWN
Definition pg_shmem.h:56
@ HUGE_PAGES_ON
Definition pg_shmem.h:54
void GetHugePageSize(Size *hugepagesize, int *mmap_flags)
Definition sysv_shmem.c:480

References Assert, fb(), GetHugePageSize(), HUGE_PAGES_ON, huge_pages_status, HUGE_PAGES_UNKNOWN, and IsUnderPostmaster.

Referenced by pg_buffercache_os_pages_internal(), and pg_get_shmem_allocations_numa().

◆ pg_numa_available()

Datum pg_numa_available ( PG_FUNCTION_ARGS  )

Definition at line 773 of file shmem.c.

774{
776}
#define PG_RETURN_BOOL(x)
Definition fmgr.h:360

References pg_numa_init(), and PG_RETURN_BOOL.

◆ ShmemAddrIsValid()

bool ShmemAddrIsValid ( const void addr)

Definition at line 276 of file shmem.c.

277{
278 return (addr >= ShmemBase) && (addr < ShmemEnd);
279}

References ShmemBase, and ShmemEnd.

Referenced by ReleasePredXact(), and ShmemInitStruct().

◆ ShmemAlloc()

void * ShmemAlloc ( Size  size)

Definition at line 154 of file shmem.c.

155{
156 void *newSpace;
157 Size allocated_size;
158
159 newSpace = ShmemAllocRaw(size, &allocated_size);
160 if (!newSpace)
163 errmsg("out of shared memory (%zu bytes requested)",
164 size)));
165 return newSpace;
166}
static void * ShmemAllocRaw(Size size, Size *allocated_size)
Definition shmem.c:188

References ereport, errcode(), errmsg(), ERROR, fb(), and ShmemAllocRaw().

Referenced by CreateLWLocks(), PGReserveSemaphores(), ShmemInitStruct(), and StatsShmemInit().

◆ ShmemAllocNoError()

void * ShmemAllocNoError ( Size  size)

Definition at line 174 of file shmem.c.

175{
176 Size allocated_size;
177
178 return ShmemAllocRaw(size, &allocated_size);
179}

References ShmemAllocRaw().

Referenced by ShmemInitHash().

◆ ShmemAllocRaw()

static void * ShmemAllocRaw ( Size  size,
Size allocated_size 
)
static

Definition at line 188 of file shmem.c.

189{
192 void *newSpace;
193
194 /*
195 * Ensure all space is adequately aligned. We used to only MAXALIGN this
196 * space but experience has proved that on modern systems that is not good
197 * enough. Many parts of the system are very sensitive to critical data
198 * structures getting split across cache line boundaries. To avoid that,
199 * attempt to align the beginning of the allocation to a cache line
200 * boundary. The calling code will still need to be careful about how it
201 * uses the allocated space - e.g. by padding each element in an array of
202 * structures out to a power-of-two size - but without this, even that
203 * won't be sufficient.
204 */
205 size = CACHELINEALIGN(size);
206 *allocated_size = size;
207
209
211
213
214 newFree = newStart + size;
215 if (newFree <= ShmemSegHdr->totalsize)
216 {
217 newSpace = (char *) ShmemBase + newStart;
219 }
220 else
221 newSpace = NULL;
222
224
225 /* note this assert is okay with newSpace == NULL */
227
228 return newSpace;
229}
#define SpinLockRelease(lock)
Definition spin.h:61
#define SpinLockAcquire(lock)
Definition spin.h:59

References Assert, CACHELINEALIGN, fb(), PGShmemHeader::freeoffset, ShmemBase, ShmemLock, ShmemSegHdr, SpinLockAcquire, and SpinLockRelease.

Referenced by ShmemAlloc(), ShmemAllocNoError(), and ShmemInitStruct().

◆ ShmemAllocUnlocked()

static void * ShmemAllocUnlocked ( Size  size)
static

Definition at line 240 of file shmem.c.

241{
244 void *newSpace;
245
246 /*
247 * Ensure allocated space is adequately aligned.
248 */
249 size = MAXALIGN(size);
250
252
254
255 newFree = newStart + size;
259 errmsg("out of shared memory (%zu bytes requested)",
260 size)));
262
263 newSpace = (char *) ShmemBase + newStart;
264
265 Assert(newSpace == (void *) MAXALIGN(newSpace));
266
267 return newSpace;
268}
#define MAXALIGN(LEN)
Definition c.h:826

References Assert, ereport, errcode(), errmsg(), ERROR, fb(), PGShmemHeader::freeoffset, MAXALIGN, ShmemBase, ShmemSegHdr, and PGShmemHeader::totalsize.

Referenced by InitShmemAllocation().

◆ ShmemInitHash()

HTAB * ShmemInitHash ( const char name,
int64  init_size,
int64  max_size,
HASHCTL infoP,
int  hash_flags 
)

Definition at line 334 of file shmem.c.

339{
340 bool found;
341 void *location;
342
343 /*
344 * Hash tables allocated in shared memory have a fixed directory; it can't
345 * grow or other backends wouldn't be able to find it. So, make sure we
346 * make it big enough to start with.
347 *
348 * The shared memory allocator must be specified too.
349 */
350 infoP->dsize = infoP->max_dsize = hash_select_dirsize(max_size);
351 infoP->alloc = ShmemAllocNoError;
353
354 /* look it up in the shmem index */
355 location = ShmemInitStruct(name,
357 &found);
358
359 /*
360 * if it already exists, attach to it rather than allocate and initialize
361 * new space
362 */
363 if (found)
365
366 /* Pass location of hashtable header to hash_create */
367 infoP->hctl = (HASHHDR *) location;
368
370}
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition dynahash.c:358
Size hash_get_shared_size(HASHCTL *info, int flags)
Definition dynahash.c:854
int64 hash_select_dirsize(int64 num_entries)
Definition dynahash.c:830
#define HASH_ALLOC
Definition hsearch.h:101
#define HASH_DIRSIZE
Definition hsearch.h:94
#define HASH_ATTACH
Definition hsearch.h:104
#define HASH_SHARED_MEM
Definition hsearch.h:103
void * ShmemAllocNoError(Size size)
Definition shmem.c:174
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition shmem.c:389
const char * name

References fb(), HASH_ALLOC, HASH_ATTACH, hash_create(), HASH_DIRSIZE, hash_get_shared_size(), hash_select_dirsize(), HASH_SHARED_MEM, name, ShmemAllocNoError(), and ShmemInitStruct().

Referenced by InitBufTable(), InitShmemIndex(), LockManagerShmemInit(), pgss_shmem_startup(), PredicateLockShmemInit(), and WaitEventCustomShmemInit().

◆ ShmemInitStruct()

void * ShmemInitStruct ( const char name,
Size  size,
bool foundPtr 
)

Definition at line 389 of file shmem.c.

390{
391 ShmemIndexEnt *result;
392 void *structPtr;
393
395
396 if (!ShmemIndex)
397 {
399
400 /* Must be trying to create/attach to ShmemIndex itself */
401 Assert(strcmp(name, "ShmemIndex") == 0);
402
404 {
405 /* Must be initializing a (non-standalone) backend */
406 Assert(shmemseghdr->index != NULL);
407 structPtr = shmemseghdr->index;
408 *foundPtr = true;
409 }
410 else
411 {
412 /*
413 * If the shmem index doesn't exist, we are bootstrapping: we must
414 * be trying to init the shmem index itself.
415 *
416 * Notice that the ShmemIndexLock is released before the shmem
417 * index has been initialized. This should be OK because no other
418 * process can be accessing shared memory yet.
419 */
420 Assert(shmemseghdr->index == NULL);
421 structPtr = ShmemAlloc(size);
422 shmemseghdr->index = structPtr;
423 *foundPtr = false;
424 }
426 return structPtr;
427 }
428
429 /* look it up in the shmem index */
430 result = (ShmemIndexEnt *)
432
433 if (!result)
434 {
438 errmsg("could not create ShmemIndex entry for data structure \"%s\"",
439 name)));
440 }
441
442 if (*foundPtr)
443 {
444 /*
445 * Structure is in the shmem index so someone else has allocated it
446 * already. The size better be the same as the size we are trying to
447 * initialize to, or there is a name conflict (or worse).
448 */
449 if (result->size != size)
450 {
453 (errmsg("ShmemIndex entry size is wrong for data structure"
454 " \"%s\": expected %zu, actual %zu",
455 name, size, result->size)));
456 }
457 structPtr = result->location;
458 }
459 else
460 {
461 Size allocated_size;
462
463 /* It isn't in the table yet. allocate and initialize it */
464 structPtr = ShmemAllocRaw(size, &allocated_size);
465 if (structPtr == NULL)
466 {
467 /* out of memory; remove the failed ShmemIndex entry */
472 errmsg("not enough shared memory for data structure"
473 " \"%s\" (%zu bytes requested)",
474 name, size)));
475 }
476 result->size = size;
477 result->allocated_size = allocated_size;
478 result->location = structPtr;
479 }
480
482
484
486
487 return structPtr;
488}
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:952
@ HASH_REMOVE
Definition hsearch.h:115
@ HASH_ENTER_NULL
Definition hsearch.h:116
@ LW_EXCLUSIVE
Definition lwlock.h:112
bool ShmemAddrIsValid(const void *addr)
Definition shmem.c:276
void * ShmemAlloc(Size size)
Definition shmem.c:154
void * location
Definition shmem.h:59
Size size
Definition shmem.h:60
Size allocated_size
Definition shmem.h:61

References ShmemIndexEnt::allocated_size, Assert, CACHELINEALIGN, ereport, errcode(), errmsg(), ERROR, fb(), HASH_ENTER_NULL, HASH_REMOVE, hash_search(), IsUnderPostmaster, ShmemIndexEnt::location, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), name, ShmemAddrIsValid(), ShmemAlloc(), ShmemAllocRaw(), ShmemIndex, ShmemSegHdr, and ShmemIndexEnt::size.

Referenced by AioShmemInit(), ApplyLauncherShmemInit(), AsyncShmemInit(), AutoVacuumShmemInit(), BackendStatusShmemInit(), BackgroundWorkerShmemInit(), BTreeShmemInit(), BufferManagerShmemInit(), CheckpointerShmemInit(), CommitTsShmemInit(), dsm_shmem_init(), DSMRegistryShmemInit(), InitProcGlobal(), injection_shmem_startup(), InjectionPointShmemInit(), LockManagerShmemInit(), LogicalDecodingCtlShmemInit(), MultiXactShmemInit(), pgaio_worker_shmem_init(), PgArchShmemInit(), pgss_shmem_startup(), PMSignalShmemInit(), PredicateLockShmemInit(), ProcArrayShmemInit(), ProcSignalShmemInit(), ReplicationOriginShmemInit(), ReplicationSlotsShmemInit(), SerialInit(), SharedInvalShmemInit(), ShmemInitHash(), SimpleLruInit(), SlotSyncShmemInit(), StatsShmemInit(), StrategyInitialize(), SyncScanShmemInit(), test_aio_shmem_startup(), TwoPhaseShmemInit(), VarsupShmemInit(), WaitEventCustomShmemInit(), WaitLSNShmemInit(), WalRcvShmemInit(), WalSndShmemInit(), WalSummarizerShmemInit(), XLogPrefetchShmemInit(), XLogRecoveryShmemInit(), and XLOGShmemInit().

Variable Documentation

◆ firstNumaTouch

bool firstNumaTouch = true
static

Definition at line 96 of file shmem.c.

Referenced by pg_get_shmem_allocations_numa().

◆ ShmemBase

void* ShmemBase
static

Definition at line 86 of file shmem.c.

Referenced by InitShmemAccess(), ShmemAddrIsValid(), ShmemAllocRaw(), and ShmemAllocUnlocked().

◆ ShmemEnd

void* ShmemEnd
static

Definition at line 88 of file shmem.c.

Referenced by InitShmemAccess(), and ShmemAddrIsValid().

◆ ShmemIndex

◆ ShmemLock

slock_t* ShmemLock

Definition at line 90 of file shmem.c.

Referenced by GetLWTrancheName(), InitShmemAllocation(), LWLockNewTrancheId(), and ShmemAllocRaw().

◆ ShmemSegHdr