diff options
Diffstat (limited to 'src/backend/storage/ipc/spin.c')
-rw-r--r-- | src/backend/storage/ipc/spin.c | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/src/backend/storage/ipc/spin.c b/src/backend/storage/ipc/spin.c new file mode 100644 index 00000000000..7ff2561f237 --- /dev/null +++ b/src/backend/storage/ipc/spin.c @@ -0,0 +1,247 @@ +/*------------------------------------------------------------------------- + * + * spin.c-- + * routines for managing spin locks + * + * Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.1.1.1 1996/07/09 06:21:55 scrappy Exp $ + * + *------------------------------------------------------------------------- + */ +/* + * POSTGRES has two kinds of locks: semaphores (which put the + * process to sleep) and spinlocks (which are supposed to be + * short term locks). Currently both are implemented as SysV + * semaphores, but presumably this can change if we move to + * a machine with a test-and-set (TAS) instruction. Its probably + * a good idea to think about (and allocate) short term and long + * term semaphores separately anyway. + * + * NOTE: These routines are not supposed to be widely used in Postgres. + * They are preserved solely for the purpose of porting Mark Sullivan's + * buffer manager to Postgres. + */ +#include <errno.h> +#include "postgres.h" +#include "storage/ipc.h" +#include "storage/shmem.h" +#include "storage/spin.h" +#include "storage/proc.h" +#include "utils/elog.h" + +/* globals used in this file */ +IpcSemaphoreId SpinLockId; + +#ifdef HAS_TEST_AND_SET +/* real spin lock implementations */ + +bool +CreateSpinlocks(IPCKey key) +{ + /* the spin lock shared memory must have been created by now */ + return(TRUE); +} + +bool +AttachSpinLocks(IPCKey key) +{ + /* the spin lock shared memory must have been attached by now */ + return(TRUE); +} + +bool +InitSpinLocks(int init, IPCKey key) +{ + extern SPINLOCK ShmemLock; + extern SPINLOCK BindingLock; + extern SPINLOCK BufMgrLock; + extern SPINLOCK LockMgrLock; + extern SPINLOCK ProcStructLock; + extern SPINLOCK SInvalLock; + extern SPINLOCK OidGenLockId; + +#ifdef MAIN_MEMORY + extern SPINLOCK MMCacheLock; +#endif /* SONY_JUKEBOX */ + + /* These six spinlocks have fixed location is shmem */ + ShmemLock = (SPINLOCK) SHMEMLOCKID; + BindingLock = (SPINLOCK) BINDINGLOCKID; + BufMgrLock = (SPINLOCK) BUFMGRLOCKID; + LockMgrLock = (SPINLOCK) LOCKMGRLOCKID; + ProcStructLock = (SPINLOCK) PROCSTRUCTLOCKID; + SInvalLock = (SPINLOCK) SINVALLOCKID; + OidGenLockId = (SPINLOCK) OIDGENLOCKID; + +#ifdef MAIN_MEMORY + MMCacheLock = (SPINLOCK) MMCACHELOCKID; +#endif /* MAIN_MEMORY */ + + return(TRUE); +} + +void +SpinAcquire(SPINLOCK lock) +{ + ExclusiveLock(lock); + PROC_INCR_SLOCK(lock); +} + +void +SpinRelease(SPINLOCK lock) +{ + PROC_DECR_SLOCK(lock); + ExclusiveUnlock(lock); +} + +bool +SpinIsLocked(SPINLOCK lock) +{ + return(!LockIsFree(lock)); +} + +#else /* HAS_TEST_AND_SET */ +/* Spinlocks are implemented using SysV semaphores */ + + +/* + * SpinAcquire -- try to grab a spinlock + * + * FAILS if the semaphore is corrupted. + */ +void +SpinAcquire(SPINLOCK lock) +{ + IpcSemaphoreLock(SpinLockId, lock, IpcExclusiveLock); + PROC_INCR_SLOCK(lock); +} + +/* + * SpinRelease -- release a spin lock + * + * FAILS if the semaphore is corrupted + */ +void +SpinRelease(SPINLOCK lock) +{ + Assert(SpinIsLocked(lock)) + PROC_DECR_SLOCK(lock); + IpcSemaphoreUnlock(SpinLockId, lock, IpcExclusiveLock); +} + +bool +SpinIsLocked(SPINLOCK lock) +{ + int semval; + + semval = IpcSemaphoreGetValue(SpinLockId, lock); + return(semval < IpcSemaphoreDefaultStartValue); +} + +/* + * CreateSpinlocks -- Create a sysV semaphore array for + * the spinlocks + * + */ +bool +CreateSpinlocks(IPCKey key) +{ + + int status; + IpcSemaphoreId semid; + semid = IpcSemaphoreCreate(key, MAX_SPINS, IPCProtection, + IpcSemaphoreDefaultStartValue, 1, &status); + if (status == IpcSemIdExist) { + IpcSemaphoreKill(key); + elog(NOTICE,"Destroying old spinlock semaphore"); + semid = IpcSemaphoreCreate(key, MAX_SPINS, IPCProtection, + IpcSemaphoreDefaultStartValue, 1, &status); + } + + if (semid >= 0) { + SpinLockId = semid; + return(TRUE); + } + /* cannot create spinlocks */ + elog(FATAL,"CreateSpinlocks: cannot create spin locks"); + return(FALSE); +} + +/* + * Attach to existing spinlock set + */ +bool +AttachSpinLocks(IPCKey key) +{ + IpcSemaphoreId id; + + id = semget (key, MAX_SPINS, 0); + if (id < 0) { + if (errno == EEXIST) { + /* key is the name of someone else's semaphore */ + elog (FATAL,"AttachSpinlocks: SPIN_KEY belongs to someone else"); + } + /* cannot create spinlocks */ + elog(FATAL,"AttachSpinlocks: cannot create spin locks"); + return(FALSE); + } + SpinLockId = id; + return(TRUE); +} + +/* + * InitSpinLocks -- Spinlock bootstrapping + * + * We need several spinlocks for bootstrapping: + * BindingLock (for the shmem binding table) and + * ShmemLock (for the shmem allocator), BufMgrLock (for buffer + * pool exclusive access), LockMgrLock (for the lock table), and + * ProcStructLock (a spin lock for the shared process structure). + * If there's a Sony WORM drive attached, we also have a spinlock + * (SJCacheLock) for it. Same story for the main memory storage mgr. + * + */ +bool +InitSpinLocks(int init, IPCKey key) +{ + extern SPINLOCK ShmemLock; + extern SPINLOCK BindingLock; + extern SPINLOCK BufMgrLock; + extern SPINLOCK LockMgrLock; + extern SPINLOCK ProcStructLock; + extern SPINLOCK SInvalLock; + extern SPINLOCK OidGenLockId; + +#ifdef MAIN_MEMORY + extern SPINLOCK MMCacheLock; +#endif /* MAIN_MEMORY */ + + if (!init || key != IPC_PRIVATE) { + /* if bootstrap and key is IPC_PRIVATE, it means that we are running + * backend by itself. no need to attach spinlocks + */ + if (! AttachSpinLocks(key)) { + elog(FATAL,"InitSpinLocks: couldnt attach spin locks"); + return(FALSE); + } + } + + /* These five (or six) spinlocks have fixed location is shmem */ + ShmemLock = (SPINLOCK) SHMEMLOCKID; + BindingLock = (SPINLOCK) BINDINGLOCKID; + BufMgrLock = (SPINLOCK) BUFMGRLOCKID; + LockMgrLock = (SPINLOCK) LOCKMGRLOCKID; + ProcStructLock = (SPINLOCK) PROCSTRUCTLOCKID; + SInvalLock = (SPINLOCK) SINVALLOCKID; + OidGenLockId = (SPINLOCK) OIDGENLOCKID; + +#ifdef MAIN_MEMORY + MMCacheLock = (SPINLOCK) MMCACHELOCKID; +#endif /* MAIN_MEMORY */ + + return(TRUE); +} +#endif /* HAS_TEST_AND_SET */ |