#include "postgres.h"
#include "access/transam.h"
#include "miscadmin.h"
#include "storage/lwlock.h"
#include "storage/pg_shmem.h"
#include "storage/shmem.h"
#include "storage/spin.h"
Go to the source code of this file.
Functions | |
void | InitShmemAccess (void *seghdr) |
void | InitShmemAllocation (void) |
void * | ShmemAlloc (Size size) |
bool | ShmemAddrIsValid (const void *addr) |
void | InitShmemIndex (void) |
HTAB * | ShmemInitHash (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) |
Variables | |
static PGShmemHeader * | ShmemSegHdr |
static void * | ShmemBase |
static void * | ShmemEnd |
slock_t * | ShmemLock |
static HTAB * | ShmemIndex = NULL |
Definition at line 418 of file shmem.c.
References ereport, errcode(), errmsg(), and ERROR.
Referenced by AsyncShmemInit(), AsyncShmemSize(), AutoVacuumShmemSize(), BackendStatusShmemSize(), BTreeShmemSize(), BufferShmemSize(), CheckpointerShmemSize(), CreateSharedInvalidationState(), CreateSharedMemoryAndSemaphores(), CreateSharedProcArray(), hash_estimate_size(), LockShmemSize(), LWLockShmemSize(), MultiXactShmemSize(), pgss_memsize(), PMSignalShmemSize(), PredicateLockShmemSize(), ProcArrayShmemSize(), ProcGlobalShmemSize(), RequestAddinShmemSpace(), SInvalShmemSize(), StrategyShmemSize(), TwoPhaseShmemSize(), WalRcvShmemSize(), WalSndShmemSize(), and XLOGShmemSize().
void InitShmemAccess | ( | void * | seghdr | ) |
Definition at line 97 of file shmem.c.
References ShmemBase, ShmemEnd, and PGShmemHeader::totalsize.
Referenced by CreateSharedMemoryAndSemaphores().
{ PGShmemHeader *shmhdr = (PGShmemHeader *) seghdr; ShmemSegHdr = shmhdr; ShmemBase = (void *) shmhdr; ShmemEnd = (char *) ShmemBase + shmhdr->totalsize; }
void InitShmemAllocation | ( | void | ) |
Definition at line 112 of file shmem.c.
References Assert, MAXALIGN, NULL, ShmemAlloc(), ShmemLock, ShmemVariableCache, and SpinLockInit.
Referenced by CreateSharedMemoryAndSemaphores().
{ PGShmemHeader *shmhdr = ShmemSegHdr; Assert(shmhdr != NULL); /* * Initialize the spinlock used by ShmemAlloc. We have to do the space * allocation the hard way, since obviously ShmemAlloc can't be called * yet. */ ShmemLock = (slock_t *) (((char *) shmhdr) + shmhdr->freeoffset); shmhdr->freeoffset += MAXALIGN(sizeof(slock_t)); Assert(shmhdr->freeoffset <= shmhdr->totalsize); SpinLockInit(ShmemLock); /* ShmemIndex can't be set up yet (need LWLocks first) */ shmhdr->index = NULL; ShmemIndex = (HTAB *) NULL; /* * Initialize ShmemVariableCache for transaction manager. (This doesn't * really belong here, but not worth moving.) */ ShmemVariableCache = (VariableCache) ShmemAlloc(sizeof(*ShmemVariableCache)); memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache)); }
void InitShmemIndex | ( | void | ) |
Definition at line 210 of file shmem.c.
References HASHCTL::entrysize, HASHCTL::keysize, SHMEM_INDEX_SIZE, and ShmemInitHash().
Referenced by CreateSharedMemoryAndSemaphores().
{ HASHCTL info; int hash_flags; /* * Create the shared memory shmem index. * * Since ShmemInitHash calls ShmemInitStruct, which expects the ShmemIndex * hashtable to exist already, we have a bit of a circularity problem in * initializing the ShmemIndex itself. The special "ShmemIndex" hash * table name will tell ShmemInitStruct to fake it. */ info.keysize = SHMEM_INDEX_KEYSIZE; info.entrysize = sizeof(ShmemIndexEnt); hash_flags = HASH_ELEM; ShmemIndex = ShmemInitHash("ShmemIndex", SHMEM_INDEX_SIZE, SHMEM_INDEX_SIZE, &info, hash_flags); }
Definition at line 435 of file shmem.c.
References ereport, errcode(), errmsg(), and ERROR.
Referenced by AsyncShmemInit(), AsyncShmemSize(), AutoVacuumShmemSize(), BackendStatusShmemSize(), BTreeShmemSize(), BufferShmemSize(), CheckpointerShmemSize(), CreateSharedBackendStatus(), CreateSharedInvalidationState(), CreateSharedProcArray(), hash_estimate_size(), InitPredicateLocks(), LWLockShmemSize(), PMSignalShmemSize(), PredicateLockShmemSize(), ProcArrayShmemSize(), ProcGlobalShmemSize(), SInvalShmemSize(), TwoPhaseShmemSize(), WalSndShmemSize(), and XLOGShmemSize().
bool ShmemAddrIsValid | ( | const void * | addr | ) |
Definition at line 201 of file shmem.c.
References ShmemBase, and ShmemEnd.
Referenced by NextPredXact(), ReleasePredXact(), ShmemInitStruct(), SHMQueueDelete(), SHMQueueElemInit(), SHMQueueEmpty(), SHMQueueInit(), SHMQueueInsertAfter(), SHMQueueInsertBefore(), SHMQueueIsDetached(), SHMQueueNext(), and SHMQueuePrev().
void* ShmemAlloc | ( | Size | size | ) |
Definition at line 152 of file shmem.c.
References Assert, BUFFERALIGN, ereport, errcode(), errmsg(), PGShmemHeader::freeoffset, MAXALIGN, NULL, ShmemBase, ShmemLock, SpinLockAcquire, SpinLockRelease, totalsize, and WARNING.
Referenced by CreateLWLocks(), InitPredicateLocks(), InitProcGlobal(), InitShmemAllocation(), and ShmemInitStruct().
{ Size newStart; Size newFree; void *newSpace; /* use volatile pointer to prevent code rearrangement */ volatile PGShmemHeader *shmemseghdr = ShmemSegHdr; /* * ensure all space is adequately aligned. */ size = MAXALIGN(size); Assert(shmemseghdr != NULL); SpinLockAcquire(ShmemLock); newStart = shmemseghdr->freeoffset; /* extra alignment for large requests, since they are probably buffers */ if (size >= BLCKSZ) newStart = BUFFERALIGN(newStart); newFree = newStart + size; if (newFree <= shmemseghdr->totalsize) { newSpace = (void *) ((char *) ShmemBase + newStart); shmemseghdr->freeoffset = newFree; } else newSpace = NULL; SpinLockRelease(ShmemLock); if (!newSpace) ereport(WARNING, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); return newSpace; }
HTAB* ShmemInitHash | ( | const char * | name, | |
long | init_size, | |||
long | max_size, | |||
HASHCTL * | infoP, | |||
int | hash_flags | |||
) |
Definition at line 255 of file shmem.c.
References HASHCTL::alloc, HASHCTL::dsize, HASH_ALLOC, hash_create(), hash_get_shared_size(), hash_select_dirsize(), HASH_SHARED_MEM, HASHCTL::hctl, HASHCTL::max_dsize, and ShmemInitStruct().
Referenced by InitBufTable(), InitLocks(), InitPredicateLocks(), InitShmemIndex(), and pgss_shmem_startup().
{ bool found; void *location; /* * Hash tables allocated in shared memory have a fixed directory; it can't * grow or other backends wouldn't be able to find it. So, make sure we * make it big enough to start with. * * The shared memory allocator must be specified too. */ infoP->dsize = infoP->max_dsize = hash_select_dirsize(max_size); infoP->alloc = ShmemAlloc; hash_flags |= HASH_SHARED_MEM | HASH_ALLOC | HASH_DIRSIZE; /* look it up in the shmem index */ location = ShmemInitStruct(name, hash_get_shared_size(infoP, hash_flags), &found); /* * if it already exists, attach to it rather than allocate and initialize * new space */ if (found) hash_flags |= HASH_ATTACH; /* Pass location of hashtable header to hash_create */ infoP->hctl = (HASHHDR *) location; return hash_create(name, init_size, infoP, hash_flags); }
Definition at line 310 of file shmem.c.
References Assert, ereport, errcode(), errmsg(), ERROR, HASH_ENTER_NULL, HASH_REMOVE, hash_search(), PGShmemHeader::index, IsUnderPostmaster, ShmemIndexEnt::location, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), NULL, ShmemAddrIsValid(), ShmemAlloc(), ShmemIndexLock, and ShmemIndexEnt::size.
Referenced by AsyncShmemInit(), AutoVacuumShmemInit(), BTreeShmemInit(), CheckpointerShmemInit(), CreateSharedBackendStatus(), CreateSharedInvalidationState(), CreateSharedProcArray(), InitBufferPool(), InitLocks(), InitPredicateLocks(), InitProcGlobal(), MultiXactShmemInit(), OldSerXidInit(), pgss_shmem_startup(), PMSignalShmemInit(), ProcSignalShmemInit(), ShmemInitHash(), SimpleLruInit(), StrategyInitialize(), SyncScanShmemInit(), TwoPhaseShmemInit(), WalRcvShmemInit(), WalSndShmemInit(), and XLOGShmemInit().
{ ShmemIndexEnt *result; void *structPtr; LWLockAcquire(ShmemIndexLock, LW_EXCLUSIVE); if (!ShmemIndex) { PGShmemHeader *shmemseghdr = ShmemSegHdr; /* Must be trying to create/attach to ShmemIndex itself */ Assert(strcmp(name, "ShmemIndex") == 0); if (IsUnderPostmaster) { /* Must be initializing a (non-standalone) backend */ Assert(shmemseghdr->index != NULL); structPtr = shmemseghdr->index; *foundPtr = TRUE; } else { /* * If the shmem index doesn't exist, we are bootstrapping: we must * be trying to init the shmem index itself. * * Notice that the ShmemIndexLock is released before the shmem * index has been initialized. This should be OK because no other * process can be accessing shared memory yet. */ Assert(shmemseghdr->index == NULL); structPtr = ShmemAlloc(size); if (structPtr == NULL) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("not enough shared memory for data structure" " \"%s\" (%lu bytes requested)", name, (unsigned long) size))); shmemseghdr->index = structPtr; *foundPtr = FALSE; } LWLockRelease(ShmemIndexLock); return structPtr; } /* look it up in the shmem index */ result = (ShmemIndexEnt *) hash_search(ShmemIndex, name, HASH_ENTER_NULL, foundPtr); if (!result) { LWLockRelease(ShmemIndexLock); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("could not create ShmemIndex entry for data structure \"%s\"", name))); } if (*foundPtr) { /* * Structure is in the shmem index so someone else has allocated it * already. The size better be the same as the size we are trying to * initialize to, or there is a name conflict (or worse). */ if (result->size != size) { LWLockRelease(ShmemIndexLock); ereport(ERROR, (errmsg("ShmemIndex entry size is wrong for data structure" " \"%s\": expected %lu, actual %lu", name, (unsigned long) size, (unsigned long) result->size))); } structPtr = result->location; } else { /* It isn't in the table yet. allocate and initialize it */ structPtr = ShmemAlloc(size); if (structPtr == NULL) { /* out of memory; remove the failed ShmemIndex entry */ hash_search(ShmemIndex, name, HASH_REMOVE, NULL); LWLockRelease(ShmemIndexLock); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("not enough shared memory for data structure" " \"%s\" (%lu bytes requested)", name, (unsigned long) size))); } result->size = size; result->location = structPtr; } LWLockRelease(ShmemIndexLock); Assert(ShmemAddrIsValid(structPtr)); return structPtr; }
void* ShmemBase [static] |
Definition at line 80 of file shmem.c.
Referenced by InitShmemAccess(), ShmemAddrIsValid(), and ShmemAlloc().
void* ShmemEnd [static] |
Definition at line 82 of file shmem.c.
Referenced by InitShmemAccess(), and ShmemAddrIsValid().
HTAB* ShmemIndex = NULL [static] |
Definition at line 84 of file shmem.c.
Referenced by InitShmemAllocation(), LWLockAssign(), and ShmemAlloc().
PGShmemHeader* ShmemSegHdr [static] |