PostgreSQL Source Code  git master
shmem.h File Reference
#include "storage/spin.h"
#include "utils/hsearch.h"
Include dependency graph for shmem.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ShmemIndexEnt
 

Macros

#define SHMEM_INDEX_KEYSIZE   (48)
 
#define SHMEM_INDEX_SIZE   (64)
 

Functions

void InitShmemAccess (void *seghdr)
 
void InitShmemAllocation (void)
 
void * ShmemAlloc (Size size)
 
void * ShmemAllocNoError (Size size)
 
void * ShmemAllocUnlocked (Size size)
 
bool ShmemAddrIsValid (const void *addr)
 
void InitShmemIndex (void)
 
HTABShmemInitHash (const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
 
void * ShmemInitStruct (const char *name, Size size, bool *foundPtr)
 
Size add_size (Size s1, Size s2)
 
Size mul_size (Size s1, Size s2)
 
void RequestAddinShmemSpace (Size size)
 

Variables

PGDLLIMPORT slock_t * ShmemLock
 

Macro Definition Documentation

◆ SHMEM_INDEX_KEYSIZE

#define SHMEM_INDEX_KEYSIZE   (48)

Definition at line 48 of file shmem.h.

◆ SHMEM_INDEX_SIZE

#define SHMEM_INDEX_SIZE   (64)

Definition at line 50 of file shmem.h.

Function Documentation

◆ add_size()

Size add_size ( Size  s1,
Size  s2 
)

Definition at line 493 of file shmem.c.

494 {
495  Size result;
496 
497  result = s1 + s2;
498  /* We are assuming Size is an unsigned type here... */
499  if (result < s1 || result < s2)
500  ereport(ERROR,
501  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
502  errmsg("requested shared memory size overflows size_t")));
503  return result;
504 }
size_t Size
Definition: c.h:608
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
char * s1
char * s2

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

Referenced by _brin_parallel_estimate_shared(), _bt_parallel_estimate_shared(), ApplyLauncherShmemSize(), AsyncShmemInit(), AsyncShmemSize(), AutoVacuumShmemSize(), BackendStatusShmemSize(), BackgroundWorkerShmemSize(), BTreeShmemSize(), BufferManagerShmemSize(), CalculateShmemSize(), CheckpointerShmemSize(), estimate_variable_size(), EstimateClientConnectionInfoSpace(), EstimateComboCIDStateSpace(), EstimateGUCStateSpace(), EstimateLibraryStateSpace(), EstimateParamExecSpace(), EstimateParamListSpace(), EstimateSnapshotSpace(), EstimateTransactionStateSpace(), ExecAggEstimate(), ExecAppendEstimate(), ExecBitmapHeapEstimate(), ExecBitmapHeapInitializeDSM(), ExecHashEstimate(), ExecIncrementalSortEstimate(), ExecMemoizeEstimate(), ExecSortEstimate(), expand_planner_arrays(), hash_estimate_size(), index_parallelscan_estimate(), index_parallelscan_initialize(), InitializeShmemGUCs(), InjectionPointShmemSize(), LockManagerShmemSize(), LWLockShmemSize(), MultiXactShmemSize(), PgArchShmemSize(), pgss_memsize(), PMSignalShmemSize(), 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 ( void *  seghdr)

Definition at line 100 of file shmem.c.

101 {
102  PGShmemHeader *shmhdr = (PGShmemHeader *) seghdr;
103 
104  ShmemSegHdr = shmhdr;
105  ShmemBase = (void *) shmhdr;
106  ShmemEnd = (char *) ShmemBase + shmhdr->totalsize;
107 }
static void * ShmemBase
Definition: shmem.c:83
static void * ShmemEnd
Definition: shmem.c:85
static PGShmemHeader * ShmemSegHdr
Definition: shmem.c:81
Size totalsize
Definition: pg_shmem.h:34

References ShmemBase, ShmemEnd, ShmemSegHdr, and PGShmemHeader::totalsize.

Referenced by CreateSharedMemoryAndSemaphores().

◆ InitShmemAllocation()

void InitShmemAllocation ( void  )

Definition at line 115 of file shmem.c.

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

References Assert, CACHELINEALIGN, PGShmemHeader::freeoffset, PGShmemHeader::index, ShmemAllocUnlocked(), ShmemIndex, ShmemLock, ShmemSegHdr, and SpinLockInit.

Referenced by CreateSharedMemoryAndSemaphores().

◆ InitShmemIndex()

void InitShmemIndex ( void  )

Definition at line 283 of file shmem.c.

284 {
285  HASHCTL info;
286 
287  /*
288  * Create the shared memory shmem index.
289  *
290  * Since ShmemInitHash calls ShmemInitStruct, which expects the ShmemIndex
291  * hashtable to exist already, we have a bit of a circularity problem in
292  * initializing the ShmemIndex itself. The special "ShmemIndex" hash
293  * table name will tell ShmemInitStruct to fake it.
294  */
296  info.entrysize = sizeof(ShmemIndexEnt);
297 
298  ShmemIndex = ShmemInitHash("ShmemIndex",
300  &info,
302 }
#define HASH_STRINGS
Definition: hsearch.h:96
#define HASH_ELEM
Definition: hsearch.h:95
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Definition: shmem.c:332
#define SHMEM_INDEX_SIZE
Definition: shmem.h:50
#define SHMEM_INDEX_KEYSIZE
Definition: shmem.h:48
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 (s1 == 0 || s2 == 0)
515  return 0;
516  result = s1 * s2;
517  /* We are assuming Size is an unsigned type here... */
518  if (result / s2 != s1)
519  ereport(ERROR,
520  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
521  errmsg("requested shared memory size overflows size_t")));
522  return result;
523 }

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

Referenced by _brin_begin_parallel(), _bt_begin_parallel(), 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(), hash_estimate_size(), InitializeParallelDSM(), LWLockShmemSize(), parallel_vacuum_init(), PGSemaphoreShmemSize(), PMSignalShmemSize(), PredicateLockShmemInit(), PredicateLockShmemSize(), ProcArrayShmemInit(), ProcArrayShmemSize(), ProcGlobalShmemSize(), ProcSignalShmemSize(), ReplicationOriginShmemSize(), ReplicationSlotsShmemSize(), SharedInvalShmemSize(), shm_toc_estimate(), tuplesort_estimate_shared(), TwoPhaseShmemSize(), WaitLSNShmemSize(), WalSndShmemSize(), and XLOGShmemSize().

◆ RequestAddinShmemSpace()

void RequestAddinShmemSpace ( Size  size)

Definition at line 76 of file ipci.c.

77 {
79  elog(FATAL, "cannot request additional shared memory outside shmem_request_hook");
81 }
#define FATAL
Definition: elog.h:41
#define elog(elevel,...)
Definition: elog.h:225
static Size total_addin_request
Definition: ipci.c:62
bool process_shmem_requests_in_progress
Definition: miscinit.c:1782
Size add_size(Size s1, Size s2)
Definition: shmem.c:493
static pg_noinline void Size size
Definition: slab.c:607

References add_size(), elog, FATAL, process_shmem_requests_in_progress, size, and total_addin_request.

Referenced by injection_shmem_request(), pgss_shmem_request(), and test_slru_shmem_request().

◆ ShmemAddrIsValid()

bool ShmemAddrIsValid ( const void *  addr)

Definition at line 274 of file shmem.c.

275 {
276  return (addr >= ShmemBase) && (addr < ShmemEnd);
277 }

References ShmemBase, and ShmemEnd.

Referenced by ReleasePredXact(), and ShmemInitStruct().

◆ ShmemAlloc()

void* ShmemAlloc ( Size  size)

Definition at line 152 of file shmem.c.

153 {
154  void *newSpace;
155  Size allocated_size;
156 
157  newSpace = ShmemAllocRaw(size, &allocated_size);
158  if (!newSpace)
159  ereport(ERROR,
160  (errcode(ERRCODE_OUT_OF_MEMORY),
161  errmsg("out of shared memory (%zu bytes requested)",
162  size)));
163  return newSpace;
164 }
static void * ShmemAllocRaw(Size size, Size *allocated_size)
Definition: shmem.c:186

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

Referenced by CreateLWLocks(), InitProcGlobal(), PredicateLockShmemInit(), ShmemInitStruct(), and StatsShmemInit().

◆ ShmemAllocNoError()

void* ShmemAllocNoError ( Size  size)

Definition at line 172 of file shmem.c.

173 {
174  Size allocated_size;
175 
176  return ShmemAllocRaw(size, &allocated_size);
177 }

References ShmemAllocRaw(), and size.

Referenced by ShmemInitHash().

◆ ShmemAllocUnlocked()

void* ShmemAllocUnlocked ( Size  size)

Definition at line 238 of file shmem.c.

239 {
240  Size newStart;
241  Size newFree;
242  void *newSpace;
243 
244  /*
245  * Ensure allocated space is adequately aligned.
246  */
247  size = MAXALIGN(size);
248 
249  Assert(ShmemSegHdr != NULL);
250 
251  newStart = ShmemSegHdr->freeoffset;
252 
253  newFree = newStart + size;
254  if (newFree > ShmemSegHdr->totalsize)
255  ereport(ERROR,
256  (errcode(ERRCODE_OUT_OF_MEMORY),
257  errmsg("out of shared memory (%zu bytes requested)",
258  size)));
259  ShmemSegHdr->freeoffset = newFree;
260 
261  newSpace = (void *) ((char *) ShmemBase + newStart);
262 
263  Assert(newSpace == (void *) MAXALIGN(newSpace));
264 
265  return newSpace;
266 }
#define MAXALIGN(LEN)
Definition: c.h:814
Size freeoffset
Definition: pg_shmem.h:35

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

Referenced by InitShmemAllocation(), and PGReserveSemaphores().

◆ ShmemInitHash()

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

Definition at line 332 of file shmem.c.

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

References HASHCTL::alloc, HASHCTL::dsize, HASH_ALLOC, HASH_ATTACH, hash_create(), HASH_DIRSIZE, hash_get_shared_size(), hash_select_dirsize(), HASH_SHARED_MEM, HASHCTL::hctl, HASHCTL::max_dsize, 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 387 of file shmem.c.

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

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

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

Variable Documentation

◆ ShmemLock

PGDLLIMPORT slock_t* ShmemLock
extern

Definition at line 87 of file shmem.c.

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