/*------------------------------------------------------------------------- * * 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 #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 */