aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/ipc/spin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/ipc/spin.c')
-rw-r--r--src/backend/storage/ipc/spin.c247
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 */