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

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

Referenced by _bt_parallel_estimate_shared(), ApplyLauncherShmemSize(), AsyncShmemInit(), AsyncShmemSize(), AutoVacuumShmemSize(), BackendStatusShmemSize(), BackgroundWorkerShmemSize(), BTreeShmemSize(), BufferShmemSize(), CheckpointerShmemSize(), CreateSharedMemoryAndSemaphores(), CreateSharedProcArray(), estimate_variable_size(), EstimateComboCIDStateSpace(), EstimateGUCStateSpace(), EstimateLibraryStateSpace(), EstimateParamExecSpace(), EstimateParamListSpace(), EstimateSnapshotSpace(), EstimateTransactionStateSpace(), ExecAppendEstimate(), ExecBitmapHeapEstimate(), ExecHashEstimate(), ExecSortEstimate(), expand_planner_arrays(), hash_estimate_size(), index_parallelscan_estimate(), index_parallelscan_initialize(), LockShmemSize(), LWLockShmemSize(), MultiXactShmemSize(), 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().

499 {
500  Size result;
501 
502  result = s1 + s2;
503  /* We are assuming Size is an unsigned type here... */
504  if (result < s1 || result < s2)
505  ereport(ERROR,
506  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
507  errmsg("requested shared memory size overflows size_t")));
508  return result;
509 }
int errcode(int sqlerrcode)
Definition: elog.c:608
#define ERROR
Definition: elog.h:43
char * s1
#define ereport(elevel, rest)
Definition: elog.h:141
char * s2
size_t Size
Definition: c.h:467
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ 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:192
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:208
VariableCache ShmemVariableCache
Definition: varsup.c:34
void * ShmemAllocUnlocked(Size size)
Definition: shmem.c:247
#define Assert(condition)
Definition: c.h:739
#define CACHELINEALIGN(LEN)
Definition: c.h:695
slock_t * ShmemLock
Definition: shmem.c:88

◆ InitShmemIndex()

void InitShmemIndex ( void  )

Definition at line 292 of file shmem.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

293 {
294  HASHCTL info;
295  int hash_flags;
296 
297  /*
298  * Create the shared memory shmem index.
299  *
300  * Since ShmemInitHash calls ShmemInitStruct, which expects the ShmemIndex
301  * hashtable to exist already, we have a bit of a circularity problem in
302  * initializing the ShmemIndex itself. The special "ShmemIndex" hash
303  * table name will tell ShmemInitStruct to fake it.
304  */
306  info.entrysize = sizeof(ShmemIndexEnt);
307  hash_flags = HASH_ELEM;
308 
309  ShmemIndex = ShmemInitHash("ShmemIndex",
311  &info, hash_flags);
312 }
#define SHMEM_INDEX_SIZE
Definition: shmem.h:55
#define HASH_ELEM
Definition: hsearch.h:87
Size entrysize
Definition: hsearch.h:73
static HTAB * ShmemIndex
Definition: shmem.c:91
Size keysize
Definition: hsearch.h:72
#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:337

◆ mul_size()

Size mul_size ( Size  s1,
Size  s2 
)

Definition at line 515 of file shmem.c.

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

Referenced by ApplyLauncherShmemSize(), AsyncShmemInit(), AsyncShmemSize(), AutoVacuumShmemSize(), BackendStatusShmemSize(), BackgroundWorkerShmemSize(), BTreeShmemSize(), BufferShmemSize(), CheckpointerShmemSize(), CreateSharedBackendStatus(), CreateSharedProcArray(), EstimateComboCIDStateSpace(), EstimateReindexStateSpace(), EstimateSnapshotSpace(), EstimateTransactionStateSpace(), ExecHashEstimate(), ExecInitParallelPlan(), 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().

516 {
517  Size result;
518 
519  if (s1 == 0 || s2 == 0)
520  return 0;
521  result = s1 * s2;
522  /* We are assuming Size is an unsigned type here... */
523  if (result / s2 != s1)
524  ereport(ERROR,
525  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
526  errmsg("requested shared memory size overflows size_t")));
527  return result;
528 }
int errcode(int sqlerrcode)
Definition: elog.c:608
#define ERROR
Definition: elog.h:43
char * s1
#define ereport(elevel, rest)
Definition: elog.h:141
char * s2
size_t Size
Definition: c.h:467
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ pg_get_shmem_allocations()

Datum pg_get_shmem_allocations ( PG_FUNCTION_ARGS  )

Definition at line 532 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.

533 {
534 #define PG_GET_SHMEM_SIZES_COLS 4
535  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
536  TupleDesc tupdesc;
537  Tuplestorestate *tupstore;
538  MemoryContext per_query_ctx;
539  MemoryContext oldcontext;
540  HASH_SEQ_STATUS hstat;
541  ShmemIndexEnt *ent;
542  Size named_allocated = 0;
544  bool nulls[PG_GET_SHMEM_SIZES_COLS];
545 
546  /* check to see if caller supports us returning a tuplestore */
547  if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
548  ereport(ERROR,
549  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
550  errmsg("set-valued function called in context that cannot accept a set")));
551  if (!(rsinfo->allowedModes & SFRM_Materialize))
552  ereport(ERROR,
553  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
554  errmsg("materialize mode required, but it is not allowed in this context")));
555 
556  /* Build a tuple descriptor for our result type */
557  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
558  elog(ERROR, "return type must be a row type");
559 
560  per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
561  oldcontext = MemoryContextSwitchTo(per_query_ctx);
562 
563  tupstore = tuplestore_begin_heap(true, false, work_mem);
564  rsinfo->returnMode = SFRM_Materialize;
565  rsinfo->setResult = tupstore;
566  rsinfo->setDesc = tupdesc;
567 
568  MemoryContextSwitchTo(oldcontext);
569 
570  LWLockAcquire(ShmemIndexLock, LW_SHARED);
571 
572  hash_seq_init(&hstat, ShmemIndex);
573 
574  /* output all allocated entries */
575  memset(nulls, 0, sizeof(nulls));
576  while ((ent = (ShmemIndexEnt *) hash_seq_search(&hstat)) != NULL)
577  {
578  values[0] = CStringGetTextDatum(ent->key);
579  values[1] = Int64GetDatum((char *) ent->location - (char *) ShmemSegHdr);
580  values[2] = Int64GetDatum(ent->size);
581  values[3] = Int64GetDatum(ent->allocated_size);
582  named_allocated += ent->allocated_size;
583 
584  tuplestore_putvalues(tupstore, tupdesc, values, nulls);
585  }
586 
587  /* output shared memory allocated but not counted via the shmem index */
588  values[0] = CStringGetTextDatum("<anonymous>");
589  nulls[1] = true;
590  values[2] = Int64GetDatum(ShmemSegHdr->freeoffset - named_allocated);
591  values[3] = values[2];
592  tuplestore_putvalues(tupstore, tupdesc, values, nulls);
593 
594  /* output as-of-yet unused shared memory */
595  nulls[0] = true;
597  nulls[1] = false;
599  values[3] = values[2];
600  tuplestore_putvalues(tupstore, tupdesc, values, nulls);
601 
602  LWLockRelease(ShmemIndexLock);
603 
604  tuplestore_donestoring(tupstore);
605 
606  return (Datum) 0;
607 }
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, Datum *values, bool *isnull)
Definition: tuplestore.c:750
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
static PGShmemHeader * ShmemSegHdr
Definition: shmem.c:82
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:196
#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:608
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
static HTAB * ShmemIndex
Definition: shmem.c:91
#define ERROR
Definition: elog.h:43
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1699
#define ereport(elevel, rest)
Definition: elog.h:141
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:367
int work_mem
Definition: globals.c:121
int allowedModes
Definition: execnodes.h:302
SetFunctionReturnMode returnMode
Definition: execnodes.h:304
Size freeoffset
Definition: pg_shmem.h:35
size_t Size
Definition: c.h:467
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:230
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
Tuplestorestate * setResult
Definition: execnodes.h:307
static Datum values[MAXATTR]
Definition: bootstrap.c:167
ExprContext * econtext
Definition: execnodes.h:300
TupleDesc setDesc
Definition: execnodes.h:308
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
#define CStringGetTextDatum(s)
Definition: builtins.h:83

◆ 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:608
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
static void * ShmemAllocRaw(Size size, Size *allocated_size)
Definition: shmem.c:195
size_t Size
Definition: c.h:467
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ 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:467

◆ 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:739
#define CACHELINEALIGN(LEN)
Definition: c.h:695
Size freeoffset
Definition: pg_shmem.h:35
size_t Size
Definition: c.h:467
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:608
static void * ShmemBase
Definition: shmem.c:84
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
Size totalsize
Definition: pg_shmem.h:34
#define Assert(condition)
Definition: c.h:739
Size freeoffset
Definition: pg_shmem.h:35
size_t Size
Definition: c.h:467
#define MAXALIGN(LEN)
Definition: c.h:692
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ ShmemInitHash()

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

Definition at line 337 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().

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

◆ ShmemInitStruct()

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

Definition at line 392 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(), InitBufferPool(), InitLocks(), InitPredicateLocks(), InitProcGlobal(), MultiXactShmemInit(), OldSerXidInit(), pgss_shmem_startup(), PMSignalShmemInit(), ProcSignalShmemInit(), ReplicationOriginShmemInit(), ReplicationSlotsShmemInit(), ShmemInitHash(), SimpleLruInit(), SnapMgrInit(), StrategyInitialize(), SyncScanShmemInit(), TwoPhaseShmemInit(), WalRcvShmemInit(), WalSndShmemInit(), and XLOGShmemInit().

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