From f83b2215987b474472c3115f91bff745bfa7de28 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sat, 30 Dec 2000 02:34:56 +0000 Subject: [PATCH] Clean up spinlock assembly code slightly (just cosmetic improvements) for Alpha gcc case. For Alpha non-gcc case, replace use of __INTERLOCKED_TESTBITSS_QUAD builtin with __LOCK_LONG_RETRY and __UNLOCK_LONG. The former does not execute an MB instruction and therefore was guaranteed not to work on multiprocessor machines. The LOCK_LONG builtins produce code that is the same in all essential details as the gcc assembler code. --- src/include/storage/s_lock.h | 76 ++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h index 9f6b8d3a12..b55b4b60d4 100644 --- a/src/include/storage/s_lock.h +++ b/src/include/storage/s_lock.h @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/include/storage/s_lock.h,v 1.76 2000/12/29 21:31:20 tgl Exp $ + * $Header: /cvsroot/pgsql/src/include/storage/s_lock.h,v 1.77 2000/12/30 02:34:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -291,50 +291,56 @@ tas(volatile slock_t *s_lock) #if defined(__alpha) -#if defined(__osf__) /* - * OSF/1 (Alpha AXP) - * - * Note that slock_t on the Alpha AXP is msemaphore instead of char - * (see storage/ipc.h). + * Correct multi-processor locking methods are explained in section 5.5.3 + * of the Alpha AXP Architecture Handbook, which at this writing can be + * found at ftp://ftp.netbsd.org/pub/NetBSD/misc/dec-docs/index.html. + * For gcc we implement the handbook's code directly with inline assembler. */ -#include -#if 0 -#define TAS(lock) (msem_lock((lock), MSEM_IF_NOWAIT) < 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) -#else -#define TAS(lock) (__INTERLOCKED_TESTBITSS_QUAD((lock),0)) -#endif - -#else /* i.e. not __osf__ */ +#if defined(__GNUC__) -#define TAS(lock) tas(lock) -#define S_UNLOCK(lock) do { __asm__("mb"); *(lock) = 0; } while (0) +#define TAS(lock) tas(lock) +#define S_UNLOCK(lock) do { __asm__ volatile ("mb"); *(lock) = 0; } while (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"); + register slock_t _res; + + __asm__ volatile +(" ldq $0, %0 \n\ + bne $0, 2f \n\ + ldq_l %1, %0 \n\ + bne %1, 2f \n\ + mov 1, $0 \n\ + stq_c $0, %0 \n\ + beq $0, 2f \n\ + mb \n\ + br 3f \n\ + 2: mov 1, %1 \n\ + 3: \n" : "=m"(*lock), "=r"(_res) : : "0"); return (int) _res; } -#endif /* __osf__ */ + +#else /* !defined(__GNUC__) */ + +/* + * The Tru64 compiler doesn't support gcc-style inline asm, but it does + * have some builtin functions that accomplish much the same results. + * For simplicity, slock_t is defined as long (ie, quadword) on Alpha + * regardless of the compiler in use. LOCK_LONG and UNLOCK_LONG only + * operate on an int (ie, longword), but that's OK as long as we define + * S_INIT_LOCK to zero out the whole quadword. + */ + +#include + +#define S_INIT_LOCK(lock) (*(lock) = 0) +#define TAS(lock) (__LOCK_LONG_RETRY((lock), 1) == 0) +#define S_UNLOCK(lock) __UNLOCK_LONG(lock) + +#endif /* defined(__GNUC__) */ #endif /* __alpha */ -- 2.11.0