aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/port/tas/sunstudio_sparc.s2
-rw-r--r--src/include/storage/s_lock.h49
2 files changed, 50 insertions, 1 deletions
diff --git a/src/backend/port/tas/sunstudio_sparc.s b/src/backend/port/tas/sunstudio_sparc.s
index 486b7be167b..dcf54e2d418 100644
--- a/src/backend/port/tas/sunstudio_sparc.s
+++ b/src/backend/port/tas/sunstudio_sparc.s
@@ -37,6 +37,8 @@ pg_atomic_cas:
!
! http://cvs.opensolaris.org/source/xref/on/usr/src/lib/libc/sparc/threads/sparc.il
!
+ ! NB: We're assuming we're running on a TSO system here - solaris
+ ! userland luckily always has done so.
#if defined(__sparcv9) || defined(__sparcv8plus)
cas [%o0],%o2,%o1
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index 849651ed02c..39917a41f2c 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -351,6 +351,12 @@ tas(volatile slock_t *lock)
#if defined(__sparc__) /* Sparc */
+/*
+ * Solaris has always run sparc processors in TSO (total store) mode, but
+ * linux didn't use to and the *BSDs still don't. So, be careful about
+ * acquire/release semantics. The CPU will treat superflous membars as NOPs,
+ * so it's just code space.
+ */
#define HAS_TEST_AND_SET
typedef unsigned char slock_t;
@@ -372,9 +378,50 @@ tas(volatile slock_t *lock)
: "=r"(_res), "+m"(*lock)
: "r"(lock)
: "memory");
+#if defined(__sparcv7)
+ /*
+ * No stbar or membar available, luckily no actually produced hardware
+ * requires a barrier.
+ */
+#elif defined(__sparcv8)
+ /* stbar is available (and required for both PSO, RMO), membar isn't */
+ __asm__ __volatile__ ("stbar \n":::"memory");
+#else
+ /*
+ * #LoadStore (RMO) | #LoadLoad (RMO) together are the appropriate acquire
+ * barrier for sparcv8+ upwards.
+ */
+ __asm__ __volatile__ ("membar #LoadStore | #LoadLoad \n":::"memory");
+#endif
return (int) _res;
}
+#if defined(__sparcv7)
+/*
+ * No stbar or membar available, luckily no actually produced hardware
+ * requires a barrier.
+ */
+#define S_UNLOCK(lock) (*((volatile slock_t *) (lock)) = 0)
+#elif __sparcv8
+/* stbar is available (and required for both PSO, RMO), membar isn't */
+#define S_UNLOCK(lock) \
+do \
+{ \
+ __asm__ __volatile__ ("stbar \n":::"memory"); \
+ *((volatile slock_t *) (lock)) = 0; \
+} while (0)
+#else
+/*
+ * #LoadStore (RMO) | #StoreStore (RMO, PSO) together are the appropriate
+ * release barrier for sparcv8+ upwards.
+ */
+do \
+{ \
+ __asm__ __volatile__ ("membar #LoadStore | #StoreStore \n":::"memory"); \
+ *((volatile slock_t *) (lock)) = 0; \
+} while (0)
+#endif
+
#endif /* __sparc__ */
@@ -740,7 +787,7 @@ typedef int slock_t;
#endif /* _AIX */
-/* These are in s_lock.c */
+/* These are in sunstudio_(sparc|x86).s */
#if defined(__SUNPRO_C) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
#define HAS_TEST_AND_SET