summaryrefslogtreecommitdiff
path: root/src/include/storage/s_lock.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/storage/s_lock.h')
-rw-r--r--src/include/storage/s_lock.h105
1 files changed, 38 insertions, 67 deletions
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 98b4d718d29..1e1eb324b43 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -765,44 +765,14 @@ tas(volatile slock_t *lock)
typedef unsigned char slock_t;
#endif
-/*
- * Default implementation of S_UNLOCK() for gcc/icc.
- *
- * Note that this implementation is unsafe for any platform that can reorder
- * a memory access (either load or store) after a following store. That
- * happens not to be possible on x86 and most legacy architectures (some are
- * single-processor!), but many modern systems have weaker memory ordering.
- * Those that do must define their own version of S_UNLOCK() rather than
- * relying on this one.
- */
-#if !defined(S_UNLOCK)
-#define S_UNLOCK(lock) \
- do { __asm__ __volatile__("" : : : "memory"); *(lock) = 0; } while (0)
-#endif
-
-#endif /* defined(__GNUC__) || defined(__INTEL_COMPILER) */
-
-
-/*
- * ---------------------------------------------------------------------
- * Platforms that use non-gcc inline assembly:
- * ---------------------------------------------------------------------
- */
-
-#if !defined(HAS_TEST_AND_SET) /* We didn't trigger above, let's try here */
-
-
-#if defined(__hppa) || defined(__hppa__) /* HP PA-RISC, GCC and HP compilers */
+#if defined(__hppa) || defined(__hppa__) /* HP PA-RISC */
/*
* HP's PA-RISC
*
- * See src/backend/port/hpux/tas.c.template for details about LDCWX. Because
- * LDCWX requires a 16-byte-aligned address, we declare slock_t as a 16-byte
- * struct. The active word in the struct is whichever has the aligned address;
- * the other three words just sit at -1.
- *
- * When using gcc, we can inline the required assembly code.
+ * Because LDCWX requires a 16-byte-aligned address, we declare slock_t as a
+ * 16-byte struct. The active word in the struct is whichever has the aligned
+ * address; the other three words just sit at -1.
*/
#define HAS_TEST_AND_SET
@@ -813,14 +783,27 @@ typedef struct
#define TAS_ACTIVE_WORD(lock) ((volatile int *) (((uintptr_t) (lock) + 15) & ~15))
-#if defined(__GNUC__)
-
static __inline__ int
tas(volatile slock_t *lock)
{
volatile int *lockword = TAS_ACTIVE_WORD(lock);
register int lockval;
+ /*
+ * The LDCWX instruction atomically clears the target word and
+ * returns the previous value. Hence, if the instruction returns
+ * 0, someone else has already acquired the lock before we tested
+ * it (i.e., we have failed).
+ *
+ * Notice that this means that we actually clear the word to set
+ * the lock and set the word to clear the lock. This is the
+ * opposite behavior from the SPARC LDSTUB instruction. For some
+ * reason everything that H-P does is rather baroque...
+ *
+ * For details about the LDCWX instruction, see the "Precision
+ * Architecture and Instruction Reference Manual" (09740-90014 of June
+ * 1987), p. 5-38.
+ */
__asm__ __volatile__(
" ldcwx 0(0,%2),%0 \n"
: "=r"(lockval), "+m"(*lockword)
@@ -829,23 +812,12 @@ tas(volatile slock_t *lock)
return (lockval == 0);
}
-/*
- * The hppa implementation doesn't follow the rules of this files and provides
- * a gcc specific implementation outside of the above defined(__GNUC__). It
- * does so to avoid duplication between the HP compiler and gcc. So undefine
- * the generic fallback S_UNLOCK from above.
- */
-#ifdef S_UNLOCK
-#undef S_UNLOCK
-#endif
#define S_UNLOCK(lock) \
do { \
__asm__ __volatile__("" : : : "memory"); \
*TAS_ACTIVE_WORD(lock) = -1; \
} while (0)
-#endif /* __GNUC__ */
-
#define S_INIT_LOCK(lock) \
do { \
volatile slock_t *lock_ = (lock); \
@@ -860,32 +832,31 @@ tas(volatile slock_t *lock)
#endif /* __hppa || __hppa__ */
-#if defined(__hpux) && defined(__ia64) && !defined(__GNUC__)
/*
- * HP-UX on Itanium, non-gcc/icc compiler
- *
- * We assume that the compiler enforces strict ordering of loads/stores on
- * volatile data (see comments on the gcc-version earlier in this file).
- * Note that this assumption does *not* hold if you use the
- * +Ovolatile=__unordered option on the HP-UX compiler, so don't do that.
+ * Default implementation of S_UNLOCK() for gcc/icc.
*
- * See also Implementing Spinlocks on the Intel Itanium Architecture and
- * PA-RISC, by Tor Ekqvist and David Graves, for more information. As of
- * this writing, version 1.0 of the manual is available at:
- * http://h21007.www2.hp.com/portal/download/files/unprot/itanium/spinlocks.pdf
+ * Note that this implementation is unsafe for any platform that can reorder
+ * a memory access (either load or store) after a following store. That
+ * happens not to be possible on x86 and most legacy architectures (some are
+ * single-processor!), but many modern systems have weaker memory ordering.
+ * Those that do must define their own version of S_UNLOCK() rather than
+ * relying on this one.
*/
-#define HAS_TEST_AND_SET
+#if !defined(S_UNLOCK)
+#define S_UNLOCK(lock) \
+ do { __asm__ __volatile__("" : : : "memory"); *(lock) = 0; } while (0)
+#endif
-typedef unsigned int slock_t;
+#endif /* defined(__GNUC__) || defined(__INTEL_COMPILER) */
-#include <ia64/sys/inline.h>
-#define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
-/* On IA64, it's a win to use a non-locking test before the xchg proper */
-#define TAS_SPIN(lock) (*(lock) ? 1 : TAS(lock))
-#define S_UNLOCK(lock) \
- do { _Asm_mf(); (*(lock)) = 0; } while (0)
-#endif /* HPUX on IA64, non gcc/icc */
+/*
+ * ---------------------------------------------------------------------
+ * Platforms that use non-gcc inline assembly:
+ * ---------------------------------------------------------------------
+ */
+
+#if !defined(HAS_TEST_AND_SET) /* We didn't trigger above, let's try here */
#if defined(_AIX) /* AIX */
/*