summaryrefslogtreecommitdiff
path: root/src/backend/storage/ipc/spin.c
diff options
context:
space:
mode:
authorTom Lane2001-09-27 19:10:02 +0000
committerTom Lane2001-09-27 19:10:02 +0000
commit90aebf7f5242b11bc9576f5d9052d755336b1bcc (patch)
treedbc549709f897a737f5e799986674c5cea4617b3 /src/backend/storage/ipc/spin.c
parent3d59ad00e8cc6a1bd919280be839fca152149ec2 (diff)
Move s_lock.c and spin.c into lmgr subdirectory, which seems a much
more reasonable location for them.
Diffstat (limited to 'src/backend/storage/ipc/spin.c')
-rw-r--r--src/backend/storage/ipc/spin.c397
1 files changed, 0 insertions, 397 deletions
diff --git a/src/backend/storage/ipc/spin.c b/src/backend/storage/ipc/spin.c
deleted file mode 100644
index 05bf5acbbb3..00000000000
--- a/src/backend/storage/ipc/spin.c
+++ /dev/null
@@ -1,397 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * spin.c
- * routines for managing spin locks
- *
- * POSTGRES has two kinds of locks: semaphores (which put the
- * process to sleep) and spinlocks (which are supposed to be
- * short term locks). Spinlocks are implemented via test-and-set (TAS)
- * instructions if possible, else via semaphores. The semaphore method
- * is too slow to be useful :-(
- *
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.33 2001/06/27 23:31:39 tgl Exp $
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include <errno.h>
-#if !defined(HAS_TEST_AND_SET) && defined(HAVE_SYS_SEM_H)
-#include <sys/sem.h>
-#endif
-
-#include "miscadmin.h"
-#include "storage/proc.h"
-#include "storage/s_lock.h"
-
-
-/* Probably should move these to an appropriate header file */
-extern SPINLOCK BufMgrLock;
-extern SPINLOCK OidGenLockId;
-extern SPINLOCK XidGenLockId;
-extern SPINLOCK ControlFileLockId;
-extern SPINLOCK ShmemLock;
-extern SPINLOCK ShmemIndexLock;
-extern SPINLOCK LockMgrLock;
-extern SPINLOCK SInvalLock;
-extern SPINLOCK ProcStructLock;
-extern SPINLOCK FreeSpaceLock;
-#ifdef STABLE_MEMORY_STORAGE
-extern SPINLOCK MMCacheLock;
-#endif
-
-
-/*
- * Initialize identifiers for permanent spinlocks during startup
- *
- * The same identifiers are used for both TAS and semaphore implementations,
- * although in one case they are indexes into a shmem array and in the other
- * they are semaphore numbers.
- */
-static void
-InitSpinLockIDs(void)
-{
- BufMgrLock = (SPINLOCK) BUFMGRLOCKID;
- OidGenLockId = (SPINLOCK) OIDGENLOCKID;
- XidGenLockId = (SPINLOCK) XIDGENLOCKID;
- ControlFileLockId = (SPINLOCK) CNTLFILELOCKID;
- ShmemLock = (SPINLOCK) SHMEMLOCKID;
- ShmemIndexLock = (SPINLOCK) SHMEMINDEXLOCKID;
- LockMgrLock = (SPINLOCK) LOCKMGRLOCKID;
- SInvalLock = (SPINLOCK) SINVALLOCKID;
- ProcStructLock = (SPINLOCK) PROCSTRUCTLOCKID;
- FreeSpaceLock = (SPINLOCK) FREESPACELOCKID;
-#ifdef STABLE_MEMORY_STORAGE
- MMCacheLock = (SPINLOCK) MMCACHELOCKID;
-#endif
-}
-
-
-#ifdef HAS_TEST_AND_SET
-
-/* real spin lock implementation */
-
-typedef struct slock
-{
- slock_t shlock;
-} SLock;
-
-#ifdef LOCK_DEBUG
-bool Trace_spinlocks = false;
-
-inline static void
-PRINT_SLDEBUG(const char *where, SPINLOCK lockid, const SLock *lock)
-{
- if (Trace_spinlocks)
- elog(DEBUG, "%s: id=%d", where, lockid);
-}
-
-#else /* not LOCK_DEBUG */
-#define PRINT_SLDEBUG(a,b,c)
-#endif /* not LOCK_DEBUG */
-
-
-static SLock *SLockArray = NULL;
-
-#define SLOCKMEMORYSIZE ((int) MAX_SPINS * sizeof(SLock))
-
-/*
- * SLockShmemSize --- return shared-memory space needed
- */
-int
-SLockShmemSize(void)
-{
- return MAXALIGN(SLOCKMEMORYSIZE);
-}
-
-/*
- * CreateSpinlocks --- create and initialize spinlocks during startup
- */
-void
-CreateSpinlocks(PGShmemHeader *seghdr)
-{
- int id;
-
- /*
- * We must allocate the space "by hand" because shmem.c isn't up yet
- */
- SLockArray = (SLock *) (((char *) seghdr) + seghdr->freeoffset);
- seghdr->freeoffset += MAXALIGN(SLOCKMEMORYSIZE);
- Assert(seghdr->freeoffset <= seghdr->totalsize);
-
- /*
- * Initialize all spinlocks to "unlocked" state
- */
- for (id = 0; id < (int) MAX_SPINS; id++)
- {
- SLock *slckP = &(SLockArray[id]);
-
- S_INIT_LOCK(&(slckP->shlock));
- }
-
- /*
- * Assign indexes for fixed spinlocks
- */
- InitSpinLockIDs();
-}
-
-void
-SpinAcquire(SPINLOCK lockid)
-{
- SLock *slckP = &(SLockArray[lockid]);
-
- PRINT_SLDEBUG("SpinAcquire", lockid, slckP);
-
- /*
- * Acquire the lock, then record that we have done so (for recovery in
- * case of elog(ERROR) while holding the lock). Note we assume here
- * that S_LOCK will not accept cancel/die interrupts once it has
- * acquired the lock. However, interrupts should be accepted while
- * waiting, if InterruptHoldoffCount is zero.
- */
- S_LOCK(&(slckP->shlock));
- PROC_INCR_SLOCK(lockid);
-
- /*
- * Lock out cancel/die interrupts until we exit the code section
- * protected by the spinlock. This ensures that interrupts will not
- * interfere with manipulations of data structures in shared memory.
- */
- HOLD_INTERRUPTS();
-
- PRINT_SLDEBUG("SpinAcquire/done", lockid, slckP);
-}
-
-void
-SpinRelease(SPINLOCK lockid)
-{
- SLock *slckP = &(SLockArray[lockid]);
-
- PRINT_SLDEBUG("SpinRelease", lockid, slckP);
-
- /*
- * Check that we are actually holding the lock we are releasing. This
- * can be done only after MyProc has been initialized.
- */
- Assert(!MyProc || MyProc->sLocks[lockid] > 0);
-
- /*
- * Record that we no longer hold the spinlock, and release it.
- */
- PROC_DECR_SLOCK(lockid);
- S_UNLOCK(&(slckP->shlock));
-
- /*
- * Exit the interrupt holdoff entered in SpinAcquire().
- */
- RESUME_INTERRUPTS();
-
- PRINT_SLDEBUG("SpinRelease/done", lockid, slckP);
-}
-
-#else /* !HAS_TEST_AND_SET */
-
-/*
- * No TAS, so spinlocks are implemented using SysV semaphores.
- *
- * We support two slightly different APIs here: SpinAcquire/SpinRelease
- * work with SPINLOCK integer indexes for the permanent spinlocks, which
- * are all assumed to live in the first spinlock semaphore set. There
- * is also an emulation of the s_lock.h TAS-spinlock macros; for that case,
- * typedef slock_t stores the semId and sem number of the sema to use.
- * The semas needed are created by CreateSpinlocks and doled out by
- * s_init_lock_sema.
- *
- * Since many systems have a rather small SEMMSL limit on semas per set,
- * we allocate the semaphores required in sets of SPINLOCKS_PER_SET semas.
- * This value is deliberately made equal to PROC_NSEMS_PER_SET so that all
- * sema sets allocated by Postgres will be the same size; that eases the
- * semaphore-recycling logic in IpcSemaphoreCreate().
- *
- * Note that the SpinLockIds array is not in shared memory; it is filled
- * by the postmaster and then inherited through fork() by backends. This
- * is OK because its contents do not change after shmem initialization.
- */
-
-#define SPINLOCKS_PER_SET PROC_NSEMS_PER_SET
-
-static IpcSemaphoreId *SpinLockIds = NULL;
-
-static int numSpinSets = 0; /* number of sema sets used */
-static int numSpinLocks = 0; /* total number of semas allocated */
-static int nextSpinLock = 0; /* next free spinlock index */
-
-static void SpinFreeAllSemaphores(void);
-
-/*
- * SLockShmemSize --- return shared-memory space needed
- */
-int
-SLockShmemSize(void)
-{
- return 0;
-}
-
-/*
- * CreateSpinlocks --- create and initialize spinlocks during startup
- */
-void
-CreateSpinlocks(PGShmemHeader *seghdr)
-{
- int i;
-
- if (SpinLockIds == NULL)
- {
-
- /*
- * Compute number of spinlocks needed. If this logic gets any
- * more complicated, it should be distributed into the affected
- * modules, similar to the way shmem space estimation is handled.
- *
- * For now, though, we just need the fixed spinlocks (MAX_SPINS), two
- * spinlocks per shared disk buffer, and four spinlocks for XLOG.
- */
- numSpinLocks = (int) MAX_SPINS + 2 * NBuffers + 4;
-
- /* might as well round up to a multiple of SPINLOCKS_PER_SET */
- numSpinSets = (numSpinLocks - 1) / SPINLOCKS_PER_SET + 1;
- numSpinLocks = numSpinSets * SPINLOCKS_PER_SET;
-
- SpinLockIds = (IpcSemaphoreId *)
- malloc(numSpinSets * sizeof(IpcSemaphoreId));
- Assert(SpinLockIds != NULL);
- }
-
- for (i = 0; i < numSpinSets; i++)
- SpinLockIds[i] = -1;
-
- /*
- * Arrange to delete semas on exit --- set this up now so that we will
- * clean up if allocation fails. We use our own freeproc, rather than
- * IpcSemaphoreCreate's removeOnExit option, because we don't want to
- * fill up the on_shmem_exit list with a separate entry for each
- * semaphore set.
- */
- on_shmem_exit(SpinFreeAllSemaphores, 0);
-
- /* Create sema sets and set all semas to count 1 */
- for (i = 0; i < numSpinSets; i++)
- {
- SpinLockIds[i] = IpcSemaphoreCreate(SPINLOCKS_PER_SET,
- IPCProtection,
- 1,
- false);
- }
-
- /*
- * Assign indexes for fixed spinlocks
- */
- Assert(MAX_SPINS <= SPINLOCKS_PER_SET);
- InitSpinLockIDs();
-
- /* Init counter for allocating dynamic spinlocks */
- nextSpinLock = MAX_SPINS;
-}
-
-/*
- * SpinFreeAllSemaphores -
- * called at shmem_exit time, ie when exiting the postmaster or
- * destroying shared state for a failed set of backends.
- * Free up all the semaphores allocated for spinlocks.
- */
-static void
-SpinFreeAllSemaphores(void)
-{
- int i;
-
- for (i = 0; i < numSpinSets; i++)
- {
- if (SpinLockIds[i] >= 0)
- IpcSemaphoreKill(SpinLockIds[i]);
- }
- free(SpinLockIds);
- SpinLockIds = NULL;
-}
-
-/*
- * SpinAcquire -- grab a fixed spinlock
- *
- * FAILS if the semaphore is corrupted.
- */
-void
-SpinAcquire(SPINLOCK lock)
-{
-
- /*
- * See the TAS() version of this routine for primary commentary.
- *
- * NOTE we must pass interruptOK = false to IpcSemaphoreLock, to ensure
- * that a cancel/die interrupt cannot prevent us from recording
- * ownership of a lock we have just acquired.
- */
- IpcSemaphoreLock(SpinLockIds[0], lock, false);
- PROC_INCR_SLOCK(lock);
- HOLD_INTERRUPTS();
-}
-
-/*
- * SpinRelease -- release a fixed spin lock
- *
- * FAILS if the semaphore is corrupted
- */
-void
-SpinRelease(SPINLOCK lock)
-{
- /* See the TAS() version of this routine for commentary */
-#ifdef USE_ASSERT_CHECKING
- /* Check it's locked */
- int semval;
-
- semval = IpcSemaphoreGetValue(SpinLockIds[0], lock);
- Assert(semval < 1);
-#endif
- Assert(!MyProc || MyProc->sLocks[lockid] > 0);
- PROC_DECR_SLOCK(lock);
- IpcSemaphoreUnlock(SpinLockIds[0], lock);
- RESUME_INTERRUPTS();
-}
-
-/*
- * s_lock.h hardware-spinlock emulation
- */
-
-void
-s_init_lock_sema(volatile slock_t *lock)
-{
- if (nextSpinLock >= numSpinLocks)
- elog(FATAL, "s_init_lock_sema: not enough semaphores");
- lock->semId = SpinLockIds[nextSpinLock / SPINLOCKS_PER_SET];
- lock->sem = nextSpinLock % SPINLOCKS_PER_SET;
- nextSpinLock++;
-}
-
-void
-s_unlock_sema(volatile slock_t *lock)
-{
- IpcSemaphoreUnlock(lock->semId, lock->sem);
-}
-
-bool
-s_lock_free_sema(volatile slock_t *lock)
-{
- return IpcSemaphoreGetValue(lock->semId, lock->sem) > 0;
-}
-
-int
-tas_sema(volatile slock_t *lock)
-{
- /* Note that TAS macros return 0 if *success* */
- return !IpcSemaphoreTryLock(lock->semId, lock->sem);
-}
-
-#endif /* !HAS_TEST_AND_SET */