diff --git a/src/backend/port/tas/sunstudio_sparc.s b/src/backend/port/tas/sunstudio_sparc.s index 486b7be167..dcf54e2d41 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 849651ed02..39917a41f2 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