diff --git a/src/backend/storage/buffer/Makefile b/src/backend/storage/buffer/Makefile
index 20ac86ee2ecc437b93323ff0e3829ff5efbae391..1f0f4ab8fe61a66dfff485fe4c16b35aeddaf08c 100644
--- a/src/backend/storage/buffer/Makefile
+++ b/src/backend/storage/buffer/Makefile
@@ -4,7 +4,7 @@
 #    Makefile for storage/buffer
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/storage/buffer/Makefile,v 1.8 1998/04/29 12:37:51 scrappy Exp $
+#    $Header: /cvsroot/pgsql/src/backend/storage/buffer/Makefile,v 1.9 1998/05/04 15:44:39 scrappy Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -24,11 +24,11 @@ depend dep:
 	$(CC) -MM $(CFLAGS) *.c >depend
 
 clean: 
-	rm -f SUBSYS.o $(OBJS) tas_test
+	rm -f SUBSYS.o $(OBJS) s_lock_test
 
-tas_test: s_lock.c
-	$(CC) $(CFLAGS) -DTAS_TEST=1 -g s_lock.c -o tas_test
-	./tas_test
+s_lock_test: s_lock.c
+	$(CC) $(CFLAGS) -DS_LOCK_TEST=1 -g s_lock.c -o s_lock_test
+	./s_lock_test
 
 ifeq (depend,$(wildcard depend))
 include depend
diff --git a/src/backend/storage/buffer/s_lock.c b/src/backend/storage/buffer/s_lock.c
index a3f63735643e651b3dd2d5c73bc71984ff2e5efa..d5de97c1423fa106c8ca2c94c2f86198d65abfaa 100644
--- a/src/backend/storage/buffer/s_lock.c
+++ b/src/backend/storage/buffer/s_lock.c
@@ -7,61 +7,334 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/Attic/s_lock.c,v 1.4 1998/04/27 14:43:15 scrappy Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/Attic/s_lock.c,v 1.5 1998/05/04 15:44:41 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
+
+#include <stdio.h>
+
+#include "config.h"
+#include "c.h"
+#include "storage/s_lock.h"
+
+
 /*
- * S_LOCK() -- Implements the S_LOCK function for the Linux/Alpha platform.
- *		   This function is usually an inlined macro for all other platforms,
- *		   but must be a seperate function for the Linux/Alpha platform, due
- *		   to the assembly code involved.
+ * Each time we busy spin we select the next element of this array as the
+ * number of microseconds to wait. This accomplishes pseudo random back-off.
+ * Values are not critical and are weighted to the low end of the range. They
+ * were chosen to work even with different select() timer resolutions on
+ * different platforms.
+ * note: total time to cycle through all 16 entries might be about .1 second.
  */
+int			s_spincycle[S_NSPINCYCLE] =
+{0, 0, 0, 1000, 5000, 0, 10000, 3000,
+ 0, 10000, 0, 15000, 9000, 21000, 6000, 30000
+};
 
 
-#include <sys/types.h>
-#include <sys/file.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include <signal.h>
+#if defined(S_LOCK_DEBUG)
+/*
+ * s_lock(lock) - take a spinlock
+ * add intrumentation code to this and define S_LOCK_DEBUG
+ * instead of hacking up the macro in s_lock.h
+ */
+void
+s_lock(slock_t *lock, char *file, int line)
+{
+	int			spins = 0;
 
-#include "postgres.h"
+	while (TAS(lock))
+	{
+		struct timeval delay;
 
-/* declarations split between these three files */
-#include "storage/buf.h"
-#include "storage/buf_internals.h"
-#include "storage/bufmgr.h"
+		delay.tv_sec = 0;
+		delay.tv_usec = s_spincycle[spins++ % S_NSPINCYCLE];
+		(void) select(0, NULL, NULL, NULL, &delay);
+		if (spins > S_MAX_BUSY)
+		{
+			/* It's been well over a minute...  */
+			s_lock_stuck(lock, file, line);
+		}
+	}
+}
+#endif /* S_LOCK_DEBUG */
 
-#include "storage/fd.h"
-#include "storage/ipc.h"
-#include "storage/s_lock.h"
 
-#if defined(__alpha) && defined(linux)
+/*
+ * s_lock_stuck(lock) - deal with stuck spinlock
+ */
 void
-S_LOCK(slock_t *lock)
+s_lock_stuck(slock_t *lock, char *file, int line)
 {
-	do
+	fprintf(stderr,
+			"\nFATAL: s_lock(%08x) at %s:%d, stuck spinlock. Aborting.\n",
+			(unsigned int) lock, file, line);
+	fprintf(stdout,
+			"\nFATAL: s_lock(%08x) at %s:%d, stuck spinlock. Aborting.\n",
+			(unsigned int) lock, file, line);
+	abort();
+}
+
+
+
+/*
+ * Various TAS implementations moved from s_lock.h to avoid redundant
+ * definitions of the same routine.
+ * RESOLVE: move this to tas.c. Alternatively get rid of tas.[cso] and fold
+ * all that into this file.
+ */
+
+
+#if defined(linux)
+/*************************************************************************
+ * All the Linux flavors
+ */
+
+
+#if defined(__alpha__)
+int
+tas(slock_t *lock)
+{
+	slock_t		_res;
+
+  __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");
+
+	return (_res != 0);
+}
+#endif /* __alpha__ */
+
+
+
+#if defined(i386)
+int
+tas(slock_t *lock)
+{
+	slock_t		_res = 1;
+
+  __asm__("lock; xchgb %0,%1": "=q"(_res), "=m"(*lock):"0"(0x1));
+	return (_res != 0);
+}
+#endif /* i386 */
+
+
+
+#if defined(sparc)
+
+int
+tas(slock_t *lock)
+{
+	slock_t		_res;
+	slock_t    *tmplock = lock;
+
+  __asm__("ldstub [%1], %0" \
+  :			"=&r"(_res), "=r"(tmplock) \
+  :			"1"(tmplock));
+	return (_res != 0);
+}
+
+#endif /* sparc */
+
+
+
+#if 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\
+	");
+}
+
+#endif /* PPC */
+
+
+
+#else /* defined(linux) */
+/***************************************************************************
+ * All Non-Linux
+ */
+
+
+
+#if defined(sun3)
+static void
+tas_dummy()						/* really means: extern int tas(slock_t *lock); */
+{
+	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 */
+
+
+
+#if defined(NEED_SPARC_TAS_ASM)
+/*
+ * bsd and bsdi sparc machines
+ */
+
+/* if we're using -ansi w/ gcc, use __asm__ instead of asm */
+#if defined(__STRICT_ANSI__)
+#define asm(x)	__asm__(x)
+#endif /* __STRICT_ANSI__ */
+
+static void
+tas_dummy()						/* really means: extern int tas(slock_t *lock); */
+{
+	asm(".seg \"data\"");
+	asm(".seg \"text\"");
+	asm("_tas:");
+
+	/*
+	 * Sparc atomic test and set (sparc calls it "atomic load-store")
+	 */
+	asm("ldstub [%r8], %r8");
+
+	asm("retl");
+	asm("nop");
+}
+
+#endif /* NEED_SPARC_TAS_ASM */
+
+
+
+
+#if defined(NEED_VAX_TAS_ASM)
+/*
+ * VAXen -- even multiprocessor ones
+ * (thanks to Tom Ivar Helbekkmo)
+ */
+typedef unsigned char slock_t;
+
+int
+tas(slock_t *lock)
+{
+	register	ret;
+
+	asm("	movl $1, r0
+		bbssi $0, (%1), 1f
+		clrl r0
+  1:	movl r0, %0 "
+  :		"=r"(ret)				/* return value, in register */
+  :		"r"(lock)				/* argument, 'lock pointer', in register */
+  :		"r0");					/* inline code uses this register */
+
+	return ret;
+}
+
+#endif /* NEED_VAX_TAS_ASM */
+
+
+
+#if defined(NEED_I386_TAS_ASM)
+/*
+ * i386 based things
+ */
+
+#if defined(USE_UNIVEL_CC)
+asm int
+tas(slock_t *s_lock)
+{
+	%lab locked;
+/* Upon entry, %eax will contain the pointer to the lock byte */
+	pushl % ebx
+	xchgl % eax, %ebx
+	xor % eax, %eax
+	movb $255, %al
+	lock
+	xchgb % al, (%ebx)
+	popl % ebx
+}
+
+
+#else /* USE_UNIVEL_CC */
+
+int
+tas(slock_t *lock)
+{
+	slock_t		_res = 1;
+
+  __asm__("lock; xchgb %0,%1": "=q"(_res), "=m"(*lock):"0"(0x1));
+	return (_res != 0);
+}
+
+#endif /* USE_UNIVEL_CC */
+
+#endif /* NEED_I386_TAS_ASM */
+
+
+#endif /* linux */
+
+
+#if defined(S_LOCK_TEST)
+
+slock_t		test_lock;
+
+void
+main()
+{
+	S_INIT_LOCK(&test_lock);
+
+	if (!S_LOCK_FREE(&test_lock))
 	{
-		slock_t		_res;
+		printf("S_LOCK_TEST: failed, lock not initialized.\n");
+		exit(1);
+	}
+
+	S_LOCK(&test_lock);
+
+	if (S_LOCK_FREE(&test_lock))
+	{
+		printf("S_LOCK_TEST: failed, lock not locked\n");
+		exit(2);
+	}
+
+	printf("S_LOCK_TEST: this will hang for a few minutes and then abort\n");
+	printf("             with a 'stuck spinlock' message if S_LOCK()\n");
+	printf("             and TAS() are working.\n");
+	S_LOCK(&test_lock);
+
+	printf("S_LOCK_TEST: failed, lock not locked~\n");
+	exit(3);
 
-		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);
 }
 
-#endif
+#endif /* S_LOCK_TEST */
diff --git a/src/include/port/linux.h b/src/include/port/linux.h
index 437ee7231220e332456cf1320997dad4f2c9c36c..e18e6fbaa8d3215242d26be7f4cc67fa365168c4 100644
--- a/src/include/port/linux.h
+++ b/src/include/port/linux.h
@@ -12,7 +12,7 @@
 #if defined(PPC)
 typedef unsigned int slock_t;
 
-#elif defined(__alpha)
+#elif defined(__alpha__)
 typedef long int slock_t;
 
 #else /* i386 probably */
@@ -33,14 +33,6 @@ typedef unsigned char slock_t;
 #endif
 
 #if defined(PPC)
-#undef NEED_I386_TAS_ASM
 #undef HAVE_INT_TIMEZONE
 #endif
 
-#if defined(sparc)
-#undef NEED_I386_TAS_ASM
-#endif
-
-#if defined(__alpha)
-#undef NEED_I386_TAS_ASM
-#endif