< 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 >