diff --git a/src/backend/access/common/heapvalid.c b/src/backend/access/common/heapvalid.c
index da2e93a30b..22d62afcd3 100644
--- a/src/backend/access/common/heapvalid.c
+++ b/src/backend/access/common/heapvalid.c
@@ -7,143 +7,15 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/common/Attic/heapvalid.c,v 1.19 1997/09/12 04:07:09 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/common/Attic/heapvalid.c,v 1.20 1997/09/18 14:19:27 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include <postgres.h>
 
-#include <fmgr.h>
 #include <access/heapam.h>
-#include <access/valid.h>
 #include <access/xact.h>
-#include <storage/bufpage.h>
-#include <utils/rel.h>
-#include <utils/tqual.h>
-#include <storage/bufmgr.h>
-#include <utils/builtins.h>
-
-/* ----------------
- *		heap_keytest
- *
- *		Test a heap tuple with respect to a scan key.
- * ----------------
- */
-bool
-heap_keytest(HeapTuple t,
-			 TupleDesc tupdesc,
-			 int nkeys,
-			 ScanKey keys)
-{
-	bool		isnull;
-	Datum		atp;
-	int			test;
-
-	for (; nkeys--; keys++)
-	{
-		atp = heap_getattr(t, InvalidBuffer,
-						   keys->sk_attno,
-						   tupdesc,
-						   &isnull);
-
-		if (isnull)
-			/* XXX eventually should check if SK_ISNULL */
-			return false;
-
-		if (keys->sk_flags & SK_ISNULL)
-		{
-			return (false);
-		}
-
-		if (keys->sk_func == (func_ptr) oideq)	/* optimization */
-			test = (keys->sk_argument == atp);
-		else if (keys->sk_flags & SK_COMMUTE)
-			test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure,
-									keys->sk_argument, atp);
-		else
-			test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure,
-									atp, keys->sk_argument);
-
-		if (!test == !(keys->sk_flags & SK_NEGATE))
-			return false;
-	}
-
-	return true;
-}
-
-/* ----------------
- *		heap_tuple_satisfies
- *
- *	Returns a valid HeapTuple if it satisfies the timequal and keytest.
- *	Returns NULL otherwise.  Used to be heap_satisifies (sic) which
- *	returned a boolean.  It now returns a tuple so that we can avoid doing two
- *	PageGetItem's per tuple.
- *
- *		Complete check of validity including LP_CTUP and keytest.
- *		This should perhaps be combined with valid somehow in the
- *		future.  (Also, additional rule tests/time range tests.)
- *
- *	on 8/21/92 mao says:  i rearranged the tests here to do keytest before
- *	SatisfiesTimeQual.	profiling indicated that even for vacuumed relations,
- *	time qual checking was more expensive than key testing.  time qual is
- *	least likely to fail, too.	we should really add the time qual test to
- *	the restriction and optimize it in the normal way.	this has interactions
- *	with joey's expensive function work.
- * ----------------
- */
-HeapTuple
-heap_tuple_satisfies(ItemId itemId,
-					 Relation relation,
-					 Buffer buffer,
-					 PageHeader disk_page,
-					 TimeQual qual,
-					 int nKeys,
-					 ScanKey key)
-{
-	HeapTuple	tuple,
-				result;
-	bool		res;
-	TransactionId old_tmin,
-				old_tmax;
-
-	if (!ItemIdIsUsed(itemId))
-		return NULL;
-
-	tuple = (HeapTuple) PageGetItem((Page) disk_page, itemId);
-
-	if (key != NULL)
-		res = heap_keytest(tuple, RelationGetTupleDescriptor(relation),
-						   nKeys, key);
-	else
-		res = TRUE;
-
-	result = (HeapTuple) NULL;
-	if (res)
-	{
-		if (relation->rd_rel->relkind == RELKIND_UNCATALOGED)
-		{
-			result = tuple;
-		}
-		else
-		{
-			old_tmin = tuple->t_tmin;
-			old_tmax = tuple->t_tmax;
-			res = HeapTupleSatisfiesTimeQual(tuple, qual);
-			if (tuple->t_tmin != old_tmin ||
-				tuple->t_tmax != old_tmax)
-			{
-				SetBufferCommitInfoNeedsSave(buffer);
-			}
-			if (res)
-			{
-				result = tuple;
-			}
-		}
-	}
-
-	return result;
-}
 
 /*
  *	TupleUpdatedByCurXactAndCmd() -- Returns true if this tuple has
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 19bdf5b34c..2537e7e777 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.19 1997/09/08 21:40:57 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.20 1997/09/18 14:19:30 momjian Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -429,8 +429,9 @@ heapgettup(Relation relation,
 			 *	if current tuple qualifies, return it.
 			 * ----------------
 			 */
-			if ((rtup = heap_tuple_satisfies(lpp, relation, *b, (PageHeader) dp,
-										  timeQual, nkeys, key)) != NULL)
+			HeapTupleSatisfies(lpp, relation, *b, (PageHeader) dp,
+							   timeQual, nkeys, key, rtup);
+			if (rtup != NULL)
 			{
 				ItemPointer iptr = &(rtup->t_ctid);
 
@@ -1092,8 +1093,8 @@ heap_fetch(Relation relation,
 	 * ----------------
 	 */
 
-	tuple = heap_tuple_satisfies(lp, relation, buffer, dp,
-								 timeQual, 0, (ScanKey) NULL);
+	HeapTupleSatisfies(lp, relation, buffer, dp,
+					   timeQual, 0, (ScanKey) NULL, tuple);
 
 	if (tuple == NULL)
 	{
@@ -1257,8 +1258,9 @@ heap_delete(Relation relation, ItemPointer tid)
 	 *	check that we're deleteing a valid item
 	 * ----------------
 	 */
-	if (!(tp = heap_tuple_satisfies(lp, relation, b, dp,
-									NowTimeQual, 0, (ScanKey) NULL)))
+	HeapTupleSatisfies(lp, relation, b, dp,
+					   NowTimeQual, 0, (ScanKey) NULL, tp);
+	if (!tp)
 	{
 
 		/* XXX call something else */
@@ -1317,7 +1319,8 @@ heap_replace(Relation relation, ItemPointer otid, HeapTuple tup)
 	HeapTuple	tp;
 	Page		dp;
 	Buffer		buffer;
-
+	HeapTuple	tuple;
+	
 	/* ----------------
 	 *	increment access statistics
 	 * ----------------
@@ -1388,13 +1391,15 @@ heap_replace(Relation relation, ItemPointer otid, HeapTuple tup)
 	 *		 xact, we only want to flag the 'non-functional' NOTICE. -mer
 	 * ----------------
 	 */
-	if (!heap_tuple_satisfies(lp,
-							  relation,
-							  buffer,
-							  (PageHeader) dp,
-							  NowTimeQual,
-							  0,
-							  (ScanKey) NULL))
+	HeapTupleSatisfies(lp,
+						 relation,
+						 buffer,
+						 (PageHeader) dp,
+						 NowTimeQual,
+						 0,
+						 (ScanKey) NULL,
+						 tuple);
+	if (!tuple)
 	{
 		ReleaseBuffer(buffer);
 		elog(WARN, "heap_replace: (am)invalid otid");
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 58d93a0799..5aa70f52cb 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -792,8 +792,9 @@ GetTupleForTrigger(Relation relation, ItemPointer tid, bool before)
 			return (NULL);
 		}
 
-		if (!(tuple = heap_tuple_satisfies(lp, relation, b, dp,
-										NowTimeQual, 0, (ScanKey) NULL)))
+		HeapTupleSatisfies(lp, relation, b, dp,
+						   NowTimeQual, 0, (ScanKey) NULL, tuple);
+		if (!tuple)
 		{
 			ReleaseBuffer(b);
 			elog(WARN, "GetTupleForTrigger: (am)invalid tid");
diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c
index a0f45eca09..9b2f7a237c 100644
--- a/src/backend/storage/buffer/buf_init.c
+++ b/src/backend/storage/buffer/buf_init.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.12 1997/09/08 02:28:27 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.13 1997/09/18 14:19:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,6 +26,7 @@
 
 #include "storage/fd.h"
 #include "storage/ipc.h"
+#include "storage/s_lock.h"
 #include "storage/shmem.h"
 #include "storage/spin.h"
 #include "storage/smgr.h"
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 7acc70342c..0fc48c2052 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.23 1997/09/08 21:46:50 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.24 1997/09/18 14:20:00 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -56,6 +56,7 @@
 
 #include "storage/fd.h"
 #include "storage/ipc.h"
+#include "storage/s_lock.h"
 #include "storage/shmem.h"
 #include "storage/spin.h"
 #include "storage/smgr.h"
diff --git a/src/backend/storage/ipc/Makefile b/src/backend/storage/ipc/Makefile
index 821bf688cf..e5517135d3 100644
--- a/src/backend/storage/ipc/Makefile
+++ b/src/backend/storage/ipc/Makefile
@@ -4,7 +4,7 @@
 #    Makefile for storage/ipc
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/storage/ipc/Makefile,v 1.3 1996/11/09 06:21:47 momjian Exp $
+#    $Header: /cvsroot/pgsql/src/backend/storage/ipc/Makefile,v 1.4 1997/09/18 14:20:08 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -17,7 +17,7 @@ INCLUDE_OPT = -I../.. \
 
 CFLAGS+=$(INCLUDE_OPT)
 
-OBJS = ipc.o ipci.o s_lock.o shmem.o shmqueue.o sinval.o \
+OBJS = ipc.o ipci.o shmem.o shmqueue.o sinval.o \
        sinvaladt.o spin.o
 
 all: SUBSYS.o
diff --git a/src/backend/storage/ipc/ipc.c b/src/backend/storage/ipc/ipc.c
index 856ca13508..2ef50c5c91 100644
--- a/src/backend/storage/ipc/ipc.c
+++ b/src/backend/storage/ipc/ipc.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.14 1997/09/08 21:46:59 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.15 1997/09/18 14:20:14 momjian Exp $
  *
  * NOTES
  *
@@ -33,6 +33,7 @@
 
 #include "postgres.h"
 #include "storage/ipc.h"
+#include "storage/s_lock.h"
 /* In Ultrix, sem.h and shm.h must be included AFTER ipc.h */
 #include <sys/sem.h>
 #include <sys/shm.h>
@@ -615,7 +616,10 @@ IpcMemoryKill(IpcMemoryKey memKey)
  *	supply of locks.
  * ------------------
  */
-static SLock *SLockArray = NULL;
+
+/* used in spin.c */
+SLock *SLockArray = NULL;
+
 static SLock **FreeSLockPP;
 static int *UnusedSLockIP;
 static slock_t *SLockMemoryLock;
@@ -676,92 +680,13 @@ AttachSLockMemory(IPCKey key)
 	return;
 }
 
-
-#ifdef LOCKDEBUG
-#define PRINT_LOCK(LOCK) printf("(locklock = %d, flag = %d, nshlocks = %d, \
-shlock = %d, exlock =%d)\n", LOCK->locklock, \
-								LOCK->flag, LOCK->nshlocks, LOCK->shlock, \
-								LOCK->exlock)
-#endif
-
-void
-ExclusiveLock(int lockid)
-{
-	SLock	   *slckP;
-
-	slckP = &(SLockArray[lockid]);
-#ifdef LOCKDEBUG
-	printf("ExclusiveLock(%d)\n", lockid);
-	printf("IN: ");
-	PRINT_LOCK(slckP);
-#endif
-ex_try_again:
-	S_LOCK(&(slckP->locklock));
-	switch (slckP->flag)
-	{
-		case NOLOCK:
-			slckP->flag = EXCLUSIVELOCK;
-			S_LOCK(&(slckP->exlock));
-			S_LOCK(&(slckP->shlock));
-			S_UNLOCK(&(slckP->locklock));
-#ifdef LOCKDEBUG
-			printf("OUT: ");
-			PRINT_LOCK(slckP);
-#endif
-			return;
-		case SHAREDLOCK:
-		case EXCLUSIVELOCK:
-			S_UNLOCK(&(slckP->locklock));
-			S_LOCK(&(slckP->exlock));
-			S_UNLOCK(&(slckP->exlock));
-			goto ex_try_again;
-	}
-}
-
-void
-ExclusiveUnlock(int lockid)
-{
-	SLock	   *slckP;
-
-	slckP = &(SLockArray[lockid]);
-#ifdef LOCKDEBUG
-	printf("ExclusiveUnlock(%d)\n", lockid);
-	printf("IN: ");
-	PRINT_LOCK(slckP);
-#endif
-	S_LOCK(&(slckP->locklock));
-	/* -------------
-	 *	give favor to read processes
-	 * -------------
-	 */
-	slckP->flag = NOLOCK;
-	if (slckP->nshlocks > 0)
-	{
-		while (slckP->nshlocks > 0)
-		{
-			S_UNLOCK(&(slckP->shlock));
-			S_LOCK(&(slckP->comlock));
-		}
-		S_UNLOCK(&(slckP->shlock));
-	}
-	else
-	{
-		S_UNLOCK(&(slckP->shlock));
-	}
-	S_UNLOCK(&(slckP->exlock));
-	S_UNLOCK(&(slckP->locklock));
-#ifdef LOCKDEBUG
-	printf("OUT: ");
-	PRINT_LOCK(slckP);
-#endif
-	return;
-}
-
+#ifdef NOT_USED
 bool
 LockIsFree(int lockid)
 {
 	return (SLockArray[lockid].flag == NOLOCK);
 }
+#endif
 
 #endif							/* HAS_TEST_AND_SET */
 
diff --git a/src/backend/storage/ipc/s_lock.c b/src/backend/storage/ipc/s_lock.c
deleted file mode 100644
index 82551f8b96..0000000000
--- a/src/backend/storage/ipc/s_lock.c
+++ /dev/null
@@ -1,525 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * s_lock.c--
- *	   This file contains the implementation (if any) for spinlocks.
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/s_lock.c,v 1.24 1997/09/08 21:47:04 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-/*
- *	 DESCRIPTION
- *		The following code fragment should be written (in assembly
- *		language) on machines that have a native test-and-set instruction:
- *
- *		void
- *		S_LOCK(char_address)
- *			char *char_address;
- *		{
- *			while (test_and_set(char_address))
- *				;
- *		}
- *
- *		If this is not done, POSTGRES will default to using System V
- *		semaphores (and take a large performance hit -- around 40% of
- *		its time on a DS5000/240 is spent in semop(3)...).
- *
- *	 NOTES
- *		AIX has a test-and-set but the recommended interface is the cs(3)
- *		system call.  This provides an 8-instruction (plus system call
- *		overhead) uninterruptible compare-and-set operation.  True
- *		spinlocks might be faster but using cs(3) still speeds up the
- *		regression test suite by about 25%.  I don't have an assembler
- *		manual for POWER in any case.
- *
- */
-#include "postgres.h"
-
-#include "storage/ipc.h"
-
-
-#if defined(HAS_TEST_AND_SET)
-
-#if defined (nextstep)
-/*
- * NEXTSTEP (mach)
- * slock_t is defined as a struct mutex.
- */
-void
-S_LOCK(slock_t *lock)
-{
-	mutex_lock(lock);
-}
-void
-S_UNLOCK(slock_t *lock)
-{
-	mutex_unlock(lock);
-}
-void
-S_INIT_LOCK(slock_t *lock)
-{
-	mutex_init(lock);
-}
-
- /* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */
-int
-S_LOCK_FREE(slock_t *lock)
-{
-/* For Mach, we have to delve inside the entrails of `struct mutex'.  Ick! */
-	return (lock->lock == 0);
-}
-
-#endif							/* next */
-
-
-
-#if defined(irix5)
-/*
- * SGI IRIX 5
- * slock_t is defined as a struct abilock_t, which has a single unsigned long
- * member.
- *
- * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
- * assembly from his NECEWS SVR4 port, but we probably ought to retain this
- * for the R3000 chips out there.
- */
-void
-S_LOCK(slock_t *lock)
-{
-	/* spin_lock(lock); */
-	while (!acquire_lock(lock))
-		;
-}
-
-void
-S_UNLOCK(slock_t *lock)
-{
-	release_lock(lock);
-}
-
-void
-S_INIT_LOCK(slock_t *lock)
-{
-	init_lock(lock);
-}
-
-/* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */
-int
-S_LOCK_FREE(slock_t *lock)
-{
-	return (stat_lock(lock) == UNLOCKED);
-}
-
-#endif							/* irix5 */
-
-
-/*
- * OSF/1 (Alpha AXP)
- *
- * Note that slock_t on the Alpha AXP is msemaphore instead of char
- * (see storage/ipc.h).
- */
-
-#if defined(__alpha__) || defined(__alpha)
-
-void
-S_LOCK(slock_t *lock)
-{
-	while (msem_lock(lock, MSEM_IF_NOWAIT) < 0)
-		;
-}
-
-void
-S_UNLOCK(slock_t *lock)
-{
-	msem_unlock(lock, 0);
-}
-
-void
-S_INIT_LOCK(slock_t *lock)
-{
-	msem_init(lock, MSEM_UNLOCKED);
-}
-
-int
-S_LOCK_FREE(slock_t *lock)
-{
-	return (lock->msem_state ? 0 : 1);
-}
-
-#endif							/* alpha */
-
-/*
- * Solaris 2
- */
-
-#if defined(i386_solaris) || \
-	defined(sparc_solaris)
-/* for xxxxx_solaris, this is defined in port/.../tas.s */
-
-static int	tas(slock_t *lock);
-
-void
-S_LOCK(slock_t *lock)
-{
-	while (tas(lock))
-		;
-}
-
-void
-S_UNLOCK(slock_t *lock)
-{
-	*lock = 0;
-}
-
-void
-S_INIT_LOCK(slock_t *lock)
-{
-	S_UNLOCK(lock);
-}
-
-#endif							/* i86pc_solaris || sparc_solaris */
-
-/*
- * AIX (POWER)
- *
- * Note that slock_t on POWER/POWER2/PowerPC is int instead of char
- * (see storage/ipc.h).
- */
-
-#if defined(aix)
-
-void
-S_LOCK(slock_t *lock)
-{
-	while (cs((int *) lock, 0, 1))
-		;
-}
-
-void
-S_UNLOCK(slock_t *lock)
-{
-	*lock = 0;
-}
-
-void
-S_INIT_LOCK(slock_t *lock)
-{
-	S_UNLOCK(lock);
-}
-
-#endif							/* aix */
-
-/*
- * HP-UX (PA-RISC)
- *
- * Note that slock_t on PA-RISC is a structure instead of char
- * (see storage/ipc.h).
- */
-
-#if defined(hpux)
-
-/*
-* a "set" slock_t has a single word cleared.  a "clear" slock_t has
-* all words set to non-zero.
-*/
-static slock_t clear_lock = {-1, -1, -1, -1};
-
-static int	tas(slock_t *lock);
-
-void
-S_LOCK(slock_t *lock)
-{
-	while (tas(lock))
-		;
-}
-
-void
-S_UNLOCK(slock_t *lock)
-{
-	*lock = clear_lock;			/* struct assignment */
-}
-
-void
-S_INIT_LOCK(slock_t *lock)
-{
-	S_UNLOCK(lock);
-}
-
-int
-S_LOCK_FREE(slock_t *lock)
-{
-	register int *lock_word = (int *) (((long) lock + 15) & ~15);
-
-	return (*lock_word != 0);
-}
-
-#endif							/* hpux */
-
-/*
- * sun3
- */
-
-#if defined(sun3)
-
-static int	tas(slock_t *lock);
-
-void
-S_LOCK(slock_t *lock)
-{
-	while (tas(lock));
-}
-
-void
-S_UNLOCK(slock_t *lock)
-{
-	*lock = 0;
-}
-
-void
-S_INIT_LOCK(slock_t *lock)
-{
-	S_UNLOCK(lock);
-}
-
-static int
-tas_dummy()
-{
-	asm("LLA0:");
-	asm("	.data");
-	asm("	.text");
-	asm("|#PROC# 04");
-	asm("	.globl	_tas");
-	asm("_tas:");
-	asm("|#PROLOGUE# 1");
-	asm("	movel   sp@(0x4),a0");
-	asm("	tas	a0@");
-	asm("	beq	LLA1");
-	asm("	moveq   #-128,d0");
-	asm("	rts");
-	asm("LLA1:");
-	asm("	moveq   #0,d0");
-	asm("	rts");
-	asm("	.data");
-}
-
-#endif							/* sun3 */
-
-/*
- * sparc machines
- */
-
-#if defined(NEED_SPARC_TAS_ASM)
-
-/* if we're using -ansi w/ gcc, use __asm__ instead of asm */
-#if defined(__STRICT_ANSI__)
-#define asm(x)	__asm__(x)
-#endif
-
-static int	tas(slock_t *lock);
-
-static int
-tas_dummy()
-{
-	asm(".seg \"data\"");
-	asm(".seg \"text\"");
-	asm(".global _tas");
-	asm("_tas:");
-
-	/*
-	 * Sparc atomic test and set (sparc calls it "atomic load-store")
-	 */
-
-	asm("ldstub [%r8], %r8");
-
-	/*
-	 * Did test and set actually do the set?
-	 */
-
-	asm("tst %r8");
-
-	asm("be,a ReturnZero");
-
-	/*
-	 * otherwise, just return.
-	 */
-
-	asm("clr %r8");
-	asm("mov 0x1, %r8");
-	asm("ReturnZero:");
-	asm("retl");
-	asm("nop");
-}
-
-void
-S_LOCK(unsigned char *addr)
-{
-	while (tas(addr));
-}
-
-
-/*
- * addr should be as in the above S_LOCK routine
- */
-void
-S_UNLOCK(unsigned char *addr)
-{
-	*addr = 0;
-}
-
-void
-S_INIT_LOCK(unsigned char *addr)
-{
-	*addr = 0;
-}
-
-#endif							/* NEED_SPARC_TAS_ASM */
-
-/*
- * i386 based things
- */
-
-#if defined(NEED_I386_TAS_ASM)
-
-void
-S_LOCK(slock_t *lock)
-{
-	slock_t		res;
-
-	do
-	{
-__asm__("xchgb %0,%1": "=q"(res), "=m"(*lock):"0"(0x1));
-	} while (res != 0);
-}
-
-void
-S_UNLOCK(slock_t *lock)
-{
-	*lock = 0;
-}
-
-void
-S_INIT_LOCK(slock_t *lock)
-{
-	S_UNLOCK(lock);
-}
-
-#endif							/* NEED_I386_TAS_ASM */
-
-
-#if defined(__alpha__) && defined(linux)
-
-void
-S_LOCK(slock_t *lock)
-{
-	slock_t		res;
-
-	do
-	{
-__asm__("    ldq   $0, %0	     \n\
-		     bne   $0, already_set   \n\
-		     ldq_l $0, %0	     \n\
-		     bne   $0, already_set   \n\
-		     or    $31, 1, $0	     \n\
-		     stq_c $0, %0	     \n\
-		     beq   $0, stqc_fail     \n\
-	success:     bis   $31, $31, %1      \n\
-		     mb		             \n\
-		     jmp   $31, end	     \n\
-	stqc_fail:   or    $31, 1, $0	     \n\
-	already_set: bis   $0, $0, %1	     \n\
-	end:	     nop      ": "=m"(*lock), "=r"(res): :"0");
-	} while (res != 0);
-}
-
-void
-S_UNLOCK(slock_t *lock)
-{
-	__asm__("mb");
-	*lock = 0;
-}
-
-void
-S_INIT_LOCK(slock_t *lock)
-{
-	S_UNLOCK(lock);
-}
-
-#endif							/* defined(__alpha__) && defined(linux) */
-
-#if defined(linux) && defined(sparc)
-
-void
-S_LOCK(slock_t *lock)
-{
-	slock_t		res;
-
-	do
-	{
-		__asm__("ldstub [%1], %0"
-:				"=&r"(res)
-:				"r"(lock));
-	} while (!res != 0);
-}
-
-void
-S_UNLOCK(slock_t *lock)
-{
-	*lock = 0;
-}
-
-void
-S_INIT_LOCK(slock_t *lock)
-{
-	S_UNLOCK(lock);
-}
-
-#endif							/* defined(linux) && defined(sparc) */
-
-#if defined(linux) && defined(PPC)
-
-static int
-tas_dummy()
-{
-	__asm__("	\n\
-tas:			\n\
-	lwarx	5,0,3	\n\
-	cmpwi	5,0	\n\
-	bne	fail	\n\
-	addi	5,5,1	\n\
-        stwcx.  5,0,3	\n\
-        beq	success	\n\
-fail:	li	3,1	\n\
-	blr		\n\
-success:		\n\
-	li 3,0		\n\
-        blr		\n\
-	");
-}
-
-void
-S_LOCK(slock_t *lock)
-{
-	while (tas(lock))
-		;
-}
-
-void
-S_UNLOCK(slock_t *lock)
-{
-	*lock = 0;
-}
-
-void
-S_INIT_LOCK(slock_t *lock)
-{
-	S_UNLOCK(lock);
-}
-
-#endif							/* defined(linux) && defined(PPC) */
-
-#endif							/* HAS_TEST_AND_SET */
diff --git a/src/backend/storage/ipc/spin.c b/src/backend/storage/ipc/spin.c
index 3443c2db95..5300e2ecd4 100644
--- a/src/backend/storage/ipc/spin.c
+++ b/src/backend/storage/ipc/spin.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.8 1997/09/08 02:29:02 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.9 1997/09/18 14:20:18 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,6 +27,7 @@
 #include <errno.h>
 #include "postgres.h"
 #include "storage/ipc.h"
+#include "storage/s_lock.h"
 #include "storage/shmem.h"
 #include "storage/spin.h"
 #include "storage/proc.h"
@@ -80,18 +81,91 @@ InitSpinLocks(int init, IPCKey key)
 	return (TRUE);
 }
 
+#ifdef LOCKDEBUG
+#define PRINT_LOCK(LOCK) printf("(locklock = %d, flag = %d, nshlocks = %d, \
+shlock = %d, exlock =%d)\n", LOCK->locklock, \
+								LOCK->flag, LOCK->nshlocks, LOCK->shlock, \
+								LOCK->exlock)
+#endif
+
+/* from ipc.c */
+extern SLock *SLockArray;
+
 void
-SpinAcquire(SPINLOCK lock)
+SpinAcquire(SPINLOCK lockid)
 {
-	ExclusiveLock(lock);
-	PROC_INCR_SLOCK(lock);
+	SLock	   *slckP;
+
+	/* This used to be in ipc.c, but move here to reduce function calls */
+	slckP = &(SLockArray[lockid]);
+#ifdef LOCKDEBUG
+	printf("SpinAcquire(%d)\n", lockid);
+	printf("IN: ");
+	PRINT_LOCK(slckP);
+#endif
+ex_try_again:
+	S_LOCK(&(slckP->locklock));
+	switch (slckP->flag)
+	{
+		case NOLOCK:
+			slckP->flag = EXCLUSIVELOCK;
+			S_LOCK(&(slckP->exlock));
+			S_LOCK(&(slckP->shlock));
+			S_UNLOCK(&(slckP->locklock));
+#ifdef LOCKDEBUG
+			printf("OUT: ");
+			PRINT_LOCK(slckP);
+#endif
+			return;
+		case SHAREDLOCK:
+		case EXCLUSIVELOCK:
+			S_UNLOCK(&(slckP->locklock));
+			S_LOCK(&(slckP->exlock));
+			S_UNLOCK(&(slckP->exlock));
+			goto ex_try_again;
+	}
+	PROC_INCR_SLOCK(lockid);
 }
 
 void
-SpinRelease(SPINLOCK lock)
+SpinRelease(SPINLOCK lockid)
 {
-	PROC_DECR_SLOCK(lock);
-	ExclusiveUnlock(lock);
+	SLock	   *slckP;
+
+	PROC_DECR_SLOCK(lockid);
+
+	/* This used to be in ipc.c, but move here to reduce function calls */
+	slckP = &(SLockArray[lockid]);
+#ifdef LOCKDEBUG
+	printf("SpinRelease(%d)\n", lockid);
+	printf("IN: ");
+	PRINT_LOCK(slckP);
+#endif
+	S_LOCK(&(slckP->locklock));
+	/* -------------
+	 *	give favor to read processes
+	 * -------------
+	 */
+	slckP->flag = NOLOCK;
+	if (slckP->nshlocks > 0)
+	{
+		while (slckP->nshlocks > 0)
+		{
+			S_UNLOCK(&(slckP->shlock));
+			S_LOCK(&(slckP->comlock));
+		}
+		S_UNLOCK(&(slckP->shlock));
+	}
+	else
+	{
+		S_UNLOCK(&(slckP->shlock));
+	}
+	S_UNLOCK(&(slckP->exlock));
+	S_UNLOCK(&(slckP->locklock));
+#ifdef LOCKDEBUG
+	printf("OUT: ");
+	PRINT_LOCK(slckP);
+#endif
 }
 
 #else							/* HAS_TEST_AND_SET */
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index dc6b7bd466..c8abb92e46 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.14 1997/09/08 21:47:26 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.15 1997/09/18 14:20:22 momjian Exp $
  *
  * NOTES
  *	  Outside modules can create a lock table and acquire/release
@@ -51,7 +51,7 @@
 static int
 WaitOnLock(LOCKTAB *ltable, LockTableId tableId, LOCK *lock,
 		   LOCKT lockt);
-
+		   
 /*#define LOCK_MGR_DEBUG*/
 
 #ifndef LOCK_MGR_DEBUG
@@ -451,6 +451,7 @@ LockTabRename(LockTableId tableId)
  *														DZ - 4 Oct 1996
 #endif
  */
+
 bool
 LockAcquire(LockTableId tableId, LOCKTAG *lockName, LOCKT lockt)
 {
@@ -540,7 +541,7 @@ LockAcquire(LockTableId tableId, LOCKTAG *lockName, LOCKT lockt)
 	 * word alignment and ensures hashing consistency).
 	 * ------------------
 	 */
-	memset(&item, 0, XID_TAGSIZE);
+	memset(&item, 0, XID_TAGSIZE); /* must clear padding, needed */
 	TransactionIdStore(myXid, &item.tag.xid);
 	item.tag.lock = MAKE_OFFSET(lock);
 #if 0
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index c74565ddfa..f0d41a7116 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.14 1997/09/12 04:08:28 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.15 1997/09/18 14:20:29 momjian Exp $
  *
  * Notes:
  *		XXX This needs to use exception.h to handle recovery when
@@ -839,16 +839,20 @@ SearchSysCache(struct catcache * cache,
 		 elt;
 		 elt = DLGetSucc(elt))
 	{
+		bool res;
+		
 		ct = (CatCTup *) DLE_VAL(elt);
 		/* ----------------
 		 *	see if the cached tuple matches our key.
 		 *	(should we be worried about time ranges? -cim 10/2/90)
 		 * ----------------
 		 */
-		if (heap_keytest(ct->ct_tup,
+		HeapKeyTest(ct->ct_tup,
 						 cache->cc_tupdesc,
 						 cache->cc_nkeys,
-						 cache->cc_skey))
+						 cache->cc_skey,
+						 res);
+		if (res)
 			break;
 	}
 
diff --git a/src/include/access/valid.h b/src/include/access/valid.h
index 7b047d66d6..a37258c62a 100644
--- a/src/include/access/valid.h
+++ b/src/include/access/valid.h
@@ -6,31 +6,156 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: valid.h,v 1.7 1997/09/08 21:51:05 momjian Exp $
+ * $Id: valid.h,v 1.8 1997/09/18 14:20:45 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef VALID_H
 #define VALID_H
 
+#include <fmgr.h>
+#include <access/heapam.h>
+#include <access/valid.h>
 #include <utils/tqual.h>
+#include <storage/bufmgr.h>
 #include <storage/bufpage.h>
 #include <utils/rel.h>
+#include <utils/builtins.h>
 
 /* ----------------
  *		extern decl's
  * ----------------
  */
 
-extern bool
-heap_keytest(HeapTuple t, TupleDesc tupdesc,
-			 int nkeys, ScanKey keys);
+/* ----------------
+ *		HeapKeyTest
+ *
+ *		Test a heap tuple with respect to a scan key.
+ * ----------------
+ */
 
-extern HeapTuple
-heap_tuple_satisfies(ItemId itemId, Relation relation,
-					 Buffer buffer, PageHeader disk_page,
-					 TimeQual qual, int nKeys,
-					 ScanKey key);
+#define HeapKeyTest(tuple, \
+					tupdesc, \
+					nkeys, \
+					keys, \
+					result) \
+do \
+{ \
+/* We use underscores to protect the variable passed in as parameters */ \
+/* We use two underscore here because this macro is included in the \
+   macro below */ \
+	bool		__isnull; \
+	Datum		__atp; \
+	int			__test; \
+	int			__cur_nkeys = (nkeys); \
+	ScanKey		__cur_keys = (keys); \
+ \
+	(result) = true; /* may change */ \
+	for (; __cur_nkeys--; __cur_keys++) \
+	{ \
+		__atp = heap_getattr((tuple), InvalidBuffer, \
+						   __cur_keys->sk_attno, \
+						   (tupdesc), \
+						   &__isnull); \
+ \
+		if (__isnull) \
+		{ \
+			/* XXX eventually should check if SK_ISNULL */ \
+			(result) = false; \
+			break; \
+		} \
+ \
+		if (__cur_keys->sk_flags & SK_ISNULL) \
+		{ \
+			(result) = false; \
+			break; \
+		} \
+ \
+		if (__cur_keys->sk_func == (func_ptr) oideq)	/* optimization */ \
+			__test = (__cur_keys->sk_argument == __atp); \
+		else if (__cur_keys->sk_flags & SK_COMMUTE) \
+			__test = (long) FMGR_PTR2(__cur_keys->sk_func, __cur_keys->sk_procedure, \
+									__cur_keys->sk_argument, __atp); \
+		else \
+			__test = (long) FMGR_PTR2(__cur_keys->sk_func, __cur_keys->sk_procedure, \
+									__atp, __cur_keys->sk_argument); \
+ \
+		if (!__test == !(__cur_keys->sk_flags & SK_NEGATE)) \
+		{ \
+			/* XXX eventually should check if SK_ISNULL */ \
+			(result) = false; \
+			break; \
+		} \
+	} \
+} while (0)
+
+/* ----------------
+ *		HeapTupleSatisfies
+ *
+ *	Returns a valid HeapTuple if it satisfies the timequal and keytest.
+ *	Returns NULL otherwise.  Used to be heap_satisifies (sic) which
+ *	returned a boolean.  It now returns a tuple so that we can avoid doing two
+ *	PageGetItem's per tuple.
+ *
+ *		Complete check of validity including LP_CTUP and keytest.
+ *		This should perhaps be combined with valid somehow in the
+ *		future.  (Also, additional rule tests/time range tests.)
+ *
+ *	on 8/21/92 mao says:  i rearranged the tests here to do keytest before
+ *	SatisfiesTimeQual.	profiling indicated that even for vacuumed relations,
+ *	time qual checking was more expensive than key testing.  time qual is
+ *	least likely to fail, too.	we should really add the time qual test to
+ *	the restriction and optimize it in the normal way.	this has interactions
+ *	with joey's expensive function work.
+ * ----------------
+ */
+#define HeapTupleSatisfies(itemId, \
+						   relation, \
+						   buffer, \
+						   disk_page, \
+						   qual, \
+						   nKeys, \
+						   key, \
+						   result) \
+do \
+{ \
+/* We use underscores to protect the variable passed in as parameters */ \
+	HeapTuple	_tuple; \
+	bool		_res; \
+	TransactionId _old_tmin, \
+				_old_tmax; \
+ \
+	if (!ItemIdIsUsed(itemId)) \
+		(result) = (HeapTuple) NULL; \
+	else \
+	{ \
+		_tuple = (HeapTuple) PageGetItem((Page) (disk_page), (itemId)); \
+	 \
+		if ((key) != NULL) \
+			HeapKeyTest(_tuple, RelationGetTupleDescriptor(relation), \
+							   (nKeys), (key), _res); \
+		else \
+			_res = TRUE; \
+ \
+		(result) = (HeapTuple) NULL; \
+		if (_res) \
+		{ \
+			if ((relation)->rd_rel->relkind == RELKIND_UNCATALOGED) \
+				(result) = _tuple; \
+			else \
+			{ \
+				_old_tmin = _tuple->t_tmin; \
+				_old_tmax = _tuple->t_tmax; \
+				_res = HeapTupleSatisfiesTimeQual(_tuple, (qual)); \
+				if (_tuple->t_tmin != _old_tmin || \
+					_tuple->t_tmax != _old_tmax) \
+					SetBufferCommitInfoNeedsSave(buffer); \
+				if (_res) \
+					(result) = _tuple; \
+			} \
+		} \
+	} \
+} while (0)
 
 extern bool TupleUpdatedByCurXactAndCmd(HeapTuple t);
 
diff --git a/src/include/c.h b/src/include/c.h
index 05c3cc5e92..b247b2e8fa 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: c.h,v 1.19 1997/09/08 21:50:24 momjian Exp $
+ * $Id: c.h,v 1.20 1997/09/18 14:20:40 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -692,6 +692,27 @@ typedef struct Exception
 /* we do this so if the macro is used in an if action, it will work */
 #define strNcpy(dst,src,len)	(strncpy((dst),(src),(len)),*((dst)+(len))='\0')
 
+/* Get a bit mask of the bits set in non-int32 aligned addresses */
+#define INT_ALIGN_MASK (sizeof(int32) - 1)
+
+/* This function gets call too often, so we inline it if we can */
+#define MemSet(start, val, len)	do \
+								{   /* are we aligned for int32? */ \
+									if (((start) & INT_ALIGN_MASK) == 0 && \
+										((len) & INT_ALIGN_MASK) == 0 && \
+										(val) == 0 && \
+										(len) <= 256) \
+									{ \
+										int32 *i = (int32 *)(start); \
+										int32 *stop = (int32 *)((char *)(start) + (len)); \
+										\
+										while (i < stop) \
+											*i++ = 0; \
+									} \
+									else \
+										memset((start), (val), (len)); \
+								}
+
 /* ----------------------------------------------------------------
  *				Section 9: externs
  * ----------------------------------------------------------------
diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h
index b62387b668..1e95f66927 100644
--- a/src/include/storage/ipc.h
+++ b/src/include/storage/ipc.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: ipc.h,v 1.20 1997/09/08 21:54:21 momjian Exp $
+ * $Id: ipc.h,v 1.21 1997/09/18 14:20:54 momjian Exp $
  *
  * NOTES
  *	  This file is very architecture-specific.	This stuff should actually
@@ -28,10 +28,6 @@
 
 #if defined(HAS_TEST_AND_SET)
 
-extern void S_LOCK(slock_t *lock);
-extern void S_UNLOCK(slock_t *lock);
-extern void S_INIT_LOCK(slock_t *lock);
-
 #if (defined(alpha) && !defined(linuxalpha)) || \
 	defined(hpux) || \
 	defined(irix5) || \
@@ -150,10 +146,6 @@ typedef struct slock
 	struct slock *next;
 } SLock;
 
-extern void ExclusiveLock(int lockid);
-extern void ExclusiveUnlock(int lockid);
-extern bool LockIsFree(int lockid);
-
 #else							/* HAS_TEST_AND_SET */
 
 typedef enum _LockId_
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
new file mode 100644
index 0000000000..3bc0af34e5
--- /dev/null
+++ b/src/include/storage/s_lock.h
@@ -0,0 +1,808 @@
+/*-------------------------------------------------------------------------
+ *
+ * s_lock.h--
+ *	   This file contains the implementation (if any) for spinlocks.
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/include/storage/s_lock.h,v 1.1 1997/09/18 14:20:59 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+/*
+ *	 DESCRIPTION
+ *		The following code fragment should be written (in assembly
+ *		language) on machines that have a native test-and-set instruction:
+ *
+ *		void
+ *		S_LOCK(char_address)
+ *			char *char_address;
+ *		{
+ *			while (test_and_set(char_address))
+ *				;
+ *		}
+ *
+ *		If this is not done, POSTGRES will default to using System V
+ *		semaphores (and take a large performance hit -- around 40% of
+ *		its time on a DS5000/240 is spent in semop(3)...).
+ *
+ *	 NOTES
+ *		AIX has a test-and-set but the recommended interface is the cs(3)
+ *		system call.  This provides an 8-instruction (plus system call
+ *		overhead) uninterruptible compare-and-set operation.  True
+ *		spinlocks might be faster but using cs(3) still speeds up the
+ *		regression test suite by about 25%.  I don't have an assembler
+ *		manual for POWER in any case.
+ *
+ */
+#ifndef S_LOCK_H
+#define S_LOCK_H
+
+#include "storage/ipc.h"
+
+#if defined(HAS_TEST_AND_SET)
+
+#if defined (nextstep)
+/*
+ * NEXTSTEP (mach)
+ * slock_t is defined as a struct mutex.
+ */
+#define	S_LOCK(lock)	mutex_lock(lock)
+
+#define	S_UNLOCK(lock)	mutex_unlock(lock)
+
+#define	S_INIT_LOCK(lock)	mutex_init(lock)
+
+ /* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */
+/* For Mach, we have to delve inside the entrails of `struct mutex'.  Ick! */
+#define	S_LOCK_FREE(alock)	((alock)->lock == 0)
+
+#endif							/* next */
+
+
+
+#if defined(irix5)
+/*
+ * SGI IRIX 5
+ * slock_t is defined as a struct abilock_t, which has a single unsigned long
+ * member.
+ *
+ * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
+ * assembly from his NECEWS SVR4 port, but we probably ought to retain this
+ * for the R3000 chips out there.
+ */
+#define	S_LOCK(lock)	do \
+						{ \
+							while (!acquire_lock(lock)) \
+								; \
+						} while (0)
+
+#define S_UNLOCK(lock)	release_lock(lock)
+
+#define	S_INIT_LOCK(lock)	init_lock(lock)
+
+/* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */
+
+#define	S_LOCK_FREE(lock)	(stat_lock(lock) == UNLOCKED)
+
+#endif							/* irix5 */
+
+
+/*
+ * OSF/1 (Alpha AXP)
+ *
+ * Note that slock_t on the Alpha AXP is msemaphore instead of char
+ * (see storage/ipc.h).
+ */
+
+#if defined(__alpha__) || defined(__alpha)
+
+#define	S_LOCK(lock)	do \
+						{ \
+							while (msem_lock((lock), MSEM_IF_NOWAIT) < 0) \
+								; \
+						} while (0)
+
+#define	S_UNLOCK(lock)	msem_unlock((lock), 0)
+
+#define	S_INIT_LOCK(lock)	msem_init((lock), MSEM_UNLOCKED)
+
+#define	S_LOCK_FREE(lock)	(!(lock)->msem_state)
+
+#endif							/* alpha */
+
+/*
+ * Solaris 2
+ */
+
+#if defined(i386_solaris) || \
+	defined(sparc_solaris)
+/* for xxxxx_solaris, this is defined in port/.../tas.s */
+
+static int	tas(slock_t *lock);
+
+#define	S_LOCK(lock)	do \
+						{ \
+							while (tas(lock)) \
+								; \
+						} while (0)
+
+#define	S_UNLOCK(lock)	(*(lock) = 0)
+
+#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
+
+#endif							/* i86pc_solaris || sparc_solaris */
+
+/*
+ * AIX (POWER)
+ *
+ * Note that slock_t on POWER/POWER2/PowerPC is int instead of char
+ * (see storage/ipc.h).
+ */
+
+#if defined(aix)
+
+#define	S_LOCK(lock)	do \
+						{ \
+							while (cs((int *) (lock), 0, 1)) \ 
+								; \
+						} while (0)
+
+#define	S_UNLOCK(lock)	(*(lock) = 0)
+
+#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
+
+#endif							/* aix */
+
+/*
+ * HP-UX (PA-RISC)
+ *
+ * Note that slock_t on PA-RISC is a structure instead of char
+ * (see storage/ipc.h).
+ */
+
+#if defined(hpux)
+
+/*
+* a "set" slock_t has a single word cleared.  a "clear" slock_t has
+* all words set to non-zero.
+*/
+static slock_t clear_lock = {-1, -1, -1, -1};
+
+static int	tas(slock_t *lock);
+
+#define	S_LOCK(lock)	do \
+						{ \
+							while (tas(lock)) \
+								; \
+						} while (0)
+
+#define	S_UNLOCK(lock)	(*(lock) = clear_lock)			/* struct assignment */
+
+#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
+
+#define	S_LOCK_FREE(lock)	( *(int *) (((long) (lock) + 15) & ~15) != 0)
+
+#endif							/* hpux */
+
+/*
+ * sun3
+ */
+
+#if defined(sun3)
+
+static int	tas(slock_t *lock);
+
+#define S_LOCK(lock)	do \
+						{ \
+							while (tas(lock)) \
+								; \
+						} while (0)
+
+#define	S_UNLOCK(lock)	(*(lock) = 0)
+
+#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
+
+#ifdef NOT_USED
+static int
+tas_dummy()
+{
+	asm("LLA0:");
+	asm("	.data");
+	asm("	.text");
+	asm("|#PROC# 04");
+	asm("	.globl	_tas");
+	asm("_tas:");
+	asm("|#PROLOGUE# 1");
+	asm("	movel   sp@(0x4),a0");
+	asm("	tas	a0@");
+	asm("	beq	LLA1");
+	asm("	moveq   #-128,d0");
+	asm("	rts");
+	asm("LLA1:");
+	asm("	moveq   #0,d0");
+	asm("	rts");
+	asm("	.data");
+}
+#endif
+
+#endif							/* sun3 */
+
+/*
+ * sparc machines
+ */
+
+#if defined(NEED_SPARC_TAS_ASM)
+
+/* if we're using -ansi w/ gcc, use __asm__ instead of asm */
+#if defined(__STRICT_ANSI__)
+#define asm(x)	__asm__(x)
+#endif
+
+static int	tas(slock_t *lock);
+
+#ifdef NOT_USED
+static int
+tas_dummy()
+{
+	asm(".seg \"data\"");
+	asm(".seg \"text\"");
+	asm(".global _tas");
+	asm("_tas:");
+
+	/*
+	 * Sparc atomic test and set (sparc calls it "atomic load-store")
+	 */
+
+	asm("ldstub [%r8], %r8");
+
+	/*
+	 * Did test and set actually do the set?
+	 */
+
+	asm("tst %r8");
+
+	asm("be,a ReturnZero");
+
+	/*
+	 * otherwise, just return.
+	 */
+
+	asm("clr %r8");
+	asm("mov 0x1, %r8");
+	asm("ReturnZero:");
+	asm("retl");
+	asm("nop");
+}
+#endif
+
+#define	S_LOCK(addr)	do \
+						{ \
+							while (tas(addr)) \
+								; \
+						} while (0)
+
+/*
+ * addr should be as in the above S_LOCK routine
+ */
+#define	S_UNLOCK(addr)	(*(addr) = 0)
+
+#define	S_INIT_LOCK(addr)	(*(addr) = 0)
+
+#endif							/* NEED_SPARC_TAS_ASM */
+
+/*
+ * i386 based things
+ */
+
+#if defined(NEED_I386_TAS_ASM)
+
+#define	S_LOCK(lock)	do \
+						{ \
+							slock_t		res; \
+							do \
+							{ \
+				__asm__("xchgb %0,%1": "=q"(res), "=m"(*lock):"0"(0x1)); \
+							} while (res != 0); \
+						} while (0)
+
+#define	S_UNLOCK(lock)	(*(lock) = 0)
+
+#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
+
+#endif							/* NEED_I386_TAS_ASM */
+
+
+#if defined(__alpha__) && defined(linux)
+
+#define	S_LOCK(lock)	do \
+						{ \
+							slock_t		res; \
+							do \
+							{ \
+								__asm__("    ldq   $0, %0	     \n\
+							     bne   $0, already_set   \n\
+							     ldq_l $0, %0	     \n\
+							     bne   $0, already_set   \n\
+							     or    $31, 1, $0	     \n\
+							     stq_c $0, %0	     \n\
+							     beq   $0, stqc_fail     \n\
+					success:     bis   $31, $31, %1      \n\
+							     mb		             \n\
+							     jmp   $31, end	     \n\
+					stqc_fail:   or    $31, 1, $0	     \n\
+					already_set: bis   $0, $0, %1	     \n\
+					end:	     nop      ": "=m"(*lock), "=r"(res): :"0"); \
+							} while (res != 0); \
+						} while (0)
+
+						
+#define	S_UNLOCK(lock)	(__asm__("mb"),	*(lock) = 0)
+
+#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
+
+#endif							/* defined(__alpha__) && defined(linux) */
+
+#if defined(linux) && defined(sparc)
+
+#define S_LOCK(lock)	do \
+						{ \
+							slock_t		res; \
+							do \
+							{ \
+								__asm__("ldstub [%1], %0" \
+						:		"=&r"(res) \
+						:		"r"(lock)); \
+							} while (!res != 0); \
+						} while (0)
+
+#define	S_UNLOCK(lock)	(*(lock) = 0)
+
+#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
+
+#endif							/* defined(linux) && defined(sparc) */
+
+#if defined(linux) && defined(PPC)
+
+#ifdef NOT_USED
+static int
+tas_dummy()
+{
+	__asm__("	\n\
+tas:			\n\
+	lwarx	5,0,3	\n\
+	cmpwi	5,0	\n\
+	bne	fail	\n\
+	addi	5,5,1	\n\
+        stwcx.  5,0,3	\n\
+        beq	success	\n\
+fail:	li	3,1	\n\
+	blr		\n\
+success:		\n\
+	li 3,0		\n\
+        blr		\n\
+	");
+}
+#endif
+
+#define	S_LOCK(lock)	do \ 
+						{ \
+							while (tas(lock)) \
+								; \
+						} while (0)
+
+#define	S_UNLOCK(lock)	(*(lock) = 0)
+
+#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
+
+#endif							/* defined(linux) && defined(PPC) */
+
+#endif							/* HAS_TEST_AND_SET */
+
+#endif							/* S_LOCK_H */ 
+/*-------------------------------------------------------------------------
+ *
+ * s_lock.h--
+ *	   This file contains the implementation (if any) for spinlocks.
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/include/storage/s_lock.h,v 1.1 1997/09/18 14:20:59 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+/*
+ *	 DESCRIPTION
+ *		The following code fragment should be written (in assembly
+ *		language) on machines that have a native test-and-set instruction:
+ *
+ *		void
+ *		S_LOCK(char_address)
+ *			char *char_address;
+ *		{
+ *			while (test_and_set(char_address))
+ *				;
+ *		}
+ *
+ *		If this is not done, POSTGRES will default to using System V
+ *		semaphores (and take a large performance hit -- around 40% of
+ *		its time on a DS5000/240 is spent in semop(3)...).
+ *
+ *	 NOTES
+ *		AIX has a test-and-set but the recommended interface is the cs(3)
+ *		system call.  This provides an 8-instruction (plus system call
+ *		overhead) uninterruptible compare-and-set operation.  True
+ *		spinlocks might be faster but using cs(3) still speeds up the
+ *		regression test suite by about 25%.  I don't have an assembler
+ *		manual for POWER in any case.
+ *
+ */
+#ifndef S_LOCK_H
+#define S_LOCK_H
+
+#include "storage/ipc.h"
+
+#if defined(HAS_TEST_AND_SET)
+
+#if defined (nextstep)
+/*
+ * NEXTSTEP (mach)
+ * slock_t is defined as a struct mutex.
+ */
+#define	S_LOCK(lock)	mutex_lock(lock)
+
+#define	S_UNLOCK(lock)	mutex_unlock(lock)
+
+#define	S_INIT_LOCK(lock)	mutex_init(lock)
+
+ /* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */
+/* For Mach, we have to delve inside the entrails of `struct mutex'.  Ick! */
+#define	S_LOCK_FREE(alock)	((alock)->lock == 0)
+
+#endif							/* next */
+
+
+
+#if defined(irix5)
+/*
+ * SGI IRIX 5
+ * slock_t is defined as a struct abilock_t, which has a single unsigned long
+ * member.
+ *
+ * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
+ * assembly from his NECEWS SVR4 port, but we probably ought to retain this
+ * for the R3000 chips out there.
+ */
+#define	S_LOCK(lock)	do \
+						{ \
+							while (!acquire_lock(lock)) \
+								; \
+						} while (0)
+
+#define S_UNLOCK(lock)	release_lock(lock)
+
+#define	S_INIT_LOCK(lock)	init_lock(lock)
+
+/* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */
+
+#define	S_LOCK_FREE(lock)	(stat_lock(lock) == UNLOCKED)
+
+#endif							/* irix5 */
+
+
+/*
+ * OSF/1 (Alpha AXP)
+ *
+ * Note that slock_t on the Alpha AXP is msemaphore instead of char
+ * (see storage/ipc.h).
+ */
+
+#if defined(__alpha__) || defined(__alpha)
+
+#define	S_LOCK(lock)	do \
+						{ \
+							while (msem_lock((lock), MSEM_IF_NOWAIT) < 0) \
+								; \
+						} while (0)
+
+#define	S_UNLOCK(lock)	msem_unlock((lock), 0)
+
+#define	S_INIT_LOCK(lock)	msem_init((lock), MSEM_UNLOCKED)
+
+#define	S_LOCK_FREE(lock)	(!(lock)->msem_state)
+
+#endif							/* alpha */
+
+/*
+ * Solaris 2
+ */
+
+#if defined(i386_solaris) || \
+	defined(sparc_solaris)
+/* for xxxxx_solaris, this is defined in port/.../tas.s */
+
+static int	tas(slock_t *lock);
+
+#define	S_LOCK(lock)	do \
+						{ \
+							while (tas(lock)) \
+								; \
+						} while (0)
+
+#define	S_UNLOCK(lock)	(*(lock) = 0)
+
+#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
+
+#endif							/* i86pc_solaris || sparc_solaris */
+
+/*
+ * AIX (POWER)
+ *
+ * Note that slock_t on POWER/POWER2/PowerPC is int instead of char
+ * (see storage/ipc.h).
+ */
+
+#if defined(aix)
+
+#define	S_LOCK(lock)	do \
+						{ \
+							while (cs((int *) (lock), 0, 1)) \ 
+								; \
+						} while (0)
+
+#define	S_UNLOCK(lock)	(*(lock) = 0)
+
+#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
+
+#endif							/* aix */
+
+/*
+ * HP-UX (PA-RISC)
+ *
+ * Note that slock_t on PA-RISC is a structure instead of char
+ * (see storage/ipc.h).
+ */
+
+#if defined(hpux)
+
+/*
+* a "set" slock_t has a single word cleared.  a "clear" slock_t has
+* all words set to non-zero.
+*/
+static slock_t clear_lock = {-1, -1, -1, -1};
+
+static int	tas(slock_t *lock);
+
+#define	S_LOCK(lock)	do \
+						{ \
+							while (tas(lock)) \
+								; \
+						} while (0)
+
+#define	S_UNLOCK(lock)	(*(lock) = clear_lock)			/* struct assignment */
+
+#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
+
+#define	S_LOCK_FREE(lock)	( *(int *) (((long) (lock) + 15) & ~15) != 0)
+
+#endif							/* hpux */
+
+/*
+ * sun3
+ */
+
+#if defined(sun3)
+
+static int	tas(slock_t *lock);
+
+#define S_LOCK(lock)	do \
+						{ \
+							while (tas(lock)) \
+								; \
+						} while (0)
+
+#define	S_UNLOCK(lock)	(*(lock) = 0)
+
+#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
+
+#ifdef NOT_USED
+static int
+tas_dummy()
+{
+	asm("LLA0:");
+	asm("	.data");
+	asm("	.text");
+	asm("|#PROC# 04");
+	asm("	.globl	_tas");
+	asm("_tas:");
+	asm("|#PROLOGUE# 1");
+	asm("	movel   sp@(0x4),a0");
+	asm("	tas	a0@");
+	asm("	beq	LLA1");
+	asm("	moveq   #-128,d0");
+	asm("	rts");
+	asm("LLA1:");
+	asm("	moveq   #0,d0");
+	asm("	rts");
+	asm("	.data");
+}
+#endif
+
+#endif							/* sun3 */
+
+/*
+ * sparc machines
+ */
+
+#if defined(NEED_SPARC_TAS_ASM)
+
+/* if we're using -ansi w/ gcc, use __asm__ instead of asm */
+#if defined(__STRICT_ANSI__)
+#define asm(x)	__asm__(x)
+#endif
+
+static int	tas(slock_t *lock);
+
+#ifdef NOT_USED
+static int
+tas_dummy()
+{
+	asm(".seg \"data\"");
+	asm(".seg \"text\"");
+	asm(".global _tas");
+	asm("_tas:");
+
+	/*
+	 * Sparc atomic test and set (sparc calls it "atomic load-store")
+	 */
+
+	asm("ldstub [%r8], %r8");
+
+	/*
+	 * Did test and set actually do the set?
+	 */
+
+	asm("tst %r8");
+
+	asm("be,a ReturnZero");
+
+	/*
+	 * otherwise, just return.
+	 */
+
+	asm("clr %r8");
+	asm("mov 0x1, %r8");
+	asm("ReturnZero:");
+	asm("retl");
+	asm("nop");
+}
+#endif
+
+#define	S_LOCK(addr)	do \
+						{ \
+							while (tas(addr)) \
+								; \
+						} while (0)
+
+/*
+ * addr should be as in the above S_LOCK routine
+ */
+#define	S_UNLOCK(addr)	(*(addr) = 0)
+
+#define	S_INIT_LOCK(addr)	(*(addr) = 0)
+
+#endif							/* NEED_SPARC_TAS_ASM */
+
+/*
+ * i386 based things
+ */
+
+#if defined(NEED_I386_TAS_ASM)
+
+#define	S_LOCK(lock)	do \
+						{ \
+							slock_t		res; \
+							do \
+							{ \
+				__asm__("xchgb %0,%1": "=q"(res), "=m"(*lock):"0"(0x1)); \
+							} while (res != 0); \
+						} while (0)
+
+#define	S_UNLOCK(lock)	(*(lock) = 0)
+
+#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
+
+#endif							/* NEED_I386_TAS_ASM */
+
+
+#if defined(__alpha__) && defined(linux)
+
+#define	S_LOCK(lock)	do \
+						{ \
+							slock_t		res; \
+							do \
+							{ \
+								__asm__("    ldq   $0, %0	     \n\
+							     bne   $0, already_set   \n\
+							     ldq_l $0, %0	     \n\
+							     bne   $0, already_set   \n\
+							     or    $31, 1, $0	     \n\
+							     stq_c $0, %0	     \n\
+							     beq   $0, stqc_fail     \n\
+					success:     bis   $31, $31, %1      \n\
+							     mb		             \n\
+							     jmp   $31, end	     \n\
+					stqc_fail:   or    $31, 1, $0	     \n\
+					already_set: bis   $0, $0, %1	     \n\
+					end:	     nop      ": "=m"(*lock), "=r"(res): :"0"); \
+							} while (res != 0); \
+						} while (0)
+
+						
+#define	S_UNLOCK(lock)	(__asm__("mb"),	*(lock) = 0)
+
+#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
+
+#endif							/* defined(__alpha__) && defined(linux) */
+
+#if defined(linux) && defined(sparc)
+
+#define S_LOCK(lock)	do \
+						{ \
+							slock_t		res; \
+							do \
+							{ \
+								__asm__("ldstub [%1], %0" \
+						:		"=&r"(res) \
+						:		"r"(lock)); \
+							} while (!res != 0); \
+						} while (0)
+
+#define	S_UNLOCK(lock)	(*(lock) = 0)
+
+#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
+
+#endif							/* defined(linux) && defined(sparc) */
+
+#if defined(linux) && defined(PPC)
+
+#ifdef NOT_USED
+static int
+tas_dummy()
+{
+	__asm__("	\n\
+tas:			\n\
+	lwarx	5,0,3	\n\
+	cmpwi	5,0	\n\
+	bne	fail	\n\
+	addi	5,5,1	\n\
+        stwcx.  5,0,3	\n\
+        beq	success	\n\
+fail:	li	3,1	\n\
+	blr		\n\
+success:		\n\
+	li 3,0		\n\
+        blr		\n\
+	");
+}
+#endif
+
+#define	S_LOCK(lock)	do \ 
+						{ \
+							while (tas(lock)) \
+								; \
+						} while (0)
+
+#define	S_UNLOCK(lock)	(*(lock) = 0)
+
+#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
+
+#endif							/* defined(linux) && defined(PPC) */
+
+#endif							/* HAS_TEST_AND_SET */
+
+#endif							/* S_LOCK_H */ 
diff --git a/src/include/storage/spin.h b/src/include/storage/spin.h
index d41768039e..c94a74255f 100644
--- a/src/include/storage/spin.h
+++ b/src/include/storage/spin.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: spin.h,v 1.5 1997/09/08 02:39:14 momjian Exp $
+ * $Id: spin.h,v 1.6 1997/09/18 14:21:02 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -29,7 +29,7 @@ typedef int SPINLOCK;
 
 extern bool CreateSpinlocks(IPCKey key);
 extern bool InitSpinLocks(int init, IPCKey key);
-extern void SpinAcquire(SPINLOCK lock);
-extern void SpinRelease(SPINLOCK lock);
+extern void SpinAcquire(SPINLOCK lockid);
+extern void SpinRelease(SPINLOCK lockid);
 
 #endif							/* SPIN_H */