aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/lmgr/spin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/lmgr/spin.c')
-rw-r--r--src/backend/storage/lmgr/spin.c143
1 files changed, 24 insertions, 119 deletions
diff --git a/src/backend/storage/lmgr/spin.c b/src/backend/storage/lmgr/spin.c
index f5bb8e34889..c384c4b1586 100644
--- a/src/backend/storage/lmgr/spin.c
+++ b/src/backend/storage/lmgr/spin.c
@@ -6,7 +6,8 @@
*
* For machines that have test-and-set (TAS) instructions, s_lock.h/.c
* define the spinlock implementation. This file contains only a stub
- * implementation for spinlocks using SysV semaphores. The semaphore method
+ * implementation for spinlocks using PGSemaphores. Unless semaphores
+ * are implemented in a way that doesn't involve a kernel call, this
* is too slow to be very useful :-(
*
*
@@ -15,143 +16,49 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/spin.c,v 1.7 2001/11/05 17:46:28 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/spin.c,v 1.8 2002/05/05 00:03:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
-#include <errno.h>
-
-#include "storage/ipc.h"
-/* In Ultrix, sem.h and shm.h must be included AFTER ipc.h */
-#ifdef HAVE_SYS_SEM_H
-#include <sys/sem.h>
-#endif
-
-#if defined(__darwin__)
-#include "port/darwin/sem.h"
-#endif
-
#include "storage/lwlock.h"
-#include "storage/proc.h"
+#include "storage/pg_sema.h"
#include "storage/spin.h"
#ifdef HAS_TEST_AND_SET
/*
- * CreateSpinlocks --- create and initialize spinlocks during startup
+ * Report number of semaphores needed to support spinlocks.
*/
-void
-CreateSpinlocks(void)
+int
+SpinlockSemas(void)
{
- /* no-op when we have TAS spinlocks */
+ return 0;
}
#else /* !HAS_TEST_AND_SET */
/*
- * No TAS, so spinlocks are implemented using SysV semaphores.
- *
- * 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.
+ * No TAS, so spinlocks are implemented as PGSemaphores.
*/
-#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);
-
/*
- * CreateSpinlocks --- create and initialize spinlocks during startup
+ * Report number of semaphores needed to support spinlocks.
*/
-void
-CreateSpinlocks(void)
+int
+SpinlockSemas(void)
{
- int i;
-
- if (SpinLockIds == NULL)
- {
- /*
- * Compute number of spinlocks needed. It would be cleaner to
- * distribute this logic into the affected modules, similar to the
- * way shmem space estimation is handled.
- *
- * For now, though, we just need a few spinlocks (10 should be
- * plenty) plus one for each LWLock.
- */
- numSpinLocks = NumLWLocks() + 10;
-
- /* 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.
+ * It would be cleaner to distribute this logic into the affected modules,
+ * similar to the way shmem space estimation is handled.
+ *
+ * For now, though, we just need a few spinlocks (10 should be
+ * plenty) plus one for each LWLock.
*/
- 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);
- }
-
- /* Init counter for allocating dynamic spinlocks */
- nextSpinLock = 0;
-}
-
-/*
- * 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;
+ return NumLWLocks() + 10;
}
/*
@@ -161,30 +68,28 @@ SpinFreeAllSemaphores(void)
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++;
+ PGSemaphoreCreate((PGSemaphore) lock);
}
void
s_unlock_sema(volatile slock_t *lock)
{
- IpcSemaphoreUnlock(lock->semId, lock->sem);
+ PGSemaphoreUnlock((PGSemaphore) lock);
}
bool
s_lock_free_sema(volatile slock_t *lock)
{
- return IpcSemaphoreGetValue(lock->semId, lock->sem) > 0;
+ /* We don't currently use S_LOCK_FREE anyway */
+ elog(ERROR, "spin.c does not support S_LOCK_FREE()");
+ return false;
}
int
tas_sema(volatile slock_t *lock)
{
/* Note that TAS macros return 0 if *success* */
- return !IpcSemaphoreTryLock(lock->semId, lock->sem);
+ return !PGSemaphoreTryLock((PGSemaphore) lock);
}
#endif /* !HAS_TEST_AND_SET */