mirror of
https://github.com/postgres/postgres.git
synced 2026-04-23 07:07:22 -04:00
Refactor ShmemIndex initialization
Initialize the ShmemIndex hash table in InitShmemAllocator() already, removing the need for the separate InitShmemIndex() step. Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Discussion: https://www.postgresql.org/message-id/CAExHW5vM1bneLYfg0wGeAa=52UiJ3z4vKd3AJ72X8Fw6k3KKrg@mail.gmail.com
This commit is contained in:
parent
515b0dc4bc
commit
6b8238cb6a
3 changed files with 56 additions and 96 deletions
|
|
@ -250,16 +250,10 @@ static void
|
||||||
CreateOrAttachShmemStructs(void)
|
CreateOrAttachShmemStructs(void)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Now initialize LWLocks, which do shared memory allocation and are
|
* Now initialize LWLocks, which do shared memory allocation.
|
||||||
* needed for InitShmemIndex.
|
|
||||||
*/
|
*/
|
||||||
CreateLWLocks();
|
CreateLWLocks();
|
||||||
|
|
||||||
/*
|
|
||||||
* Set up shmem.c index hashtable
|
|
||||||
*/
|
|
||||||
InitShmemIndex();
|
|
||||||
|
|
||||||
dsm_shmem_init();
|
dsm_shmem_init();
|
||||||
DSMRegistryShmemInit();
|
DSMRegistryShmemInit();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,14 @@ Datum pg_numa_available(PG_FUNCTION_ARGS);
|
||||||
void
|
void
|
||||||
InitShmemAllocator(PGShmemHeader *seghdr)
|
InitShmemAllocator(PGShmemHeader *seghdr)
|
||||||
{
|
{
|
||||||
|
Size offset;
|
||||||
|
HASHCTL info;
|
||||||
|
int hash_flags;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
#ifndef EXEC_BACKEND
|
||||||
|
Assert(!IsUnderPostmaster);
|
||||||
|
#endif
|
||||||
Assert(seghdr != NULL);
|
Assert(seghdr != NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -133,45 +141,58 @@ InitShmemAllocator(PGShmemHeader *seghdr)
|
||||||
Assert(seghdr == (void *) MAXALIGN(seghdr));
|
Assert(seghdr == (void *) MAXALIGN(seghdr));
|
||||||
Assert(seghdr->content_offset == MAXALIGN(seghdr->content_offset));
|
Assert(seghdr->content_offset == MAXALIGN(seghdr->content_offset));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocations after this point should go through ShmemAlloc, which
|
||||||
|
* expects to allocate everything on cache line boundaries. Make sure the
|
||||||
|
* first allocation begins on a cache line boundary.
|
||||||
|
*/
|
||||||
|
offset = CACHELINEALIGN(seghdr->content_offset + sizeof(ShmemAllocatorData));
|
||||||
|
if (offset > seghdr->totalsize)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||||
|
errmsg("out of shared memory (%zu bytes requested)",
|
||||||
|
offset)));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In postmaster or stand-alone backend, initialize the shared memory
|
||||||
|
* allocator and the spinlock so that we can allocate shared memory for
|
||||||
|
* ShmemIndex using ShmemAlloc(). In a regular backend just set up the
|
||||||
|
* pointers required by ShmemAlloc().
|
||||||
|
*/
|
||||||
|
ShmemAllocator = (ShmemAllocatorData *) ((char *) seghdr + seghdr->content_offset);
|
||||||
|
if (!IsUnderPostmaster)
|
||||||
|
{
|
||||||
|
SpinLockInit(&ShmemAllocator->shmem_lock);
|
||||||
|
ShmemAllocator->free_offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShmemLock = &ShmemAllocator->shmem_lock;
|
||||||
ShmemSegHdr = seghdr;
|
ShmemSegHdr = seghdr;
|
||||||
ShmemBase = seghdr;
|
ShmemBase = seghdr;
|
||||||
ShmemEnd = (char *) ShmemBase + seghdr->totalsize;
|
ShmemEnd = (char *) ShmemBase + seghdr->totalsize;
|
||||||
|
|
||||||
#ifndef EXEC_BACKEND
|
/*
|
||||||
Assert(!IsUnderPostmaster);
|
* Create (or attach to) the shared memory index of shmem areas.
|
||||||
#endif
|
*
|
||||||
if (IsUnderPostmaster)
|
* This is the same initialization as ShmemInitHash() does, but we cannot
|
||||||
|
* use ShmemInitHash() here because it relies on ShmemIndex being already
|
||||||
|
* initialized.
|
||||||
|
*/
|
||||||
|
info.keysize = SHMEM_INDEX_KEYSIZE;
|
||||||
|
info.entrysize = sizeof(ShmemIndexEnt);
|
||||||
|
info.dsize = info.max_dsize = hash_select_dirsize(SHMEM_INDEX_SIZE);
|
||||||
|
info.alloc = ShmemAllocNoError;
|
||||||
|
hash_flags = HASH_ELEM | HASH_STRINGS | HASH_SHARED_MEM | HASH_ALLOC | HASH_DIRSIZE;
|
||||||
|
if (!IsUnderPostmaster)
|
||||||
{
|
{
|
||||||
PGShmemHeader *shmhdr = ShmemSegHdr;
|
size = hash_get_shared_size(&info, hash_flags);
|
||||||
|
ShmemAllocator->index = (HASHHDR *) ShmemAlloc(size);
|
||||||
ShmemAllocator = (ShmemAllocatorData *) ((char *) shmhdr + shmhdr->content_offset);
|
|
||||||
ShmemLock = &ShmemAllocator->shmem_lock;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
hash_flags |= HASH_ATTACH;
|
||||||
Size offset;
|
info.hctl = ShmemAllocator->index;
|
||||||
|
ShmemIndex = hash_create("ShmemIndex", SHMEM_INDEX_SIZE, &info, hash_flags);
|
||||||
/*
|
Assert(ShmemIndex != NULL);
|
||||||
* Allocations after this point should go through ShmemAlloc, which
|
|
||||||
* expects to allocate everything on cache line boundaries. Make sure
|
|
||||||
* the first allocation begins on a cache line boundary.
|
|
||||||
*/
|
|
||||||
offset = CACHELINEALIGN(seghdr->content_offset + sizeof(ShmemAllocatorData));
|
|
||||||
if (offset > seghdr->totalsize)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_OUT_OF_MEMORY),
|
|
||||||
errmsg("out of shared memory (%zu bytes requested)",
|
|
||||||
offset)));
|
|
||||||
|
|
||||||
ShmemAllocator = (ShmemAllocatorData *) ((char *) seghdr + seghdr->content_offset);
|
|
||||||
|
|
||||||
SpinLockInit(&ShmemAllocator->shmem_lock);
|
|
||||||
ShmemLock = &ShmemAllocator->shmem_lock;
|
|
||||||
ShmemAllocator->free_offset = offset;
|
|
||||||
/* ShmemIndex can't be set up yet (need LWLocks first) */
|
|
||||||
ShmemAllocator->index = NULL;
|
|
||||||
ShmemIndex = (HTAB *) NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -270,31 +291,6 @@ ShmemAddrIsValid(const void *addr)
|
||||||
return (addr >= ShmemBase) && (addr < ShmemEnd);
|
return (addr >= ShmemBase) && (addr < ShmemEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* InitShmemIndex() --- set up or attach to shmem index table.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
InitShmemIndex(void)
|
|
||||||
{
|
|
||||||
HASHCTL info;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
ShmemIndex = ShmemInitHash("ShmemIndex",
|
|
||||||
SHMEM_INDEX_SIZE, SHMEM_INDEX_SIZE,
|
|
||||||
&info,
|
|
||||||
HASH_ELEM | HASH_STRINGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ShmemInitHash -- Create and initialize, or attach to, a
|
* ShmemInitHash -- Create and initialize, or attach to, a
|
||||||
* shared memory hash table.
|
* shared memory hash table.
|
||||||
|
|
@ -383,39 +379,10 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
|
||||||
ShmemIndexEnt *result;
|
ShmemIndexEnt *result;
|
||||||
void *structPtr;
|
void *structPtr;
|
||||||
|
|
||||||
|
Assert(ShmemIndex != NULL);
|
||||||
|
|
||||||
LWLockAcquire(ShmemIndexLock, LW_EXCLUSIVE);
|
LWLockAcquire(ShmemIndexLock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
if (!ShmemIndex)
|
|
||||||
{
|
|
||||||
/* Must be trying to create/attach to ShmemIndex itself */
|
|
||||||
Assert(strcmp(name, "ShmemIndex") == 0);
|
|
||||||
|
|
||||||
if (IsUnderPostmaster)
|
|
||||||
{
|
|
||||||
/* Must be initializing a (non-standalone) backend */
|
|
||||||
Assert(ShmemAllocator->index != NULL);
|
|
||||||
structPtr = ShmemAllocator->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(ShmemAllocator->index == NULL);
|
|
||||||
structPtr = ShmemAlloc(size);
|
|
||||||
ShmemAllocator->index = structPtr;
|
|
||||||
*foundPtr = false;
|
|
||||||
}
|
|
||||||
LWLockRelease(ShmemIndexLock);
|
|
||||||
return structPtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* look it up in the shmem index */
|
/* look it up in the shmem index */
|
||||||
result = (ShmemIndexEnt *)
|
result = (ShmemIndexEnt *)
|
||||||
hash_search(ShmemIndex, name, HASH_ENTER_NULL, foundPtr);
|
hash_search(ShmemIndex, name, HASH_ENTER_NULL, foundPtr);
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@ extern void InitShmemAllocator(PGShmemHeader *seghdr);
|
||||||
extern void *ShmemAlloc(Size size);
|
extern void *ShmemAlloc(Size size);
|
||||||
extern void *ShmemAllocNoError(Size size);
|
extern void *ShmemAllocNoError(Size size);
|
||||||
extern bool ShmemAddrIsValid(const void *addr);
|
extern bool ShmemAddrIsValid(const void *addr);
|
||||||
extern void InitShmemIndex(void);
|
|
||||||
extern HTAB *ShmemInitHash(const char *name, int64 init_size, int64 max_size,
|
extern HTAB *ShmemInitHash(const char *name, int64 init_size, int64 max_size,
|
||||||
HASHCTL *infoP, int hash_flags);
|
HASHCTL *infoP, int hash_flags);
|
||||||
extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr);
|
extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue