diff options
| author | Tom Lane | 2001-09-29 04:02:27 +0000 |
|---|---|---|
| committer | Tom Lane | 2001-09-29 04:02:27 +0000 |
| commit | 499abb0c0f21cb861c5af1d49a06469f3cfcc1eb (patch) | |
| tree | 0af6262d9b6d1159315e93e90e69047b959ea5f5 /src/backend/storage/ipc/shmem.c | |
| parent | 818fb55ac49b4b20e65d9899fc1784e54e86db58 (diff) | |
Implement new 'lightweight lock manager' that's intermediate between
existing lock manager and spinlocks: it understands exclusive vs shared
lock but has few other fancy features. Replace most uses of spinlocks
with lightweight locks. All remaining uses of spinlocks have very short
lock hold times (a few dozen instructions), so tweak spinlock backoff
code to work efficiently given this assumption. All per my proposal on
pghackers 26-Sep-01.
Diffstat (limited to 'src/backend/storage/ipc/shmem.c')
| -rw-r--r-- | src/backend/storage/ipc/shmem.c | 145 |
1 files changed, 84 insertions, 61 deletions
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index dd86609875e..0ad168680a1 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.58 2001/09/07 00:27:29 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.59 2001/09/29 04:02:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -61,8 +61,10 @@ #include "postgres.h" #include "access/transam.h" +#include "storage/spin.h" #include "utils/tqual.h" + /* shared memory global variables */ static PGShmemHeader *ShmemSegHdr; /* shared mem segment header */ @@ -71,9 +73,7 @@ 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 slock_t *ShmemLock; /* spinlock for shared memory allocation */ static HTAB *ShmemIndex = NULL; /* primary index hashtable for shmem */ @@ -81,63 +81,33 @@ static bool ShmemBootstrap = false; /* bootstrapping shmem index? */ /* - * InitShmemAllocation() --- set up shared-memory allocation and index table. + * InitShmemAllocation() --- set up shared-memory allocation. + * + * Note: the argument should be declared "PGShmemHeader *seghdr", + * but we use void to avoid having to include ipc.h in shmem.h. */ void -InitShmemAllocation(PGShmemHeader *seghdr) +InitShmemAllocation(void *seghdr) { - HASHCTL info; - int hash_flags; - ShmemIndexEnt *result, - item; - bool found; + PGShmemHeader *shmhdr = (PGShmemHeader *) seghdr; /* Set up basic pointers to shared memory */ - ShmemSegHdr = seghdr; - ShmemBase = (SHMEM_OFFSET) seghdr; - ShmemEnd = ShmemBase + seghdr->totalsize; - - /* - * 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. - */ - ShmemIndex = (HTAB *) NULL; - ShmemBootstrap = true; - - /* create the shared memory shmem index */ - info.keysize = SHMEM_INDEX_KEYSIZE; - info.datasize = SHMEM_INDEX_DATASIZE; - hash_flags = HASH_ELEM; - - /* This will acquire the shmem index lock, but not release it. */ - ShmemIndex = ShmemInitHash("ShmemIndex", - SHMEM_INDEX_SIZE, SHMEM_INDEX_SIZE, - &info, hash_flags); - if (!ShmemIndex) - elog(FATAL, "InitShmemAllocation: couldn't initialize Shmem Index"); + ShmemSegHdr = shmhdr; + ShmemBase = (SHMEM_OFFSET) shmhdr; + ShmemEnd = ShmemBase + shmhdr->totalsize; /* - * Now, create an entry in the hashtable for the index itself. + * Initialize the spinlock used by ShmemAlloc. We have to do the + * space allocation the hard way, since ShmemAlloc can't be called yet. */ - MemSet(item.key, 0, SHMEM_INDEX_KEYSIZE); - strncpy(item.key, "ShmemIndex", SHMEM_INDEX_KEYSIZE); + ShmemLock = (slock_t *) (((char *) shmhdr) + shmhdr->freeoffset); + shmhdr->freeoffset += MAXALIGN(sizeof(slock_t)); + Assert(shmhdr->freeoffset <= shmhdr->totalsize); - result = (ShmemIndexEnt *) - hash_search(ShmemIndex, (char *) &item, HASH_ENTER, &found); - if (!result) - elog(FATAL, "InitShmemAllocation: corrupted shmem index"); + SpinLockInit(ShmemLock); - Assert(ShmemBootstrap && !found); - - result->location = MAKE_OFFSET(ShmemIndex->hctl); - result->size = SHMEM_INDEX_SIZE; - - ShmemBootstrap = false; - - /* now release the lock acquired in ShmemInitStruct */ - SpinRelease(ShmemIndexLock); + /* ShmemIndex can't be set up yet (need LWLocks first) */ + ShmemIndex = (HTAB *) NULL; /* * Initialize ShmemVariableCache for transaction manager. @@ -167,9 +137,9 @@ ShmemAlloc(Size size) */ size = MAXALIGN(size); - Assert(ShmemSegHdr); + Assert(ShmemSegHdr != NULL); - SpinAcquire(ShmemLock); + SpinLockAcquire(ShmemLock); newFree = ShmemSegHdr->freeoffset + size; if (newFree <= ShmemSegHdr->totalsize) @@ -180,7 +150,7 @@ ShmemAlloc(Size size) else newSpace = NULL; - SpinRelease(ShmemLock); + SpinLockRelease(ShmemLock); if (!newSpace) elog(NOTICE, "ShmemAlloc: out of memory"); @@ -200,6 +170,60 @@ ShmemIsValid(unsigned long addr) } /* + * InitShmemIndex() --- set up shmem index table. + */ +void +InitShmemIndex(void) +{ + HASHCTL info; + int hash_flags; + ShmemIndexEnt *result, + item; + bool found; + + /* + * 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. + */ + ShmemBootstrap = true; + + /* create the shared memory shmem index */ + info.keysize = SHMEM_INDEX_KEYSIZE; + info.datasize = SHMEM_INDEX_DATASIZE; + hash_flags = HASH_ELEM; + + /* This will acquire the shmem index lock, but not release it. */ + ShmemIndex = ShmemInitHash("ShmemIndex", + SHMEM_INDEX_SIZE, SHMEM_INDEX_SIZE, + &info, hash_flags); + if (!ShmemIndex) + elog(FATAL, "InitShmemIndex: couldn't initialize Shmem Index"); + + /* + * 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, "InitShmemIndex: corrupted shmem index"); + + Assert(ShmemBootstrap && !found); + + result->location = MAKE_OFFSET(ShmemIndex->hctl); + result->size = SHMEM_INDEX_SIZE; + + ShmemBootstrap = false; + + /* now release the lock acquired in ShmemInitStruct */ + LWLockRelease(ShmemIndexLock); +} + +/* * ShmemInitHash -- Create/Attach to and initialize * shared memory hash table. * @@ -207,8 +231,7 @@ ShmemIsValid(unsigned long addr) * * assume caller is doing some kind of synchronization * so that two people dont try to create/initialize the - * table at once. Use SpinAlloc() to create a spinlock - * for the structure before creating the structure itself. + * table at once. */ HTAB * ShmemInitHash(char *name, /* table string name for shmem index */ @@ -283,7 +306,7 @@ ShmemInitStruct(char *name, Size size, bool *foundPtr) strncpy(item.key, name, SHMEM_INDEX_KEYSIZE); item.location = BAD_LOCATION; - SpinAcquire(ShmemIndexLock); + LWLockAcquire(ShmemIndexLock, LW_EXCLUSIVE); if (!ShmemIndex) { @@ -306,7 +329,7 @@ ShmemInitStruct(char *name, Size size, bool *foundPtr) if (!result) { - SpinRelease(ShmemIndexLock); + LWLockRelease(ShmemIndexLock); elog(ERROR, "ShmemInitStruct: Shmem Index corrupted"); return NULL; } @@ -320,7 +343,7 @@ ShmemInitStruct(char *name, Size size, bool *foundPtr) */ if (result->size != size) { - SpinRelease(ShmemIndexLock); + LWLockRelease(ShmemIndexLock); elog(NOTICE, "ShmemInitStruct: ShmemIndex entry size is wrong"); /* let caller print its message too */ @@ -337,7 +360,7 @@ ShmemInitStruct(char *name, Size size, bool *foundPtr) /* out of memory */ Assert(ShmemIndex); hash_search(ShmemIndex, (char *) &item, HASH_REMOVE, foundPtr); - SpinRelease(ShmemIndexLock); + LWLockRelease(ShmemIndexLock); *foundPtr = FALSE; elog(NOTICE, "ShmemInitStruct: cannot allocate '%s'", @@ -349,6 +372,6 @@ ShmemInitStruct(char *name, Size size, bool *foundPtr) } Assert(ShmemIsValid((unsigned long) structPtr)); - SpinRelease(ShmemIndexLock); + LWLockRelease(ShmemIndexLock); return structPtr; } |
