8000 Fix spinlock implementation for some !solaris sparc platforms. · zyfran/postgres@27ef6b6 · GitHub
[go: up one dir, main page]

Skip to content

Commit 27ef6b6

Browse files
committed
Fix spinlock implementation for some !solaris sparc platforms.
Some Sparc CPUs can be run in various coherence models, ranging from RMO (relaxed) over PSO (partial) to TSO (total). Solaris has always run CPUs in TSO mode while in userland, but linux didn't use to and the various *BSDs still don't. Unfortunately the sparc TAS/S_UNLOCK were only correct under TSO. Fix that by adding the necessary memory barrier instructions. On sparcv8+, which should be all relevant CPUs, these are treated as NOPs if the current consistency model doesn't require the barriers. Discussion: 20140630222854.GW26930@awork2.anarazel.de Will be backpatched to all released branches once a few buildfarm cycles haven't shown up problems. As I've no access to sparc, this is blindly written.
1 parent b0fd5c5 commit 27ef6b6

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

src/backend/port/tas/sunstudio_sparc.s

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ pg_atomic_cas:
3737
!
3838
! http://cvs.opensolaris.org/source/xref/on/usr/src/lib/libc/sparc/threads/sparc.il
3939
!
40+
! NB: We're assuming we're running on a TSO system here - solaris
41+
! userland luckily always has done so.
4042

4143
#if defined(__sparcv9) || defined(__sparcv8plus)
4244
cas [%o0],%o2,%o1

src/include/storage/s_lock.h

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,12 @@ tas(volatile slock_t *lock)
384384

385385

386386
#if defined(__sparc__) /* Sparc */
387+
/*
388+
* Solaris has always run sparc processors in TSO (total store) mode, but
389+
* linux didn't use to and the *BSDs still don't. So, be careful about
390+
* acquire/release semantics. The CPU will treat superflous membars as NOPs,
391+
* so it's just code space.
392+
*/
387393
#define HAS_TEST_AND_SET
388394

389395
typedef unsigned char slock_t;
@@ -405,9 +411,50 @@ tas(volatile slock_t *lock)
405411
: "=r"(_res), "+m"(*lock)
406412
: "r"(lock)
407413
: "memory");
414+
#if defined(__sparcv7)
415+
/*
416+
* No stbar or membar available, luckily no actually produced hardware
417+
* requires a barrier.
418+
*/
419+
#elif defined(__sparcv8)
420+
/* stbar is available (and required for both PSO, RMO), membar isn't */
421+
__asm__ __volatile__ ("stbar \n":::"memory");
422+
#else
423+
/*
424+
* #LoadStore (RMO) | #LoadLoad (RMO) together are the appropriate acquire
425+
* barrier for sparcv8+ upwards.
426+
*/
427+
__asm__ __volatile__ ("membar #LoadStore | #LoadLoad \n":::"memory");
428+
#endif
408429
return (int) _res;
409430
}
410431

432+
#if defined(__sparcv7)
433+
/*
434+
* No stbar or membar available, luckily no actually produced hardware
435+
* requires a barrier.
436+
*/
437+
#define S_UNLOCK(lock) (*((volatile slock_t *) (lock)) = 0)
438+
#elif __sparcv8
439+
/* stbar is available (and required for both PSO, RMO), membar isn't */
440+
#define S_UNLOCK(lock) \
441+
do \
442+
{ \
443+
__asm__ __volatile__ ("stbar \n":::"memory"); \
444+
*((volatile slock_t *) (lock)) = 0; \
445+
} while (0)
446+
#else
447+
/*
448+
* #LoadStore (RMO) | #StoreStore (RMO, PSO) together are the appropriate
449+
* release barrier for sparcv8+ upwards.
450+
*/
451+
do \
452+
{ \
453+
__asm__ __volatile__ ("membar #LoadStore | #StoreStore \n":::"memory"); \
454+
*((volatile slock_t *) (lock)) = 0; \
455+
} while (0)
456+
#endif
457+
411458
#endif /* __sparc__ */
412459

413460

@@ -908,7 +955,7 @@ typedef int slock_t;
908955
#endif /* _AIX */
909956

910957

911-
/* These are in s_lock.c */
958+
/* These are in sunstudio_(sparc|x86).s */
912959

913960

914961
#if defined(sun3) /* Sun3 */

0 commit comments

Comments
 (0)
0