aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/ipc/shmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/ipc/shmem.c')
-rw-r--r--src/backend/storage/ipc/shmem.c266
1 files changed, 65 insertions, 201 deletions
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index c5048a389b1..15922947087 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -8,14 +8,14 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.54 2000/11/21 21:16:01 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.55 2000/11/28 23:27:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* POSTGRES processes share one or more regions of shared memory.
* The shared memory is created by a postmaster and is inherited
- * by each backends via fork(). The routines in this file are used for
+ * by each backend via fork(). The routines in this file are used for
* allocating and binding to shared memory data structures.
*
* NOTES:
@@ -56,153 +56,57 @@
*
* See InitSem() in sem.c for an example of how to use the
* shmem index.
- *
*/
#include "postgres.h"
+
#include "access/transam.h"
#include "utils/tqual.h"
/* shared memory global variables */
-unsigned long ShmemBase = 0; /* start and end address of shared memory */
-static unsigned long ShmemEnd = 0;
-static unsigned long ShmemSize = 0; /* current size (and default) */
+static PGShmemHeader *ShmemSegHdr; /* shared mem segment header */
+
+SHMEM_OFFSET ShmemBase; /* start address of shared memory */
+
+static SHMEM_OFFSET ShmemEnd; /* end+1 address of shared memory */
SPINLOCK ShmemLock; /* lock for shared memory allocation */
SPINLOCK ShmemIndexLock; /* lock for shmem index access */
-static unsigned long *ShmemFreeStart = NULL; /* pointer to the OFFSET
- * of first free shared
- * memory */
-static unsigned long *ShmemIndexOffset = NULL; /* start of the shmem
- * index table (for
- * bootstrap) */
-static int ShmemBootstrap = FALSE; /* flag becomes true when shared
- * mem is created by POSTMASTER */
-
-static HTAB *ShmemIndex = NULL;
-
-/* ---------------------
- * ShmemIndexReset() - Resets the shmem index to NULL....
- * useful when the postmaster destroys existing shared memory
- * and creates all new segments after a backend crash.
- * ----------------------
- */
-void
-ShmemIndexReset(void)
-{
- ShmemIndex = (HTAB *) NULL;
-}
+static HTAB *ShmemIndex = NULL; /* primary index hashtable for shmem */
-/*
- * CreateSharedRegion()
- *
- * This routine is called once by the postmaster to
- * initialize the shared buffer pool. Assume there is
- * only one postmaster so no synchronization is necessary
- * until after this routine completes successfully.
- *
- * key is a unique identifier for the shmem region.
- * size is the size of the region.
- */
-static IpcMemoryId ShmemId;
+static bool ShmemBootstrap = false; /* bootstrapping shmem index? */
-void
-ShmemCreate(unsigned int key, unsigned int size)
-{
- if (size)
- ShmemSize = size;
- /* create shared mem region */
- if ((ShmemId = IpcMemoryCreate(key, ShmemSize, IPCProtection))
- == IpcMemCreationFailed)
- {
- elog(FATAL, "ShmemCreate: cannot create region");
- exit(1);
- }
-
- /*
- * ShmemBootstrap is true if shared memory has been created, but not
- * yet initialized. Only the postmaster/creator-of-all-things should
- * have this flag set.
- */
- ShmemBootstrap = TRUE;
-}
/*
- * InitShmem() -- map region into process address space
- * and initialize shared data structures.
- *
+ * InitShmemAllocation() --- set up shared-memory allocation and index table.
*/
-int
-InitShmem(unsigned int key, unsigned int size)
+void
+InitShmemAllocation(PGShmemHeader *seghdr)
{
- Pointer sharedRegion;
- unsigned long currFreeSpace;
-
HASHCTL info;
int hash_flags;
ShmemIndexEnt *result,
item;
bool found;
- IpcMemoryId shmid;
-
- /* if zero key, use default memory size */
- if (size)
- ShmemSize = size;
-
- /* default key is 0 */
-
- /* attach to shared memory region (SysV or BSD OS specific) */
- if (ShmemBootstrap && key == PrivateIPCKey)
- /* if we are running backend alone */
- shmid = ShmemId;
- else
- shmid = IpcMemoryIdGet(IPCKeyGetBufferMemoryKey(key), ShmemSize);
- sharedRegion = IpcMemoryAttach(shmid);
- if (sharedRegion == NULL)
- {
- elog(FATAL, "AttachSharedRegion: couldn't attach to shmem\n");
- return FALSE;
- }
-
- /* get pointers to the dimensions of shared memory */
- ShmemBase = (unsigned long) sharedRegion;
- ShmemEnd = (unsigned long) sharedRegion + ShmemSize;
-
- /* First long in shared memory is the available-space pointer */
- ShmemFreeStart = (unsigned long *) ShmemBase;
- /* next is a shmem pointer to the shmem index */
- ShmemIndexOffset = ShmemFreeStart + 1;
- /* next is ShmemVariableCache */
- ShmemVariableCache = (VariableCache) (ShmemIndexOffset + 1);
-
- /* here is where to start dynamic allocation */
- currFreeSpace = MAXALIGN(sizeof(*ShmemFreeStart) +
- sizeof(*ShmemIndexOffset) +
- sizeof(*ShmemVariableCache));
- /*
- * bootstrap initialize spin locks so we can start to use the
- * allocator and shmem index.
- */
- InitSpinLocks();
+ /* Set up basic pointers to shared memory */
+ ShmemSegHdr = seghdr;
+ ShmemBase = (SHMEM_OFFSET) seghdr;
+ ShmemEnd = ShmemBase + seghdr->totalsize;
/*
- * We have just allocated additional space for two spinlocks. Now
- * setup the global free space count
+ * 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. We set ShmemBootstrap
+ * to tell ShmemInitStruct to fake it.
*/
- if (ShmemBootstrap)
- {
- *ShmemFreeStart = currFreeSpace;
- memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache));
- }
-
- /* if ShmemFreeStart is NULL, then the allocator won't work */
- Assert(*ShmemFreeStart);
+ ShmemIndex = (HTAB *) NULL;
+ ShmemBootstrap = true;
- /* create OR attach to the shared memory shmem index */
+ /* create the shared memory shmem index */
info.keysize = SHMEM_INDEX_KEYSIZE;
info.datasize = SHMEM_INDEX_DATASIZE;
hash_flags = HASH_ELEM;
@@ -211,60 +115,43 @@ InitShmem(unsigned int key, unsigned int size)
ShmemIndex = ShmemInitHash("ShmemIndex",
SHMEM_INDEX_SIZE, SHMEM_INDEX_SIZE,
&info, hash_flags);
-
if (!ShmemIndex)
- {
- elog(FATAL, "InitShmem: couldn't initialize Shmem Index");
- return FALSE;
- }
+ elog(FATAL, "InitShmemAllocation: couldn't initialize Shmem Index");
/*
- * Now, check the shmem index for an entry to the shmem index. If
- * there is an entry there, someone else created the table. Otherwise,
- * we did and we have to initialize it.
+ * Now, create an entry in the hashtable for the index itself.
*/
MemSet(item.key, 0, SHMEM_INDEX_KEYSIZE);
strncpy(item.key, "ShmemIndex", SHMEM_INDEX_KEYSIZE);
result = (ShmemIndexEnt *)
hash_search(ShmemIndex, (char *) &item, HASH_ENTER, &found);
-
-
if (!result)
- {
- elog(FATAL, "InitShmem: corrupted shmem index");
- return FALSE;
- }
-
- if (!found)
- {
+ elog(FATAL, "InitShmemAllocation: corrupted shmem index");
- /*
- * bootstrapping shmem: we have to initialize the shmem index now.
- */
+ Assert(ShmemBootstrap && !found);
- Assert(ShmemBootstrap);
- result->location = MAKE_OFFSET(ShmemIndex->hctl);
- *ShmemIndexOffset = result->location;
- result->size = SHMEM_INDEX_SIZE;
+ result->location = MAKE_OFFSET(ShmemIndex->hctl);
+ result->size = SHMEM_INDEX_SIZE;
- ShmemBootstrap = FALSE;
+ ShmemBootstrap = false;
- }
- else
- Assert(!ShmemBootstrap);
- /* now release the lock acquired in ShmemHashInit */
+ /* now release the lock acquired in ShmemInitStruct */
SpinRelease(ShmemIndexLock);
- Assert(result->location == MAKE_OFFSET(ShmemIndex->hctl));
-
- return TRUE;
+ /*
+ * Initialize ShmemVariableCache for transaction manager.
+ */
+ ShmemVariableCache = (VariableCache)
+ ShmemAlloc(sizeof(*ShmemVariableCache));
+ memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache));
}
/*
- * ShmemAlloc -- allocate max-aligned byte string from shared memory
+ * ShmemAlloc -- allocate max-aligned chunk from shared memory
+ *
+ * Assumes ShmemLock and ShmemSegHdr are initialized.
*
- * Assumes ShmemLock and ShmemFreeStart are initialized.
* Returns: real pointer to memory or NULL if we are out
* of space. Has to return a real pointer in order
* to be compatible with malloc().
@@ -272,7 +159,7 @@ InitShmem(unsigned int key, unsigned int size)
void *
ShmemAlloc(Size size)
{
- unsigned long tmpFree;
+ uint32 newFree;
void *newSpace;
/*
@@ -280,15 +167,15 @@ ShmemAlloc(Size size)
*/
size = MAXALIGN(size);
- Assert(*ShmemFreeStart);
+ Assert(ShmemSegHdr);
SpinAcquire(ShmemLock);
- tmpFree = *ShmemFreeStart + size;
- if (tmpFree <= ShmemSize)
+ newFree = ShmemSegHdr->freeoffset + size;
+ if (newFree <= ShmemSegHdr->totalsize)
{
- newSpace = (void *) MAKE_PTR(*ShmemFreeStart);
- *ShmemFreeStart += size;
+ newSpace = (void *) MAKE_PTR(ShmemSegHdr->freeoffset);
+ ShmemSegHdr->freeoffset = newFree;
}
else
newSpace = NULL;
@@ -306,7 +193,7 @@ ShmemAlloc(Size size)
*
* Returns TRUE if the pointer is valid.
*/
-int
+bool
ShmemIsValid(unsigned long addr)
{
return (addr < ShmemEnd) && (addr >= ShmemBase);
@@ -394,16 +281,15 @@ ShmemPIDLookup(int pid, SHMEM_OFFSET *locationPtr)
sprintf(item.key, "PID %d", pid);
SpinAcquire(ShmemIndexLock);
+
result = (ShmemIndexEnt *)
hash_search(ShmemIndex, (char *) &item, HASH_ENTER, &found);
if (!result)
{
-
SpinRelease(ShmemIndexLock);
elog(ERROR, "ShmemInitPID: ShmemIndex corrupted");
return FALSE;
-
}
if (found)
@@ -438,19 +324,19 @@ ShmemPIDDestroy(int pid)
sprintf(item.key, "PID %d", pid);
SpinAcquire(ShmemIndexLock);
+
result = (ShmemIndexEnt *)
hash_search(ShmemIndex, (char *) &item, HASH_REMOVE, &found);
if (found)
location = result->location;
+
SpinRelease(ShmemIndexLock);
if (!result)
{
-
elog(ERROR, "ShmemPIDDestroy: PID table corrupted");
return INVALID_OFFSET;
-
}
if (found)
@@ -487,53 +373,31 @@ ShmemInitStruct(char *name, Size size, bool *foundPtr)
if (!ShmemIndex)
{
-#ifdef USE_ASSERT_CHECKING
- char *strname = "ShmemIndex";
-
-#endif
-
/*
- * If the shmem index doesn't exist, we fake it.
+ * If the shmem index doesn't exist, we are bootstrapping: we must
+ * be trying to init the shmem index itself.
*
- * If we are creating the first shmem index, then let shmemalloc()
- * allocate the space for a new HTAB. Otherwise, find the old one
- * and return that. Notice that the ShmemIndexLock is held until
- * the shmem index has been completely initialized.
+ * Notice that the ShmemIndexLock is held until the shmem index has
+ * been completely initialized.
*/
- Assert(strcmp(name, strname) == 0);
- if (ShmemBootstrap)
- {
- /* in POSTMASTER/Single process */
-
- *foundPtr = FALSE;
- return ShmemAlloc(size);
- }
- else
- {
- Assert(*ShmemIndexOffset);
-
- *foundPtr = TRUE;
- return (void *) MAKE_PTR(*ShmemIndexOffset);
- }
-
-
- }
- else
- {
- /* look it up in the shmem index */
- result = (ShmemIndexEnt *)
- hash_search(ShmemIndex, (char *) &item, HASH_ENTER, foundPtr);
+ Assert(strcmp(name, "ShmemIndex") == 0);
+ Assert(ShmemBootstrap);
+ *foundPtr = FALSE;
+ return ShmemAlloc(size);
}
+ /* look it up in the shmem index */
+ result = (ShmemIndexEnt *)
+ hash_search(ShmemIndex, (char *) &item, HASH_ENTER, foundPtr);
+
if (!result)
{
SpinRelease(ShmemIndexLock);
-
elog(ERROR, "ShmemInitStruct: Shmem Index corrupted");
return NULL;
-
}
- else if (*foundPtr)
+
+ if (*foundPtr)
{
/*