< prev index next >
src/hotspot/os_cpu/linux_s390/atomic_linux_s390.hpp
Print this page
rev 49986 : 8202080: Introduce ordering semantics for Atomic::add and other RMW atomics
Reviewed-by: lucy, rehn, dholmes
@@ -1,8 +1,8 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
@@ -66,27 +66,35 @@
// instruction is retried as often as required.
//
// The return value of the method is the value that was successfully stored. At the
// time the caller receives back control, the value in memory may have changed already.
+// New atomic operations only include specific-operand-serialization, not full
+// memory barriers. We can use the Fast-BCR-Serialization Facility for them.
+inline void z196_fast_sync() {
+ __asm__ __volatile__ ("bcr 14, 0" : : : "memory");
+}
+
template<size_t byte_size>
struct Atomic::PlatformAdd
: Atomic::AddAndFetch<Atomic::PlatformAdd<byte_size> >
{
template<typename I, typename D>
- D add_and_fetch(I add_value, D volatile* dest) const;
+ D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const;
};
template<>
template<typename I, typename D>
-inline D Atomic::PlatformAdd<4>::add_and_fetch(I inc, D volatile* dest) const {
+inline D Atomic::PlatformAdd<4>::add_and_fetch(I inc, D volatile* dest,
+ atomic_memory_order order) const {
STATIC_ASSERT(4 == sizeof(I));
STATIC_ASSERT(4 == sizeof(D));
D old, upd;
if (VM_Version::has_LoadAndALUAtomicV1()) {
+ if (order == memory_order_conservative) { z196_fast_sync(); }
__asm__ __volatile__ (
" LGFR 0,%[inc] \n\t" // save increment
" LA 3,%[mem] \n\t" // force data address into ARG2
// " LAA %[upd],%[inc],%[mem] \n\t" // increment and get old value
// " LAA 2,0,0(3) \n\t" // actually coded instruction
@@ -104,10 +112,11 @@
//---< inputs >---
: [inc] "a" (inc) // read-only.
//---< clobbered >---
: "cc", "r0", "r2", "r3", "memory"
);
+ if (order == memory_order_conservative) { z196_fast_sync(); }
} else {
__asm__ __volatile__ (
" LLGF %[old],%[mem] \n\t" // get old value
"0: LA %[upd],0(%[inc],%[old]) \n\t" // calc result
" CS %[old],%[upd],%[mem] \n\t" // try to xchg res with mem
@@ -127,17 +136,19 @@
}
template<>
template<typename I, typename D>
-inline D Atomic::PlatformAdd<8>::add_and_fetch(I inc, D volatile* dest) const {
+inline D Atomic::PlatformAdd<8>::add_and_fetch(I inc, D volatile* dest,
+ atomic_memory_order order) const {
STATIC_ASSERT(8 == sizeof(I));
STATIC_ASSERT(8 == sizeof(D));
D old, upd;
if (VM_Version::has_LoadAndALUAtomicV1()) {
+ if (order == memory_order_conservative) { z196_fast_sync(); }
__asm__ __volatile__ (
" LGR 0,%[inc] \n\t" // save increment
" LA 3,%[mem] \n\t" // force data address into ARG2
// " LAAG %[upd],%[inc],%[mem] \n\t" // increment and get old value
// " LAAG 2,0,0(3) \n\t" // actually coded instruction
@@ -155,10 +166,11 @@
//---< inputs >---
: [inc] "a" (inc) // read-only.
//---< clobbered >---
: "cc", "r0", "r2", "r3", "memory"
);
+ if (order == memory_order_conservative) { z196_fast_sync(); }
} else {
__asm__ __volatile__ (
" LG %[old],%[mem] \n\t" // get old value
"0: LA %[upd],0(%[inc],%[old]) \n\t" // calc result
" CSG %[old],%[upd],%[mem] \n\t" // try to xchg res with mem
@@ -195,11 +207,12 @@
// The return value is the (unchanged) value from memory as it was when the
// replacement succeeded.
template<>
template<typename T>
inline T Atomic::PlatformXchg<4>::operator()(T exchange_value,
- T volatile* dest) const {
+ T volatile* dest,
+ atomic_memory_order unused) const {
STATIC_ASSERT(4 == sizeof(T));
T old;
__asm__ __volatile__ (
" LLGF %[old],%[mem] \n\t" // get old value
@@ -218,11 +231,12 @@
}
template<>
template<typename T>
inline T Atomic::PlatformXchg<8>::operator()(T exchange_value,
- T volatile* dest) const {
+ T volatile* dest,
+ atomic_memory_order unused) const {
STATIC_ASSERT(8 == sizeof(T));
T old;
__asm__ __volatile__ (
" LG %[old],%[mem] \n\t" // get old value
@@ -276,11 +290,11 @@
template<>
template<typename T>
inline T Atomic::PlatformCmpxchg<4>::operator()(T xchg_val,
T volatile* dest,
T cmp_val,
- cmpxchg_memory_order unused) const {
+ atomic_memory_order unused) const {
STATIC_ASSERT(4 == sizeof(T));
T old;
__asm__ __volatile__ (
" CS %[old],%[upd],%[mem] \n\t" // Try to xchg upd with mem.
@@ -300,11 +314,11 @@
template<>
template<typename T>
inline T Atomic::PlatformCmpxchg<8>::operator()(T xchg_val,
T volatile* dest,
T cmp_val,
- cmpxchg_memory_order unused) const {
+ atomic_memory_order unused) const {
STATIC_ASSERT(8 == sizeof(T));
T old;
__asm__ __volatile__ (
" CSG %[old],%[upd],%[mem] \n\t" // Try to xchg upd with mem.
< prev index next >