1 /*
   2  * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_RUNTIME_ATOMIC_HPP
  26 #define SHARE_RUNTIME_ATOMIC_HPP
  27 
  28 #include "memory/allocation.hpp"
  29 #include "metaprogramming/conditional.hpp"
  30 #include "metaprogramming/enableIf.hpp"
  31 #include "metaprogramming/isIntegral.hpp"
  32 #include "metaprogramming/isPointer.hpp"
  33 #include "metaprogramming/isSame.hpp"
  34 #include "metaprogramming/primitiveConversions.hpp"
  35 #include "metaprogramming/removeCV.hpp"
  36 #include "metaprogramming/removePointer.hpp"
  37 #include "runtime/orderAccess.hpp"
  38 #include "utilities/align.hpp"
  39 #include "utilities/macros.hpp"
  40 
  41 enum atomic_memory_order {
  42   // The modes that align with C++11 are intended to
  43   // follow the same semantics.
  44   memory_order_relaxed = 0,
  45   memory_order_acquire = 2,
  46   memory_order_release = 3,
  47   memory_order_acq_rel = 4,
  48   // Strong two-way memory barrier.
  49   memory_order_conservative = 8
  50 };
  51 
  52 enum ScopedFenceType {
  53     X_ACQUIRE
  54   , RELEASE_X
  55   , RELEASE_X_FENCE
  56 };
  57 
  58 class Atomic : AllStatic {
  59 public:
  60   // Atomic operations on int64 types are not available on all 32-bit
  61   // platforms. If atomic ops on int64 are defined here they must only
  62   // be used from code that verifies they are available at runtime and
  63   // can provide an alternative action if not - see supports_cx8() for
  64   // a means to test availability.
  65 
  66   // The memory operations that are mentioned with each of the atomic
  67   // function families come from src/share/vm/runtime/orderAccess.hpp,
  68   // e.g., <fence> is described in that file and is implemented by the
  69   // OrderAccess::fence() function. See that file for the gory details
  70   // on the Memory Access Ordering Model.
  71 
  72   // All of the atomic operations that imply a read-modify-write action
  73   // guarantee a two-way memory barrier across that operation. Historically
  74   // these semantics reflect the strength of atomic operations that are
  75   // provided on SPARC/X86. We assume that strength is necessary unless
  76   // we can prove that a weaker form is sufficiently safe.
  77 
  78   // Atomically store to a location
  79   // The type T must be either a pointer type convertible to or equal
  80   // to D, an integral/enum type equal to D, or a type equal to D that
  81   // is primitive convertible using PrimitiveConversions.
  82   template<typename D, typename T>
  83   inline static void store(volatile D* dest, T store_value);
  84 
  85   template <typename D, typename T>
  86   inline static void release_store(volatile D* dest, T store_value);
  87 
  88   template <typename D, typename T>
  89   inline static void release_store_fence(volatile D* dest, T store_value);
  90 
  91   // Atomically load from a location
  92   // The type T must be either a pointer type, an integral/enum type,
  93   // or a type that is primitive convertible using PrimitiveConversions.
  94   template<typename T>
  95   inline static T load(const volatile T* dest);
  96 
  97   template <typename T>
  98   inline static T load_acquire(const volatile T* dest);
  99 
 100   // Atomically add to a location. Returns updated value. add*() provide:
 101   // <fence> add-value-to-dest <membar StoreLoad|StoreStore>
 102 
 103   template<typename D, typename I>
 104   inline static D add(D volatile* dest, I add_value,
 105                       atomic_memory_order order = memory_order_conservative);
 106 
 107   template<typename D, typename I>
 108   inline static D fetch_and_add(D volatile* dest, I add_value,
 109                                 atomic_memory_order order = memory_order_conservative);
 110 
 111   template<typename D, typename I>
 112   inline static D sub(D volatile* dest, I sub_value,
 113                       atomic_memory_order order = memory_order_conservative);
 114 
 115   // Atomically increment location. inc() provide:
 116   // <fence> increment-dest <membar StoreLoad|StoreStore>
 117   // The type D may be either a pointer type, or an integral
 118   // type. If it is a pointer type, then the increment is
 119   // scaled to the size of the type pointed to by the pointer.
 120   template<typename D>
 121   inline static void inc(D volatile* dest,
 122                          atomic_memory_order order = memory_order_conservative);
 123 
 124   // Atomically decrement a location. dec() provide:
 125   // <fence> decrement-dest <membar StoreLoad|StoreStore>
 126   // The type D may be either a pointer type, or an integral
 127   // type. If it is a pointer type, then the decrement is
 128   // scaled to the size of the type pointed to by the pointer.
 129   template<typename D>
 130   inline static void dec(D volatile* dest,
 131                          atomic_memory_order order = memory_order_conservative);
 132 
 133   // Performs atomic exchange of *dest with exchange_value. Returns old
 134   // prior value of *dest. xchg*() provide:
 135   // <fence> exchange-value-with-dest <membar StoreLoad|StoreStore>
 136   // The type T must be either a pointer type convertible to or equal
 137   // to D, an integral/enum type equal to D, or a type equal to D that
 138   // is primitive convertible using PrimitiveConversions.
 139   template<typename D, typename T>
 140   inline static D xchg(volatile D* dest, T exchange_value,
 141                        atomic_memory_order order = memory_order_conservative);
 142 
 143   // Performs atomic compare of *dest and compare_value, and exchanges
 144   // *dest with exchange_value if the comparison succeeded. Returns prior
 145   // value of *dest. cmpxchg*() provide:
 146   // <fence> compare-and-exchange <membar StoreLoad|StoreStore>
 147 
 148   template<typename D, typename U, typename T>
 149   inline static D cmpxchg(D volatile* dest,
 150                           U compare_value,
 151                           T exchange_value,
 152                           atomic_memory_order order = memory_order_conservative);
 153 
 154   // Performs atomic compare of *dest and NULL, and replaces *dest
 155   // with exchange_value if the comparison succeeded.  Returns true if
 156   // the comparison succeeded and the exchange occurred.  This is
 157   // often used as part of lazy initialization, as a lock-free
 158   // alternative to the Double-Checked Locking Pattern.
 159   template<typename D, typename T>
 160   inline static bool replace_if_null(D* volatile* dest, T* value,
 161                                      atomic_memory_order order = memory_order_conservative);
 162 
 163 private:
 164 WINDOWS_ONLY(public:) // VS2017 warns (C2027) use of undefined type if IsPointerConvertible is declared private
 165   // Test whether From is implicitly convertible to To.
 166   // From and To must be pointer types.
 167   // Note: Provides the limited subset of C++11 std::is_convertible
 168   // that is needed here.
 169   template<typename From, typename To> struct IsPointerConvertible;
 170 
 171 protected:
 172   // Dispatch handler for store.  Provides type-based validity
 173   // checking and limited conversions around calls to the platform-
 174   // specific implementation layer provided by PlatformOp.
 175   template<typename D, typename T, typename PlatformOp, typename Enable = void>
 176   struct StoreImpl;
 177 
 178   // Platform-specific implementation of store.  Support for sizes
 179   // of 1, 2, 4, and (if different) pointer size bytes are required.
 180   // The class is a function object that must be default constructable,
 181   // with these requirements:
 182   //
 183   // either:
 184   // - dest is of type D*, an integral, enum or pointer type.
 185   // - new_value are of type T, an integral, enum or pointer type D or
 186   //   pointer type convertible to D.
 187   // or:
 188   // - T and D are the same and are primitive convertible using PrimitiveConversions
 189   // and either way:
 190   // - platform_store is an object of type PlatformStore<sizeof(T)>.
 191   //
 192   // Then
 193   //   platform_store(new_value, dest)
 194   // must be a valid expression.
 195   //
 196   // The default implementation is a volatile store. If a platform
 197   // requires more for e.g. 64 bit stores, a specialization is required
 198   template<size_t byte_size> struct PlatformStore;
 199 
 200   // Dispatch handler for load.  Provides type-based validity
 201   // checking and limited conversions around calls to the platform-
 202   // specific implementation layer provided by PlatformOp.
 203   template<typename T, typename PlatformOp, typename Enable = void>
 204   struct LoadImpl;
 205 
 206   // Platform-specific implementation of load. Support for sizes of
 207   // 1, 2, 4 bytes and (if different) pointer size bytes are required.
 208   // The class is a function object that must be default
 209   // constructable, with these requirements:
 210   //
 211   // - dest is of type T*, an integral, enum or pointer type, or
 212   //   T is convertible to a primitive type using PrimitiveConversions
 213   // - platform_load is an object of type PlatformLoad<sizeof(T)>.
 214   //
 215   // Then
 216   //   platform_load(src)
 217   // must be a valid expression, returning a result convertible to T.
 218   //
 219   // The default implementation is a volatile load. If a platform
 220   // requires more for e.g. 64 bit loads, a specialization is required
 221   template<size_t byte_size> struct PlatformLoad;
 222 
 223   // Give platforms a variation point to specialize.
 224   template<size_t byte_size, ScopedFenceType type> struct PlatformOrderedStore;
 225   template<size_t byte_size, ScopedFenceType type> struct PlatformOrderedLoad;
 226 
 227 private:
 228   // Dispatch handler for add and fetch_and add.  Provides type-based
 229   // validity checking and limited conversions around calls to the
 230   // platform-specific implementation layer provided by
 231   // PlatformAddAndFetch and PlatformFetchAndAdd.
 232   template<typename D, typename I, typename Enable = void>
 233   struct AddImpl;
 234 
 235   // Platform-specific implementation of add.  Support for sizes of 4
 236   // bytes and (if different) pointer size bytes are required.  The
 237   // class is a function object that must be default constructable,
 238   // with these requirements:
 239   //
 240   // - dest is of type D*, an integral or pointer type.
 241   // - add_value is of type I, an integral type.
 242   // - sizeof(I) == sizeof(D).
 243   // - if D is an integral type, I == D.
 244   // - platform_add is an object of type PlatformAddAndFetch<sizeof(D)>.
 245   //
 246   // Then
 247   //   platform_add(dest, add_value)
 248   // must be a valid expression, returning a result convertible to D.
 249   //
 250   // No definition is provided; all platforms must explicitly define
 251   // this class and any needed specializations.
 252   template<size_t byte_size> struct PlatformAddAndFetch;
 253 
 254   // Platfom-specific implementation of fetch_and_add.
 255   // See comment for PlatformAddAndFetch for further specification.
 256   template<size_t byte_size> struct PlatformFetchAndAdd;
 257 
 258   // Support for platforms that implement some variants of add using a
 259   // (typically out of line) non-template helper function.  The
 260   // generic arguments passed to PlatformAdd need to be translated to
 261   // the appropriate type for the helper function, the helper function
 262   // invoked on the translated arguments, and the result translated
 263   // back.  Type is the parameter / return type of the helper
 264   // function.  No scaling of add_value is performed when D is a pointer
 265   // type, so this function can be used to implement the support function
 266   // required by AddAndFetch.
 267   template<typename Type, typename Fn, typename D, typename I>
 268   static D add_using_helper(Fn fn, D volatile* dest, I add_value);
 269 
 270   // Dispatch handler for cmpxchg.  Provides type-based validity
 271   // checking and limited conversions around calls to the
 272   // platform-specific implementation layer provided by
 273   // PlatformCmpxchg.
 274   template<typename D, typename U, typename T, typename Enable = void>
 275   struct CmpxchgImpl;
 276 
 277   // Platform-specific implementation of cmpxchg.  Support for sizes
 278   // of 1, 4, and 8 are required.  The class is a function object that
 279   // must be default constructable, with these requirements:
 280   //
 281   // - dest is of type T*.
 282   // - exchange_value and compare_value are of type T.
 283   // - order is of type atomic_memory_order.
 284   // - platform_cmpxchg is an object of type PlatformCmpxchg<sizeof(T)>.
 285   //
 286   // Then
 287   //   platform_cmpxchg(dest, compare_value, exchange_value, order)
 288   // must be a valid expression, returning a result convertible to T.
 289   //
 290   // A default definition is provided, which declares a function template
 291   //   T operator()(T volatile*, T, T, atomic_memory_order) const
 292   //
 293   // For each required size, a platform must either provide an
 294   // appropriate definition of that function, or must entirely
 295   // specialize the class template for that size.
 296   template<size_t byte_size> struct PlatformCmpxchg;
 297 
 298   // Support for platforms that implement some variants of cmpxchg
 299   // using a (typically out of line) non-template helper function.
 300   // The generic arguments passed to PlatformCmpxchg need to be
 301   // translated to the appropriate type for the helper function, the
 302   // helper invoked on the translated arguments, and the result
 303   // translated back.  Type is the parameter / return type of the
 304   // helper function.
 305   template<typename Type, typename Fn, typename T>
 306   static T cmpxchg_using_helper(Fn fn,
 307                                 T volatile* dest,
 308                                 T compare_value,
 309                                 T exchange_value);
 310 
 311   // Support platforms that do not provide Read-Modify-Write
 312   // byte-level atomic access. To use, derive PlatformCmpxchg<1> from
 313   // this class.
 314 public: // Temporary, can't be private: C++03 11.4/2. Fixed by C++11.
 315   struct CmpxchgByteUsingInt;
 316 private:
 317 
 318   // Dispatch handler for xchg.  Provides type-based validity
 319   // checking and limited conversions around calls to the
 320   // platform-specific implementation layer provided by
 321   // PlatformXchg.
 322   template<typename D, typename T, typename Enable = void>
 323   struct XchgImpl;
 324 
 325   // Platform-specific implementation of xchg.  Support for sizes
 326   // of 4, and sizeof(intptr_t) are required.  The class is a function
 327   // object that must be default constructable, with these requirements:
 328   //
 329   // - dest is of type T*.
 330   // - exchange_value is of type T.
 331   // - platform_xchg is an object of type PlatformXchg<sizeof(T)>.
 332   //
 333   // Then
 334   //   platform_xchg(dest, exchange_value)
 335   // must be a valid expression, returning a result convertible to T.
 336   //
 337   // A default definition is provided, which declares a function template
 338   //   T operator()(T volatile*, T, atomic_memory_order) const
 339   //
 340   // For each required size, a platform must either provide an
 341   // appropriate definition of that function, or must entirely
 342   // specialize the class template for that size.
 343   template<size_t byte_size> struct PlatformXchg;
 344 
 345   // Support for platforms that implement some variants of xchg
 346   // using a (typically out of line) non-template helper function.
 347   // The generic arguments passed to PlatformXchg need to be
 348   // translated to the appropriate type for the helper function, the
 349   // helper invoked on the translated arguments, and the result
 350   // translated back.  Type is the parameter / return type of the
 351   // helper function.
 352   template<typename Type, typename Fn, typename T>
 353   static T xchg_using_helper(Fn fn,
 354                              T volatile* dest,
 355                              T exchange_value);
 356 };
 357 
 358 template<typename From, typename To>
 359 struct Atomic::IsPointerConvertible<From*, To*> : AllStatic {
 360   // Determine whether From* is implicitly convertible to To*, using
 361   // the "sizeof trick".
 362   typedef char yes;
 363   typedef char (&no)[2];
 364 
 365   static yes test(To*);
 366   static no test(...);
 367   static From* test_value;
 368 
 369   static const bool value = (sizeof(yes) == sizeof(test(test_value)));
 370 };
 371 
 372 // Handle load for pointer, integral and enum types.
 373 template<typename T, typename PlatformOp>
 374 struct Atomic::LoadImpl<
 375   T,
 376   PlatformOp,
 377   typename EnableIf<IsIntegral<T>::value || IsRegisteredEnum<T>::value || IsPointer<T>::value>::type>
 378 {
 379   T operator()(T const volatile* dest) const {
 380     // Forward to the platform handler for the size of T.
 381     return PlatformOp()(dest);
 382   }
 383 };
 384 
 385 // Handle load for types that have a translator.
 386 //
 387 // All the involved types must be identical.
 388 //
 389 // This translates the original call into a call on the decayed
 390 // arguments, and returns the recovered result of that translated
 391 // call.
 392 template<typename T, typename PlatformOp>
 393 struct Atomic::LoadImpl<
 394   T,
 395   PlatformOp,
 396   typename EnableIf<PrimitiveConversions::Translate<T>::value>::type>
 397 {
 398   T operator()(T const volatile* dest) const {
 399     typedef PrimitiveConversions::Translate<T> Translator;
 400     typedef typename Translator::Decayed Decayed;
 401     STATIC_ASSERT(sizeof(T) == sizeof(Decayed));
 402     Decayed result = PlatformOp()(reinterpret_cast<Decayed const volatile*>(dest));
 403     return Translator::recover(result);
 404   }
 405 };
 406 
 407 // Default implementation of atomic load if a specific platform
 408 // does not provide a specialization for a certain size class.
 409 // For increased safety, the default implementation only allows
 410 // load types that are pointer sized or smaller. If a platform still
 411 // supports wide atomics, then it has to use specialization
 412 // of Atomic::PlatformLoad for that wider size class.
 413 template<size_t byte_size>
 414 struct Atomic::PlatformLoad {
 415   template<typename T>
 416   T operator()(T const volatile* dest) const {
 417     STATIC_ASSERT(sizeof(T) <= sizeof(void*)); // wide atomics need specialization
 418     return *dest;
 419   }
 420 };
 421 
 422 // Handle store for integral and enum types.
 423 //
 424 // All the involved types must be identical.
 425 template<typename T, typename PlatformOp>
 426 struct Atomic::StoreImpl<
 427   T, T,
 428   PlatformOp,
 429   typename EnableIf<IsIntegral<T>::value || IsRegisteredEnum<T>::value>::type>
 430 {
 431   void operator()(T volatile* dest, T new_value) const {
 432     // Forward to the platform handler for the size of T.
 433     PlatformOp()(dest, new_value);
 434   }
 435 };
 436 
 437 // Handle store for pointer types.
 438 //
 439 // The new_value must be implicitly convertible to the
 440 // destination's type; it must be type-correct to store the
 441 // new_value in the destination.
 442 template<typename D, typename T, typename PlatformOp>
 443 struct Atomic::StoreImpl<
 444   D*, T*,
 445   PlatformOp,
 446   typename EnableIf<Atomic::IsPointerConvertible<T*, D*>::value>::type>
 447 {
 448   void operator()(D* volatile* dest, T* new_value) const {
 449     // Allow derived to base conversion, and adding cv-qualifiers.
 450     D* value = new_value;
 451     PlatformOp()(dest, value);
 452   }
 453 };
 454 
 455 // Handle store for types that have a translator.
 456 //
 457 // All the involved types must be identical.
 458 //
 459 // This translates the original call into a call on the decayed
 460 // arguments.
 461 template<typename T, typename PlatformOp>
 462 struct Atomic::StoreImpl<
 463   T, T,
 464   PlatformOp,
 465   typename EnableIf<PrimitiveConversions::Translate<T>::value>::type>
 466 {
 467   void operator()(T volatile* dest, T new_value) const {
 468     typedef PrimitiveConversions::Translate<T> Translator;
 469     typedef typename Translator::Decayed Decayed;
 470     STATIC_ASSERT(sizeof(T) == sizeof(Decayed));
 471     PlatformOp()(reinterpret_cast<Decayed volatile*>(dest),
 472                  Translator::decay(new_value));
 473   }
 474 };
 475 
 476 // Default implementation of atomic store if a specific platform
 477 // does not provide a specialization for a certain size class.
 478 // For increased safety, the default implementation only allows
 479 // storing types that are pointer sized or smaller. If a platform still
 480 // supports wide atomics, then it has to use specialization
 481 // of Atomic::PlatformStore for that wider size class.
 482 template<size_t byte_size>
 483 struct Atomic::PlatformStore {
 484   template<typename T>
 485   void operator()(T volatile* dest,
 486                   T new_value) const {
 487     STATIC_ASSERT(sizeof(T) <= sizeof(void*)); // wide atomics need specialization
 488     (void)const_cast<T&>(*dest = new_value);
 489   }
 490 };
 491 
 492 template<typename D>
 493 inline void Atomic::inc(D volatile* dest, atomic_memory_order order) {
 494   STATIC_ASSERT(IsPointer<D>::value || IsIntegral<D>::value);
 495   typedef typename Conditional<IsPointer<D>::value, ptrdiff_t, D>::type I;
 496   Atomic::add(dest, I(1), order);
 497 }
 498 
 499 template<typename D>
 500 inline void Atomic::dec(D volatile* dest, atomic_memory_order order) {
 501   STATIC_ASSERT(IsPointer<D>::value || IsIntegral<D>::value);
 502   typedef typename Conditional<IsPointer<D>::value, ptrdiff_t, D>::type I;
 503   // Assumes two's complement integer representation.
 504   #pragma warning(suppress: 4146)
 505   Atomic::add(dest, I(-1), order);
 506 }
 507 
 508 template<typename D, typename I>
 509 inline D Atomic::sub(D volatile* dest, I sub_value, atomic_memory_order order) {
 510   STATIC_ASSERT(IsPointer<D>::value || IsIntegral<D>::value);
 511   STATIC_ASSERT(IsIntegral<I>::value);
 512   // If D is a pointer type, use [u]intptr_t as the addend type,
 513   // matching signedness of I.  Otherwise, use D as the addend type.
 514   typedef typename Conditional<IsSigned<I>::value, intptr_t, uintptr_t>::type PI;
 515   typedef typename Conditional<IsPointer<D>::value, PI, D>::type AddendType;
 516   // Only allow conversions that can't change the value.
 517   STATIC_ASSERT(IsSigned<I>::value == IsSigned<AddendType>::value);
 518   STATIC_ASSERT(sizeof(I) <= sizeof(AddendType));
 519   AddendType addend = sub_value;
 520   // Assumes two's complement integer representation.
 521   #pragma warning(suppress: 4146) // In case AddendType is not signed.
 522   return Atomic::add(dest, -addend, order);
 523 }
 524 
 525 // Define the class before including platform file, which may specialize
 526 // the operator definition.  No generic definition of specializations
 527 // of the operator template are provided, nor are there any generic
 528 // specializations of the class.  The platform file is responsible for
 529 // providing those.
 530 template<size_t byte_size>
 531 struct Atomic::PlatformCmpxchg {
 532   template<typename T>
 533   T operator()(T volatile* dest,
 534                T compare_value,
 535                T exchange_value,
 536                atomic_memory_order order) const;
 537 };
 538 
 539 // Define the class before including platform file, which may use this
 540 // as a base class, requiring it be complete.  The definition is later
 541 // in this file, near the other definitions related to cmpxchg.
 542 struct Atomic::CmpxchgByteUsingInt {
 543   template<typename T>
 544   T operator()(T volatile* dest,
 545                T compare_value,
 546                T exchange_value,
 547                atomic_memory_order order) const;
 548 };
 549 
 550 // Define the class before including platform file, which may specialize
 551 // the operator definition.  No generic definition of specializations
 552 // of the operator template are provided, nor are there any generic
 553 // specializations of the class.  The platform file is responsible for
 554 // providing those.
 555 template<size_t byte_size>
 556 struct Atomic::PlatformXchg {
 557   template<typename T>
 558   T operator()(T volatile* dest,
 559                T exchange_value,
 560                atomic_memory_order order) const;
 561 };
 562 
 563 template <ScopedFenceType T>
 564 class ScopedFenceGeneral: public StackObj {
 565  public:
 566   void prefix() {}
 567   void postfix() {}
 568 };
 569 
 570 // The following methods can be specialized using simple template specialization
 571 // in the platform specific files for optimization purposes. Otherwise the
 572 // generalized variant is used.
 573 
 574 template<> inline void ScopedFenceGeneral<X_ACQUIRE>::postfix()       { OrderAccess::acquire(); }
 575 template<> inline void ScopedFenceGeneral<RELEASE_X>::prefix()        { OrderAccess::release(); }
 576 template<> inline void ScopedFenceGeneral<RELEASE_X_FENCE>::prefix()  { OrderAccess::release(); }
 577 template<> inline void ScopedFenceGeneral<RELEASE_X_FENCE>::postfix() { OrderAccess::fence();   }
 578 
 579 template <ScopedFenceType T>
 580 class ScopedFence : public ScopedFenceGeneral<T> {
 581   void *const _field;
 582  public:
 583   ScopedFence(void *const field) : _field(field) { prefix(); }
 584   ~ScopedFence() { postfix(); }
 585   void prefix() { ScopedFenceGeneral<T>::prefix(); }
 586   void postfix() { ScopedFenceGeneral<T>::postfix(); }
 587 };
 588 
 589 // platform specific in-line definitions - must come before shared definitions
 590 
 591 #include OS_CPU_HEADER(atomic)
 592 
 593 // shared in-line definitions
 594 
 595 // size_t casts...
 596 #if (SIZE_MAX != UINTPTR_MAX)
 597 #error size_t is not WORD_SIZE, interesting platform, but missing implementation here
 598 #endif
 599 
 600 template<typename T>
 601 inline T Atomic::load(const volatile T* dest) {
 602   return LoadImpl<T, PlatformLoad<sizeof(T)> >()(dest);
 603 }
 604 
 605 template<size_t byte_size, ScopedFenceType type>
 606 struct Atomic::PlatformOrderedLoad {
 607   template <typename T>
 608   T operator()(const volatile T* p) const {
 609     ScopedFence<type> f((void*)p);
 610     return Atomic::load(p);
 611   }
 612 };
 613 
 614 template <typename T>
 615 inline T Atomic::load_acquire(const volatile T* p) {
 616   return LoadImpl<T, PlatformOrderedLoad<sizeof(T), X_ACQUIRE> >()(p);
 617 }
 618 
 619 template<typename D, typename T>
 620 inline void Atomic::store(volatile D* dest, T store_value) {
 621   StoreImpl<D, T, PlatformStore<sizeof(D)> >()(dest, store_value);
 622 }
 623 
 624 template<size_t byte_size, ScopedFenceType type>
 625 struct Atomic::PlatformOrderedStore {
 626   template <typename T>
 627   void operator()(volatile T* p, T v) const {
 628     ScopedFence<type> f((void*)p);
 629     Atomic::store(p, v);
 630   }
 631 };
 632 
 633 template <typename D, typename T>
 634 inline void Atomic::release_store(volatile D* p, T v) {
 635   StoreImpl<D, T, PlatformOrderedStore<sizeof(D), RELEASE_X> >()(p, v);
 636 }
 637 
 638 template <typename D, typename T>
 639 inline void Atomic::release_store_fence(volatile D* p, T v) {
 640   StoreImpl<D, T, PlatformOrderedStore<sizeof(D), RELEASE_X_FENCE> >()(p, v);
 641 }
 642 
 643 template<typename D, typename I>
 644 inline D Atomic::add(D volatile* dest, I add_value,
 645                      atomic_memory_order order) {
 646   return AddImpl<D, I>::add_and_fetch(dest, add_value, order);
 647 }
 648 
 649 template<typename D, typename I>
 650 inline D Atomic::fetch_and_add(D volatile* dest, I add_value,
 651                                atomic_memory_order order) {
 652   return AddImpl<D, I>::fetch_and_add(dest, add_value, order);
 653 }
 654 
 655 template<typename D, typename I>
 656 struct Atomic::AddImpl<
 657   D, I,
 658   typename EnableIf<IsIntegral<I>::value &&
 659                     IsIntegral<D>::value &&
 660                     (sizeof(I) <= sizeof(D)) &&
 661                     (IsSigned<I>::value == IsSigned<D>::value)>::type>
 662 {
 663   static D add_and_fetch(D volatile* dest, I add_value, atomic_memory_order order) {
 664     D addend = add_value;
 665     return PlatformAddAndFetch<sizeof(D)>()(dest, addend, order);
 666   }
 667   static D fetch_and_add(D volatile* dest, I add_value, atomic_memory_order order) {
 668     D addend = add_value;
 669     return PlatformFetchAndAdd<sizeof(D)>()(dest, addend, order);
 670   }
 671 };
 672 
 673 template<typename P, typename I>
 674 struct Atomic::AddImpl<
 675   P*, I,
 676   typename EnableIf<IsIntegral<I>::value && (sizeof(I) <= sizeof(P*))>::type>
 677 {
 678   STATIC_ASSERT(sizeof(intptr_t) == sizeof(P*));
 679   STATIC_ASSERT(sizeof(uintptr_t) == sizeof(P*));
 680   typedef typename Conditional<IsSigned<I>::value,
 681                                intptr_t,
 682                                uintptr_t>::type CI;
 683 
 684   static I scale_addend(I add_value) {
 685     return add_value * sizeof(P);
 686   }
 687 
 688   static P* add_and_fetch(P* volatile* dest, I add_value, atomic_memory_order order) {
 689     CI addend = add_value;
 690     return PlatformAddAndFetch<sizeof(P*)>()(dest, scale_addend(addend), order);
 691   }
 692   static P* fetch_and_add(P* volatile* dest, I add_value, atomic_memory_order order) {
 693     CI addend = add_value;
 694     return PlatformFetchAndAdd<sizeof(P*)>()(dest, scale_addend(addend), order);
 695   }
 696 };
 697 
 698 template<typename Type, typename Fn, typename D, typename I>
 699 inline D Atomic::add_using_helper(Fn fn, D volatile* dest, I add_value) {
 700   return PrimitiveConversions::cast<D>(
 701     fn(PrimitiveConversions::cast<Type>(add_value),
 702        reinterpret_cast<Type volatile*>(dest)));
 703 }
 704 
 705 template<typename D, typename U, typename T>
 706 inline D Atomic::cmpxchg(D volatile* dest,
 707                          U compare_value,
 708                          T exchange_value,
 709                          atomic_memory_order order) {
 710   return CmpxchgImpl<D, U, T>()(dest, compare_value, exchange_value, order);
 711 }
 712 
 713 template<typename D, typename T>
 714 inline bool Atomic::replace_if_null(D* volatile* dest, T* value,
 715                                     atomic_memory_order order) {
 716   // Presently using a trivial implementation in terms of cmpxchg.
 717   // Consider adding platform support, to permit the use of compiler
 718   // intrinsics like gcc's __sync_bool_compare_and_swap.
 719   D* expected_null = NULL;
 720   return expected_null == cmpxchg(dest, expected_null, value, order);
 721 }
 722 
 723 // Handle cmpxchg for integral and enum types.
 724 //
 725 // All the involved types must be identical.
 726 template<typename T>
 727 struct Atomic::CmpxchgImpl<
 728   T, T, T,
 729   typename EnableIf<IsIntegral<T>::value || IsRegisteredEnum<T>::value>::type>
 730 {
 731   T operator()(T volatile* dest, T compare_value, T exchange_value,
 732                atomic_memory_order order) const {
 733     // Forward to the platform handler for the size of T.
 734     return PlatformCmpxchg<sizeof(T)>()(dest,
 735                                         compare_value,
 736                                         exchange_value,
 737                                         order);
 738   }
 739 };
 740 
 741 // Handle cmpxchg for pointer types.
 742 //
 743 // The destination's type and the compare_value type must be the same,
 744 // ignoring cv-qualifiers; we don't care about the cv-qualifiers of
 745 // the compare_value.
 746 //
 747 // The exchange_value must be implicitly convertible to the
 748 // destination's type; it must be type-correct to store the
 749 // exchange_value in the destination.
 750 template<typename D, typename U, typename T>
 751 struct Atomic::CmpxchgImpl<
 752   D*, U*, T*,
 753   typename EnableIf<Atomic::IsPointerConvertible<T*, D*>::value &&
 754                     IsSame<typename RemoveCV<D>::type,
 755                            typename RemoveCV<U>::type>::value>::type>
 756 {
 757   D* operator()(D* volatile* dest, U* compare_value, T* exchange_value,
 758                atomic_memory_order order) const {
 759     // Allow derived to base conversion, and adding cv-qualifiers.
 760     D* new_value = exchange_value;
 761     // Don't care what the CV qualifiers for compare_value are,
 762     // but we need to match D* when calling platform support.
 763     D* old_value = const_cast<D*>(compare_value);
 764     return PlatformCmpxchg<sizeof(D*)>()(dest, old_value, new_value, order);
 765   }
 766 };
 767 
 768 // Handle cmpxchg for types that have a translator.
 769 //
 770 // All the involved types must be identical.
 771 //
 772 // This translates the original call into a call on the decayed
 773 // arguments, and returns the recovered result of that translated
 774 // call.
 775 template<typename T>
 776 struct Atomic::CmpxchgImpl<
 777   T, T, T,
 778   typename EnableIf<PrimitiveConversions::Translate<T>::value>::type>
 779 {
 780   T operator()(T volatile* dest, T compare_value, T exchange_value,
 781                atomic_memory_order order) const {
 782     typedef PrimitiveConversions::Translate<T> Translator;
 783     typedef typename Translator::Decayed Decayed;
 784     STATIC_ASSERT(sizeof(T) == sizeof(Decayed));
 785     return Translator::recover(
 786       cmpxchg(reinterpret_cast<Decayed volatile*>(dest),
 787               Translator::decay(compare_value),
 788               Translator::decay(exchange_value),
 789               order));
 790   }
 791 };
 792 
 793 template<typename Type, typename Fn, typename T>
 794 inline T Atomic::cmpxchg_using_helper(Fn fn,
 795                                       T volatile* dest,
 796                                       T compare_value,
 797                                       T exchange_value) {
 798   STATIC_ASSERT(sizeof(Type) == sizeof(T));
 799   return PrimitiveConversions::cast<T>(
 800     fn(PrimitiveConversions::cast<Type>(exchange_value),
 801        reinterpret_cast<Type volatile*>(dest),
 802        PrimitiveConversions::cast<Type>(compare_value)));
 803 }
 804 
 805 template<typename T>
 806 inline T Atomic::CmpxchgByteUsingInt::operator()(T volatile* dest,
 807                                                  T compare_value,
 808                                                  T exchange_value,
 809                                                  atomic_memory_order order) const {
 810   STATIC_ASSERT(sizeof(T) == sizeof(uint8_t));
 811   uint8_t canon_exchange_value = exchange_value;
 812   uint8_t canon_compare_value = compare_value;
 813   volatile uint32_t* aligned_dest
 814     = reinterpret_cast<volatile uint32_t*>(align_down(dest, sizeof(uint32_t)));
 815   size_t offset = pointer_delta(dest, aligned_dest, 1);
 816   uint32_t cur = *aligned_dest;
 817   uint8_t* cur_as_bytes = reinterpret_cast<uint8_t*>(&cur);
 818 
 819   // current value may not be what we are looking for, so force it
 820   // to that value so the initial cmpxchg will fail if it is different
 821   cur_as_bytes[offset] = canon_compare_value;
 822 
 823   // always execute a real cmpxchg so that we get the required memory
 824   // barriers even on initial failure
 825   do {
 826     // value to swap in matches current value ...
 827     uint32_t new_value = cur;
 828     // ... except for the one byte we want to update
 829     reinterpret_cast<uint8_t*>(&new_value)[offset] = canon_exchange_value;
 830 
 831     uint32_t res = cmpxchg(aligned_dest, cur, new_value, order);
 832     if (res == cur) break;      // success
 833 
 834     // at least one byte in the int changed value, so update
 835     // our view of the current int
 836     cur = res;
 837     // if our byte is still as cur we loop and try again
 838   } while (cur_as_bytes[offset] == canon_compare_value);
 839 
 840   return PrimitiveConversions::cast<T>(cur_as_bytes[offset]);
 841 }
 842 
 843 // Handle xchg for integral and enum types.
 844 //
 845 // All the involved types must be identical.
 846 template<typename T>
 847 struct Atomic::XchgImpl<
 848   T, T,
 849   typename EnableIf<IsIntegral<T>::value || IsRegisteredEnum<T>::value>::type>
 850 {
 851   T operator()(T volatile* dest, T exchange_value, atomic_memory_order order) const {
 852     // Forward to the platform handler for the size of T.
 853     return PlatformXchg<sizeof(T)>()(dest, exchange_value, order);
 854   }
 855 };
 856 
 857 // Handle xchg for pointer types.
 858 //
 859 // The exchange_value must be implicitly convertible to the
 860 // destination's type; it must be type-correct to store the
 861 // exchange_value in the destination.
 862 template<typename D, typename T>
 863 struct Atomic::XchgImpl<
 864   D*, T*,
 865   typename EnableIf<Atomic::IsPointerConvertible<T*, D*>::value>::type>
 866 {
 867   D* operator()(D* volatile* dest, T* exchange_value, atomic_memory_order order) const {
 868     // Allow derived to base conversion, and adding cv-qualifiers.
 869     D* new_value = exchange_value;
 870     return PlatformXchg<sizeof(D*)>()(dest, new_value, order);
 871   }
 872 };
 873 
 874 // Handle xchg for types that have a translator.
 875 //
 876 // All the involved types must be identical.
 877 //
 878 // This translates the original call into a call on the decayed
 879 // arguments, and returns the recovered result of that translated
 880 // call.
 881 template<typename T>
 882 struct Atomic::XchgImpl<
 883   T, T,
 884   typename EnableIf<PrimitiveConversions::Translate<T>::value>::type>
 885 {
 886   T operator()(T volatile* dest, T exchange_value, atomic_memory_order order) const {
 887     typedef PrimitiveConversions::Translate<T> Translator;
 888     typedef typename Translator::Decayed Decayed;
 889     STATIC_ASSERT(sizeof(T) == sizeof(Decayed));
 890     return Translator::recover(
 891       xchg(reinterpret_cast<Decayed volatile*>(dest),
 892            Translator::decay(exchange_value),
 893            order));
 894   }
 895 };
 896 
 897 template<typename Type, typename Fn, typename T>
 898 inline T Atomic::xchg_using_helper(Fn fn,
 899                                    T volatile* dest,
 900                                    T exchange_value) {
 901   STATIC_ASSERT(sizeof(Type) == sizeof(T));
 902   // Notice the swapped order of arguments. Change when/if stubs are rewritten.
 903   return PrimitiveConversions::cast<T>(
 904     fn(PrimitiveConversions::cast<Type>(exchange_value),
 905        reinterpret_cast<Type volatile*>(dest)));
 906 }
 907 
 908 template<typename D, typename T>
 909 inline D Atomic::xchg(volatile D* dest, T exchange_value, atomic_memory_order order) {
 910   return XchgImpl<D, T>()(dest, exchange_value, order);
 911 }
 912 
 913 #endif // SHARE_RUNTIME_ATOMIC_HPP