#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] |
1.7.1