PostgreSQL Source Code  git master
shmem.c File Reference
#include "postgres.h"
#include "access/transam.h"
#include "fmgr.h"
#include "funcapi.h"
#include "miscadmin.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
 

Functions

static void * ShmemAllocRaw (Size size, Size *allocated_size)
 
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)
 
Datum pg_get_shmem_allocations (PG_FUNCTION_ARGS)
 

Variables

static PGShmemHeaderShmemSegHdr
 
static void * ShmemBase
 
static void * ShmemEnd
 
slock_tShmemLock
 
static HTABShmemIndex = NULL
 

Macro Definition Documentation

◆ 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 502 of file shmem.c.

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

Referenced by _bt_parallel_estimate_shared(), ApplyLauncherShmemSize(), AsyncShmemInit(), AsyncShmemSize(), AutoVacuumShmemSize(), BackendStatusShmemSize(), BackgroundWorkerShmemSize(), begin_parallel_vacuum(), BTreeShmemSize(), BufferShmemSize(), CheckpointerShmemSize(), CreateSharedMemoryAndSemaphores(), CreateSharedProcArray(), estimate_variable_size(), EstimateComboCIDStateSpace(), EstimateGUCStateSpace(), EstimateLibraryStateSpace(), EstimateParamExecSpace(), EstimateParamListSpace(), EstimateSnapshotSpace(), EstimateTransactionStateSpace(), ExecAggEstimate(), ExecAppendEstimate(), ExecBitmapHeapEstimate(), ExecHashEstimate(), ExecIncrementalSortEstimate(), ExecMemoizeEstimate(), ExecSortEstimate(), expand_planner_arrays(), hash_estimate_size(), index_parallelscan_estimate(), index_parallelscan_initialize(), LockShmemSize(), LWLockShmemSize(), MultiXactShmemSize(), PgArchShmemSize(), pgss_memsize(), PMSignalShmemSize(), PredicateLockShmemSize(), ProcArrayShmemSize(), ProcGlobalShmemSize(), ProcSignalShmemSize(), ReplicationOriginShmemSize(), ReplicationSlotsShmemSize(), RequestAddinShmemSpace(), SerializeTransactionState(), shm_toc_estimate(), SInvalShmemSize(), SnapMgrShmemSize(), StrategyShmemSize(), table_parallelscan_estimate(), tuplesort_estimate_shared(), TwoPhaseShmemSize(), WalRcvShmemSize(), WalSndShmemSize(), and XLOGShmemSize().

503 {
504  Size result;
505 
506  result = s1 + s2;
507  /* We are assuming Size is an unsigned type here... */
508  if (result < s1 || result < s2)
509  ereport(ERROR,
510  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
511  errmsg("requested shared memory size overflows size_t")));
512  return result;
513 }
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
char * s1
char * s2
#define ereport(elevel,...)
Definition: elog.h:157
size_t Size
Definition: c.h:540
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ InitShmemAccess()

void InitShmemAccess ( void *  seghdr)

Definition at line 101 of file shmem.c.

References ShmemBase, ShmemEnd, and PGShmemHeader::totalsize.

Referenced by BackendRun(), and CreateSharedMemoryAndSemaphores().

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

◆ InitShmemAllocation()

void InitShmemAllocation ( void  )

Definition at line 116 of file shmem.c.

References Assert, CACHELINEALIGN, ShmemAlloc(), ShmemAllocUnlocked(), ShmemLock, ShmemSegHdr, ShmemVariableCache, and SpinLockInit.

Referenced by CreateSharedMemoryAndSemaphores().

117 {
118  PGShmemHeader *shmhdr = ShmemSegHdr;
119  char *aligned;
120 
121  Assert(shmhdr != NULL);
122 
123  /*
124  * Initialize the spinlock used by ShmemAlloc. We must use
125  * ShmemAllocUnlocked, since obviously ShmemAlloc can't be called yet.
126  */
128 
130 
131  /*
132  * Allocations after this point should go through ShmemAlloc, which
133  * expects to allocate everything on cache line boundaries. Make sure the
134  * first allocation begins on a cache line boundary.
135  */
136  aligned = (char *)
137  (CACHELINEALIGN((((char *) shmhdr) + shmhdr->freeoffset)));
138  shmhdr->freeoffset = aligned - (char *) shmhdr;
139 
140  /* ShmemIndex can't be set up yet (need LWLocks first) */
141  shmhdr->index = NULL;
142  ShmemIndex = (HTAB *) NULL;
143 
144  /*
145  * Initialize ShmemVariableCache for transaction manager. (This doesn't
146  * really belong here, but not worth moving.)
147  */
149  ShmemAlloc(sizeof(*ShmemVariableCache));
150  memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache));
151 }
int slock_t
Definition: s_lock.h:934
VariableCacheData * VariableCache
Definition: transam.h:257
static PGShmemHeader * ShmemSegHdr
Definition: shmem.c:82
#define SpinLockInit(lock)
Definition: spin.h:60
void * ShmemAlloc(Size size)
Definition: shmem.c:161
static HTAB * ShmemIndex
Definition: shmem.c:91
Definition: dynahash.c:219
VariableCache ShmemVariableCache
Definition: varsup.c:34
void * ShmemAllocUnlocked(Size size)
Definition: shmem.c:247
#define Assert(condition)
Definition: c.h:804
#define CACHELINEALIGN(LEN)
Definition: c.h:760
slock_t * ShmemLock
Definition: shmem.c:88

◆ InitShmemIndex()

void InitShmemIndex ( void  )

Definition at line 292 of file shmem.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

293 {
294  HASHCTL info;
295 
296  /*
297  * Create the shared memory shmem index.
298  *
299  * Since ShmemInitHash calls ShmemInitStruct, which expects the ShmemIndex
300  * hashtable to exist already, we have a bit of a circularity problem in
301  * initializing the ShmemIndex itself. The special "ShmemIndex" hash
302  * table name will tell ShmemInitStruct to fake it.
303  */
305  info.entrysize = sizeof(ShmemIndexEnt);
306 
307  ShmemIndex = ShmemInitHash("ShmemIndex",
309  &info,
311 }
#define SHMEM_INDEX_SIZE
Definition: shmem.h:55
#define HASH_ELEM
Definition: hsearch.h:95
Size entrysize
Definition: hsearch.h:76
static HTAB * ShmemIndex
Definition: shmem.c:91
Size keysize
Definition: hsearch.h:75
#define SHMEM_INDEX_KEYSIZE
Definition: shmem.h:53
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Definition: shmem.c:341
#define HASH_STRINGS
Definition: hsearch.h:96

◆ mul_size()

Size mul_size ( Size  s1,
Size  s2 
)

Definition at line 519 of file shmem.c.

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

Referenced by _bt_begin_parallel(), ApplyLauncherShmemSize(), AsyncShmemInit(), AsyncShmemSize(), AutoVacuumShmemSize(), BackendStatusShmemSize(), BackgroundWorkerShmemSize(), begin_parallel_vacuum(), BTreeShmemSize(), BufferShmemSize(), CheckpointerShmemSize(), CreateSharedBackendStatus(), CreateSharedProcArray(), EstimateComboCIDStateSpace(), EstimatePendingSyncsSpace(), EstimateReindexStateSpace(), EstimateSnapshotSpace(), EstimateTransactionStateSpace(), ExecAggEstimate(), ExecHashEstimate(), ExecIncrementalSortEstimate(), ExecInitParallelPlan(), ExecMemoizeEstimate(), ExecParallelRetrieveInstrumentation(), ExecParallelRetrieveJitInstrumentation(), ExecParallelSetupTupleQueues(), ExecSortEstimate(), hash_estimate_size(), InitializeParallelDSM(), InitPredicateLocks(), LWLockShmemSize(), PGSemaphoreShmemSize(), PMSignalShmemSize(), PostmasterMarkPIDForWorkerNotify(), PredicateLockShmemSize(), ProcArrayShmemSize(), ProcGlobalShmemSize(), ProcSignalShmemSize(), ReplicationOriginShmemSize(), ReplicationSlotsShmemSize(), shm_toc_estimate(), SInvalShmemSize(), SnapMgrShmemSize(), tuplesort_estimate_shared(), TwoPhaseShmemSize(), WalSndShmemSize(), and XLOGShmemSize().

520 {
521  Size result;
522 
523  if (s1 == 0 || s2 == 0)
524  return 0;
525  result = s1 * s2;
526  /* We are assuming Size is an unsigned type here... */
527  if (result / s2 != s1)
528  ereport(ERROR,
529  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
530  errmsg("requested shared memory size overflows size_t")));
531  return result;
532 }
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
char * s1
char * s2
#define ereport(elevel,...)
Definition: elog.h:157
size_t Size
Definition: c.h:540
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ pg_get_shmem_allocations()

Datum pg_get_shmem_allocations ( PG_FUNCTION_ARGS  )

Definition at line 536 of file shmem.c.

References ReturnSetInfo::allowedModes, CStringGetTextDatum, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, elog, ereport, errcode(), errmsg(), ERROR, PGShmemHeader::freeoffset, get_call_result_type(), hash_seq_init(), hash_seq_search(), Int64GetDatum(), IsA, LW_SHARED, LWLockAcquire(), LWLockRelease(), MemoryContextSwitchTo(), PG_GET_SHMEM_SIZES_COLS, ReturnSetInfo::returnMode, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, PGShmemHeader::totalsize, tuplestore_begin_heap(), tuplestore_donestoring, tuplestore_putvalues(), TYPEFUNC_COMPOSITE, values, and work_mem.

537 {
538 #define PG_GET_SHMEM_SIZES_COLS 4
539  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
540  TupleDesc tupdesc;
541  Tuplestorestate *tupstore;
542  MemoryContext per_query_ctx;
543  MemoryContext oldcontext;
544  HASH_SEQ_STATUS hstat;
545  ShmemIndexEnt *ent;
546  Size named_allocated = 0;
548  bool nulls[PG_GET_SHMEM_SIZES_COLS];
549 
550  /* check to see if caller supports us returning a tuplestore */
551  if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
552  ereport(ERROR,
553  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
554  errmsg("set-valued function called in context that cannot accept a set")));
555  if (!(rsinfo->allowedModes & SFRM_Materialize))
556  ereport(ERROR,
557  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
558  errmsg("materialize mode required, but it is not allowed in this context")));
559 
560  /* Build a tuple descriptor for our result type */
561  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
562  elog(ERROR, "return type must be a row type");
563 
564  per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
565  oldcontext = MemoryContextSwitchTo(per_query_ctx);
566 
567  tupstore = tuplestore_begin_heap(true, false, work_mem);
568  rsinfo->returnMode = SFRM_Materialize;
569  rsinfo->setResult = tupstore;
570  rsinfo->setDesc = tupdesc;
571 
572  MemoryContextSwitchTo(oldcontext);
573 
574  LWLockAcquire(ShmemIndexLock, LW_SHARED);
575 
576  hash_seq_init(&hstat, ShmemIndex);
577 
578  /* output all allocated entries */
579  memset(nulls, 0, sizeof(nulls));
580  while ((ent = (ShmemIndexEnt *) hash_seq_search(&hstat)) != NULL)
581  {
582  values[0] = CStringGetTextDatum(ent->key);
583  values[1] = Int64GetDatum((char *) ent->location - (char *) ShmemSegHdr);
584  values[2] = Int64GetDatum(ent->size);
585  values[3] = Int64GetDatum(ent->allocated_size);
586  named_allocated += ent->allocated_size;
587 
588  tuplestore_putvalues(tupstore, tupdesc, values, nulls);
589  }
590 
591  /* output shared memory allocated but not counted via the shmem index */
592  values[0] = CStringGetTextDatum("<anonymous>");
593  nulls[1] = true;
594  values[2] = Int64GetDatum(ShmemSegHdr->freeoffset - named_allocated);
595  values[3] = values[2];
596  tuplestore_putvalues(tupstore, tupdesc, values, nulls);
597 
598  /* output as-of-yet unused shared memory */
599  nulls[0] = true;
601  nulls[1] = false;
603  values[3] = values[2];
604  tuplestore_putvalues(tupstore, tupdesc, values, nulls);
605 
606  LWLockRelease(ShmemIndexLock);
607 
608  tuplestore_donestoring(tupstore);
609 
610  return (Datum) 0;
611 }
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, Datum *values, bool *isnull)
Definition: tuplestore.c:750
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
static PGShmemHeader * ShmemSegHdr
Definition: shmem.c:82
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:207
#define PG_GET_SHMEM_SIZES_COLS
#define tuplestore_donestoring(state)
Definition: tuplestore.h:60
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:698
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
static HTAB * ShmemIndex
Definition: shmem.c:91
#define ERROR
Definition: elog.h:46
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1697
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
Size totalsize
Definition: pg_shmem.h:34
uintptr_t Datum
Definition: postgres.h:411
int work_mem
Definition: globals.c:124
#define ereport(elevel,...)
Definition: elog.h:157
int allowedModes
Definition: execnodes.h:305
SetFunctionReturnMode returnMode
Definition: execnodes.h:307
Size freeoffset
Definition: pg_shmem.h:35
size_t Size
Definition: c.h:540
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:233
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
Tuplestorestate * setResult
Definition: execnodes.h:310
static Datum values[MAXATTR]
Definition: bootstrap.c:166
ExprContext * econtext
Definition: execnodes.h:303
TupleDesc setDesc
Definition: execnodes.h:311
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
#define CStringGetTextDatum(s)
Definition: builtins.h:82

◆ ShmemAddrIsValid()

bool ShmemAddrIsValid ( const void *  addr)

Definition at line 283 of file shmem.c.

References ShmemBase, and ShmemEnd.

Referenced by NextPredXact(), ReleasePredXact(), ShmemInitStruct(), SHMQueueDelete(), SHMQueueElemInit(), SHMQueueEmpty(), SHMQueueInit(), SHMQueueInsertAfter(), SHMQueueInsertBefore(), SHMQueueIsDetached(), SHMQueueNext(), and SHMQueuePrev().

284 {
285  return (addr >= ShmemBase) && (addr < ShmemEnd);
286 }
static void * ShmemBase
Definition: shmem.c:84
static void * ShmemEnd
Definition: shmem.c:86

◆ ShmemAlloc()

void* ShmemAlloc ( Size  size)

Definition at line 161 of file shmem.c.

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

Referenced by CreateLWLocks(), InitPredicateLocks(), InitProcGlobal(), InitShmemAllocation(), PostmasterMarkPIDForWorkerNotify(), and ShmemInitStruct().

162 {
163  void *newSpace;
164  Size allocated_size;
165 
166  newSpace = ShmemAllocRaw(size, &allocated_size);
167  if (!newSpace)
168  ereport(ERROR,
169  (errcode(ERRCODE_OUT_OF_MEMORY),
170  errmsg("out of shared memory (%zu bytes requested)",
171  size)));
172  return newSpace;
173 }
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
static void * ShmemAllocRaw(Size size, Size *allocated_size)
Definition: shmem.c:195
#define ereport(elevel,...)
Definition: elog.h:157
size_t Size
Definition: c.h:540
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ ShmemAllocNoError()

void* ShmemAllocNoError ( Size  size)

Definition at line 181 of file shmem.c.

References ShmemAllocRaw().

Referenced by ShmemInitHash().

182 {
183  Size allocated_size;
184 
185  return ShmemAllocRaw(size, &allocated_size);
186 }
static void * ShmemAllocRaw(Size size, Size *allocated_size)
Definition: shmem.c:195
size_t Size
Definition: c.h:540

◆ ShmemAllocRaw()

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

Definition at line 195 of file shmem.c.

References Assert, CACHELINEALIGN, PGShmemHeader::freeoffset, ShmemBase, ShmemLock, SpinLockAcquire, and SpinLockRelease.

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

196 {
197  Size newStart;
198  Size newFree;
199  void *newSpace;
200 
201  /*
202  * Ensure all space is adequately aligned. We used to only MAXALIGN this
203  * space but experience has proved that on modern systems that is not good
204  * enough. Many parts of the system are very sensitive to critical data
205  * structures getting split across cache line boundaries. To avoid that,
206  * attempt to align the beginning of the allocation to a cache line
207  * boundary. The calling code will still need to be careful about how it
208  * uses the allocated space - e.g. by padding each element in an array of
209  * structures out to a power-of-two size - but without this, even that
210  * won't be sufficient.
211  */
212  size = CACHELINEALIGN(size);
213  *allocated_size = size;
214 
215  Assert(ShmemSegHdr != NULL);
216 
218 
219  newStart = ShmemSegHdr->freeoffset;
220 
221  newFree = newStart + size;
222  if (newFree <= ShmemSegHdr->totalsize)
223  {
224  newSpace = (void *) ((char *) ShmemBase + newStart);
225  ShmemSegHdr->freeoffset = newFree;
226  }
227  else
228  newSpace = NULL;
229 
231 
232  /* note this assert is okay with newSpace == NULL */
233  Assert(newSpace == (void *) CACHELINEALIGN(newSpace));
234 
235  return newSpace;
236 }
static PGShmemHeader * ShmemSegHdr
Definition: shmem.c:82
static void * ShmemBase
Definition: shmem.c:84
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:804
#define CACHELINEALIGN(LEN)
Definition: c.h:760
Size freeoffset
Definition: pg_shmem.h:35
size_t Size
Definition: c.h:540
slock_t * ShmemLock
Definition: shmem.c:88

◆ ShmemAllocUnlocked()

void* ShmemAllocUnlocked ( Size  size)

Definition at line 247 of file shmem.c.

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

Referenced by InitShmemAllocation(), PGReserveSemaphores(), and SpinlockSemaInit().

248 {
249  Size newStart;
250  Size newFree;
251  void *newSpace;
252 
253  /*
254  * Ensure allocated space is adequately aligned.
255  */
256  size = MAXALIGN(size);
257 
258  Assert(ShmemSegHdr != NULL);
259 
260  newStart = ShmemSegHdr->freeoffset;
261 
262  newFree = newStart + size;
263  if (newFree > ShmemSegHdr->totalsize)
264  ereport(ERROR,
265  (errcode(ERRCODE_OUT_OF_MEMORY),
266  errmsg("out of shared memory (%zu bytes requested)",
267  size)));
268  ShmemSegHdr->freeoffset = newFree;
269 
270  newSpace = (void *) ((char *) ShmemBase + newStart);
271 
272  Assert(newSpace == (void *) MAXALIGN(newSpace));
273 
274  return newSpace;
275 }
static PGShmemHeader * ShmemSegHdr
Definition: shmem.c:82
int errcode(int sqlerrcode)
Definition: elog.c:698
static void * ShmemBase
Definition: shmem.c:84
#define ERROR
Definition: elog.h:46
Size totalsize
Definition: pg_shmem.h:34
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
Size freeoffset
Definition: pg_shmem.h:35
size_t Size
Definition: c.h:540
#define MAXALIGN(LEN)
Definition: c.h:757
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ ShmemInitHash()

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

Definition at line 341 of file shmem.c.

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, ShmemAllocNoError(), and ShmemInitStruct().

Referenced by InitBufTable(), InitLocks(), InitPredicateLocks(), InitShmemIndex(), and pgss_shmem_startup().

346 {
347  bool found;
348  void *location;
349 
350  /*
351  * Hash tables allocated in shared memory have a fixed directory; it can't
352  * grow or other backends wouldn't be able to find it. So, make sure we
353  * make it big enough to start with.
354  *
355  * The shared memory allocator must be specified too.
356  */
357  infoP->dsize = infoP->max_dsize = hash_select_dirsize(max_size);
358  infoP->alloc = ShmemAllocNoError;
359  hash_flags |= HASH_SHARED_MEM | HASH_ALLOC | HASH_DIRSIZE;
360 
361  /* look it up in the shmem index */
362  location = ShmemInitStruct(name,
363  hash_get_shared_size(infoP, hash_flags),
364  &found);
365 
366  /*
367  * if it already exists, attach to it rather than allocate and initialize
368  * new space
369  */
370  if (found)
371  hash_flags |= HASH_ATTACH;
372 
373  /* Pass location of hashtable header to hash_create */
374  infoP->hctl = (HASHHDR *) location;
375 
376  return hash_create(name, init_size, infoP, hash_flags);
377 }
void * ShmemAllocNoError(Size size)
Definition: shmem.c:181
#define HASH_SHARED_MEM
Definition: hsearch.h:103
long dsize
Definition: hsearch.h:72
#define HASH_ATTACH
Definition: hsearch.h:104
long max_dsize
Definition: hsearch.h:73
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:396
HashAllocFunc alloc
Definition: hsearch.h:84
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
long hash_select_dirsize(long num_entries)
Definition: dynahash.c:827
Size hash_get_shared_size(HASHCTL *info, int flags)
Definition: dynahash.c:851
HASHHDR * hctl
Definition: hsearch.h:88
const char * name
Definition: encode.c:515
#define HASH_DIRSIZE
Definition: hsearch.h:94
#define HASH_ALLOC
Definition: hsearch.h:101

◆ ShmemInitStruct()

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

Definition at line 396 of file shmem.c.

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(), ShmemAddrIsValid(), ShmemAlloc(), ShmemAllocRaw(), ShmemSegHdr, and ShmemIndexEnt::size.

Referenced by ApplyLauncherShmemInit(), apw_init_shmem(), AsyncShmemInit(), AutoVacuumShmemInit(), AuxiliaryPidGetProc(), BackgroundWorkerShmemInit(), BTreeShmemInit(), CheckpointerShmemInit(), CommitTsShmemInit(), CreateSharedBackendStatus(), CreateSharedInvalidationState(), CreateSharedProcArray(), dsm_shmem_init(), InitBufferPool(), InitLocks(), InitPredicateLocks(), InitProcGlobal(), MultiXactShmemInit(), PgArchShmemInit(), pgss_shmem_startup(), PMSignalShmemInit(), ProcSignalShmemInit(), ReplicationOriginShmemInit(), ReplicationSlotsShmemInit(), SerialInit(), ShmemInitHash(), SimpleLruInit(), SnapMgrInit(), StrategyInitialize(), SyncScanShmemInit(), TwoPhaseShmemInit(), WalRcvShmemInit(), WalSndShmemInit(), and XLOGShmemInit().

397 {
398  ShmemIndexEnt *result;
399  void *structPtr;
400 
401  LWLockAcquire(ShmemIndexLock, LW_EXCLUSIVE);
402 
403  if (!ShmemIndex)
404  {
405  PGShmemHeader *shmemseghdr = ShmemSegHdr;
406 
407  /* Must be trying to create/attach to ShmemIndex itself */
408  Assert(strcmp(name, "ShmemIndex") == 0);
409 
410  if (IsUnderPostmaster)
411  {
412  /* Must be initializing a (non-standalone) backend */
413  Assert(shmemseghdr->index != NULL);
414  structPtr = shmemseghdr->index;
415  *foundPtr = true;
416  }
417  else
418  {
419  /*
420  * If the shmem index doesn't exist, we are bootstrapping: we must
421  * be trying to init the shmem index itself.
422  *
423  * Notice that the ShmemIndexLock is released before the shmem
424  * index has been initialized. This should be OK because no other
425  * process can be accessing shared memory yet.
426  */
427  Assert(shmemseghdr->index == NULL);
428  structPtr = ShmemAlloc(size);
429  shmemseghdr->index = structPtr;
430  *foundPtr = false;
431  }
432  LWLockRelease(ShmemIndexLock);
433  return structPtr;
434  }
435 
436  /* look it up in the shmem index */
437  result = (ShmemIndexEnt *)
439 
440  if (!result)
441  {
442  LWLockRelease(ShmemIndexLock);
443  ereport(ERROR,
444  (errcode(ERRCODE_OUT_OF_MEMORY),
445  errmsg("could not create ShmemIndex entry for data structure \"%s\"",
446  name)));
447  }
448 
449  if (*foundPtr)
450  {
451  /*
452  * Structure is in the shmem index so someone else has allocated it
453  * already. The size better be the same as the size we are trying to
454  * initialize to, or there is a name conflict (or worse).
455  */
456  if (result->size != size)
457  {
458  LWLockRelease(ShmemIndexLock);
459  ereport(ERROR,
460  (errmsg("ShmemIndex entry size is wrong for data structure"
461  " \"%s\": expected %zu, actual %zu",
462  name, size, result->size)));
463  }
464  structPtr = result->location;
465  }
466  else
467  {
468  Size allocated_size;
469 
470  /* It isn't in the table yet. allocate and initialize it */
471  structPtr = ShmemAllocRaw(size, &allocated_size);
472  if (structPtr == NULL)
473  {
474  /* out of memory; remove the failed ShmemIndex entry */
476  LWLockRelease(ShmemIndexLock);
477  ereport(ERROR,
478  (errcode(ERRCODE_OUT_OF_MEMORY),
479  errmsg("not enough shared memory for data structure"
480  " \"%s\" (%zu bytes requested)",
481  name, size)));
482  }
483  result->size = size;
484  result->allocated_size = allocated_size;
485  result->location = structPtr;
486  }
487 
488  LWLockRelease(ShmemIndexLock);
489 
490  Assert(ShmemAddrIsValid(structPtr));
491 
492  Assert(structPtr == (void *) CACHELINEALIGN(structPtr));
493 
494  return structPtr;
495 }
static PGShmemHeader * ShmemSegHdr
Definition: shmem.c:82
Size size
Definition: shmem.h:62
int errcode(int sqlerrcode)
Definition: elog.c:698
void * ShmemAlloc(Size size)
Definition: shmem.c:161
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
static HTAB * ShmemIndex
Definition: shmem.c:91
#define ERROR
Definition: elog.h:46
void * location
Definition: shmem.h:61
bool IsUnderPostmaster
Definition: globals.c:112
static void * ShmemAllocRaw(Size size, Size *allocated_size)
Definition: shmem.c:195
#define ereport(elevel,...)
Definition: elog.h:157
bool ShmemAddrIsValid(const void *addr)
Definition: shmem.c:283
#define Assert(condition)
Definition: c.h:804
#define CACHELINEALIGN(LEN)
Definition: c.h:760
size_t Size
Definition: c.h:540
Size allocated_size
Definition: shmem.h:63
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
const char * name
Definition: encode.c:515
int errmsg(const char *fmt,...)
Definition: elog.c:909
void * index
Definition: pg_shmem.h:37

Variable Documentation

◆ ShmemBase

void* ShmemBase
static

Definition at line 84 of file shmem.c.

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

◆ ShmemEnd

void* ShmemEnd
static

Definition at line 86 of file shmem.c.

Referenced by InitShmemAccess(), and ShmemAddrIsValid().

◆ ShmemIndex

HTAB* ShmemIndex = NULL
static

Definition at line 91 of file shmem.c.

◆ ShmemLock

◆ ShmemSegHdr

PGShmemHeader* ShmemSegHdr
static

Definition at line 82 of file shmem.c.

Referenced by InitShmemAllocation(), and ShmemInitStruct().