Subject: Some assembly required (postgresql & test-and-set)
To: None <>
From: Allen Briggs <>
List: port-alpha
Date: 11/21/1999 10:47:55
Content-Type: text/plain; charset=us-ascii

Hi, folks.  I'm looking for someone who has some Alpha assembly
knowledge to help me with a question that's come up in getting
PostgreSQL to run on NetBSD/alpha.

It allegedly works on Alpha OSF/1 (or whatever it's being called these
days), but they use msemaphores.  I think it's supposed to work on
Linux/alpha, but I'm not convinced that it does...  I've made a couple
of patches to get it to compile the basic stuff (I'll attach them to
this message), but it's still not working for me--I get a "stuck
spinlock" when trying to initialize during install.  As far as I can
tell, it looks like a problem with the test-and-set function that's
defined for the Alpha.  Since I've never actually done any assembly
programming on the Alpha, I'd like someone else to take a look at this
to help me determine whether or not it's right.  The symptom that I'm
seeing is that after running fine for a while, tas(x) will erroneously
return 'already set' (after running fine, testing and setting, on that
same memory location).

#if defined(__alpha__)
#define TAS(lock) tas(lock)
#define S_UNLOCK(lock) { __asm__("mb"); *(lock) = 0; }
static __inline__ int
tas(volatile slock_t *lock)
        register slock_t _res;

__asm__("    ldq   $0, %0              \n\
                 bne   $0, 3f          \n\
                 ldq_l $0, %0              \n\
                 bne   $0, 3f          \n\
                 or    $31, 1, $0          \n\
                 stq_c $0, %0              \n\
                 beq   $0, 2f              \n\
                 bis   $31, $31, %1        \n\
                 mb                                \n\
                 jmp   $31, 4f             \n\
              2: or    $31, 1, $0              \n\
              3: bis   $0, $0, %1              \n\
              4: nop      ": "=m"(*lock), "=r"(_res): :"0");

        return (int) _res;

#endif   /* __alpha__ */

I'm doing this work on:

NetBSD 1.4.1 (GENERIC) #0: Mon Aug  9 02:30:53 PDT 1999
DEC 3000 - M400, 133MHz
8192 byte page size, 1 processor.
real mem = 67108864 (2097152 reserved for PROM, 65011712 used by NetBSD)
avail mem = 52355072
using 793 buffers containing 6496256 bytes of memory
mainbus0 (root)
cpu0 at mainbus0: ID 0 (primary), 21064-1 (pass 3)

I think the above code is from a Linux/alpha port, and I know that that 
port does not support this hardware.  Is it some difference in the CPU,
does the code above look wrong, or is there something more nefarious
going on somewhere?


Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=patch-an


*** ./backend/main/main.c.orig	Fri Nov 19 12:53:17 1999
--- ./backend/main/main.c	Fri Nov 19 12:53:32 1999
*** 15,21 ****
  #include <string.h>
  #include <unistd.h>
! #if defined(__alpha) && !defined(linux)
  #include <sys/sysinfo.h>
  #include <machine/hal_sysinfo.h>
  #define ASSEMBLER
--- 15,21 ----
  #include <string.h>
  #include <unistd.h>
! #if defined(__alpha) && !defined(linux) && !defined(__NetBSD__)
  #include <sys/sysinfo.h>
  #include <machine/hal_sysinfo.h>
  #define ASSEMBLER

Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=patch-ao


--- ./include/port/bsd.h.orig	Tue May 25 12:14:29 1999
+++ ./include/port/bsd.h	Sat Nov 20 01:05:44 1999
@@ -28,15 +28,22 @@
+#if defined(__alpha__)
+typedef long int slock_t;
 #if defined(__powerpc__)
 typedef unsigned int slock_t;
 #if defined(__mips__)
 /* #	undef HAS_TEST_AND_SET */
-#if !defined(__powerpc__)
+#if !defined(__powerpc__) && !defined(__alpha__)
 typedef unsigned char slock_t;