< prev index next >

src/hotspot/share/runtime/atomic.hpp

Print this page




  53 
  54   // The memory operations that are mentioned with each of the atomic
  55   // function families come from src/share/vm/runtime/orderAccess.hpp,
  56   // e.g., <fence> is described in that file and is implemented by the
  57   // OrderAccess::fence() function. See that file for the gory details
  58   // on the Memory Access Ordering Model.
  59 
  60   // All of the atomic operations that imply a read-modify-write action
  61   // guarantee a two-way memory barrier across that operation. Historically
  62   // these semantics reflect the strength of atomic operations that are
  63   // provided on SPARC/X86. We assume that strength is necessary unless
  64   // we can prove that a weaker form is sufficiently safe.
  65 
  66   // Atomically store to a location
  67   // The type T must be either a pointer type convertible to or equal
  68   // to D, an integral/enum type equal to D, or a type equal to D that
  69   // is primitive convertible using PrimitiveConversions.
  70   template<typename T, typename D>
  71   inline static void store(T store_value, volatile D* dest);
  72 
  73   inline static void store_ptr(intptr_t store_value, volatile intptr_t* dest) {
  74     Atomic::store(store_value, dest);
  75   }
  76 
  77   inline static void store_ptr(void*    store_value, volatile void*     dest) {
  78     Atomic::store(store_value, reinterpret_cast<void* volatile*>(dest));
  79   }
  80 
  81   // Atomically load from a location
  82   // The type T must be either a pointer type, an integral/enum type,
  83   // or a type that is primitive convertible using PrimitiveConversions.
  84   template<typename T>
  85   inline static T load(const volatile T* dest);
  86 
  87   // Atomically add to a location. Returns updated value. add*() provide:
  88   // <fence> add-value-to-dest <membar StoreLoad|StoreStore>
  89 
  90   template<typename I, typename D>
  91   inline static D add(I add_value, D volatile* dest);
  92 
  93   inline static intptr_t add_ptr(intptr_t add_value, volatile intptr_t* dest) {
  94     return add(add_value, dest);
  95   }
  96 
  97   inline static void* add_ptr(intptr_t add_value, volatile void* dest) {
  98     return add(add_value, reinterpret_cast<char* volatile*>(dest));
  99   }
 100 
 101   // Atomically increment location. inc() provide:
 102   // <fence> increment-dest <membar StoreLoad|StoreStore>
 103   // The type D may be either a pointer type, or an integral
 104   // type. If it is a pointer type, then the increment is
 105   // scaled to the size of the type pointed to by the pointer.
 106   template<typename D>
 107   inline static void inc(D volatile* dest);
 108 
 109   // Atomically decrement a location. dec() provide:
 110   // <fence> decrement-dest <membar StoreLoad|StoreStore>
 111   // The type D may be either a pointer type, or an integral
 112   // type. If it is a pointer type, then the decrement is
 113   // scaled to the size of the type pointed to by the pointer.
 114   template<typename D>
 115   inline static void dec(D volatile* dest);
 116 
 117   // Performs atomic exchange of *dest with exchange_value. Returns old
 118   // prior value of *dest. xchg*() provide:
 119   // <fence> exchange-value-with-dest <membar StoreLoad|StoreStore>
 120   // The type T must be either a pointer type convertible to or equal
 121   // to D, an integral/enum type equal to D, or a type equal to D that
 122   // is primitive convertible using PrimitiveConversions.
 123   template<typename T, typename D>
 124   inline static D xchg(T exchange_value, volatile D* dest);
 125 
 126   inline static intptr_t xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) {
 127     return xchg(exchange_value, dest);
 128   }
 129 
 130   inline static void*    xchg_ptr(void*    exchange_value, volatile void*     dest) {
 131     return xchg(exchange_value, reinterpret_cast<void* volatile*>(dest));
 132   }
 133 
 134   // Performs atomic compare of *dest and compare_value, and exchanges
 135   // *dest with exchange_value if the comparison succeeded. Returns prior
 136   // value of *dest. cmpxchg*() provide:
 137   // <fence> compare-and-exchange <membar StoreLoad|StoreStore>
 138 
 139   template<typename T, typename D, typename U>
 140   inline static D cmpxchg(T exchange_value,
 141                           D volatile* dest,
 142                           U compare_value,
 143                           cmpxchg_memory_order order = memory_order_conservative);
 144 
 145   // Performs atomic compare of *dest and NULL, and replaces *dest
 146   // with exchange_value if the comparison succeeded.  Returns true if
 147   // the comparison succeeded and the exchange occurred.  This is
 148   // often used as part of lazy initialization, as a lock-free
 149   // alternative to the Double-Checked Locking Pattern.
 150   template<typename T, typename D>
 151   inline static bool replace_if_null(T* value, D* volatile* dest,
 152                                      cmpxchg_memory_order order = memory_order_conservative);
 153 
 154   inline static intptr_t cmpxchg_ptr(intptr_t exchange_value,
 155                                      volatile intptr_t* dest,
 156                                      intptr_t compare_value,
 157                                      cmpxchg_memory_order order = memory_order_conservative) {
 158     return cmpxchg(exchange_value, dest, compare_value, order);
 159   }
 160 
 161   inline static void* cmpxchg_ptr(void* exchange_value,
 162                                   volatile void* dest,
 163                                   void* compare_value,
 164                                   cmpxchg_memory_order order = memory_order_conservative) {
 165     return cmpxchg(exchange_value,
 166                    reinterpret_cast<void* volatile*>(dest),
 167                    compare_value,
 168                    order);
 169   }
 170 
 171 private:
 172   // Test whether From is implicitly convertible to To.
 173   // From and To must be pointer types.
 174   // Note: Provides the limited subset of C++11 std::is_convertible
 175   // that is needed here.
 176   template<typename From, typename To> struct IsPointerConvertible;
 177 
 178 protected:
 179   // Dispatch handler for store.  Provides type-based validity
 180   // checking and limited conversions around calls to the platform-
 181   // specific implementation layer provided by PlatformOp.
 182   template<typename T, typename D, typename PlatformOp, typename Enable = void>
 183   struct StoreImpl;
 184 
 185   // Platform-specific implementation of store.  Support for sizes
 186   // of 1, 2, 4, and (if different) pointer size bytes are required.
 187   // The class is a function object that must be default constructable,
 188   // with these requirements:
 189   //
 190   // either:


 536 template<typename Derived>
 537 struct Atomic::AddAndFetch VALUE_OBJ_CLASS_SPEC {
 538   template<typename I, typename D>
 539   D operator()(I add_value, D volatile* dest) const;
 540 };
 541 
 542 template<typename D>
 543 inline void Atomic::inc(D volatile* dest) {
 544   STATIC_ASSERT(IsPointer<D>::value || IsIntegral<D>::value);
 545   typedef typename Conditional<IsPointer<D>::value, ptrdiff_t, D>::type I;
 546   Atomic::add(I(1), dest);
 547 }
 548 
 549 template<typename D>
 550 inline void Atomic::dec(D volatile* dest) {
 551   STATIC_ASSERT(IsPointer<D>::value || IsIntegral<D>::value);
 552   typedef typename Conditional<IsPointer<D>::value, ptrdiff_t, D>::type I;
 553   // Assumes two's complement integer representation.
 554   #pragma warning(suppress: 4146)
 555   Atomic::add(I(-1), dest);













 556 }
 557 
 558 // Define the class before including platform file, which may specialize
 559 // the operator definition.  No generic definition of specializations
 560 // of the operator template are provided, nor are there any generic
 561 // specializations of the class.  The platform file is responsible for
 562 // providing those.
 563 template<size_t byte_size>
 564 struct Atomic::PlatformCmpxchg VALUE_OBJ_CLASS_SPEC {
 565   template<typename T>
 566   T operator()(T exchange_value,
 567                T volatile* dest,
 568                T compare_value,
 569                cmpxchg_memory_order order) const;
 570 };
 571 
 572 // Define the class before including platform file, which may use this
 573 // as a base class, requiring it be complete.  The definition is later
 574 // in this file, near the other definitions related to cmpxchg.
 575 struct Atomic::CmpxchgByteUsingInt VALUE_OBJ_CLASS_SPEC {




  53 
  54   // The memory operations that are mentioned with each of the atomic
  55   // function families come from src/share/vm/runtime/orderAccess.hpp,
  56   // e.g., <fence> is described in that file and is implemented by the
  57   // OrderAccess::fence() function. See that file for the gory details
  58   // on the Memory Access Ordering Model.
  59 
  60   // All of the atomic operations that imply a read-modify-write action
  61   // guarantee a two-way memory barrier across that operation. Historically
  62   // these semantics reflect the strength of atomic operations that are
  63   // provided on SPARC/X86. We assume that strength is necessary unless
  64   // we can prove that a weaker form is sufficiently safe.
  65 
  66   // Atomically store to a location
  67   // The type T must be either a pointer type convertible to or equal
  68   // to D, an integral/enum type equal to D, or a type equal to D that
  69   // is primitive convertible using PrimitiveConversions.
  70   template<typename T, typename D>
  71   inline static void store(T store_value, volatile D* dest);
  72 








  73   // Atomically load from a location
  74   // The type T must be either a pointer type, an integral/enum type,
  75   // or a type that is primitive convertible using PrimitiveConversions.
  76   template<typename T>
  77   inline static T load(const volatile T* dest);
  78 
  79   // Atomically add to a location. Returns updated value. add*() provide:
  80   // <fence> add-value-to-dest <membar StoreLoad|StoreStore>
  81 
  82   template<typename I, typename D>
  83   inline static D add(I add_value, D volatile* dest);
  84 
  85   template<typename I, typename D>
  86   inline static D sub(I sub_value, D volatile* dest);





  87 
  88   // Atomically increment location. inc() provide:
  89   // <fence> increment-dest <membar StoreLoad|StoreStore>
  90   // The type D may be either a pointer type, or an integral
  91   // type. If it is a pointer type, then the increment is
  92   // scaled to the size of the type pointed to by the pointer.
  93   template<typename D>
  94   inline static void inc(D volatile* dest);
  95 
  96   // Atomically decrement a location. dec() provide:
  97   // <fence> decrement-dest <membar StoreLoad|StoreStore>
  98   // The type D may be either a pointer type, or an integral
  99   // type. If it is a pointer type, then the decrement is
 100   // scaled to the size of the type pointed to by the pointer.
 101   template<typename D>
 102   inline static void dec(D volatile* dest);
 103 
 104   // Performs atomic exchange of *dest with exchange_value. Returns old
 105   // prior value of *dest. xchg*() provide:
 106   // <fence> exchange-value-with-dest <membar StoreLoad|StoreStore>
 107   // The type T must be either a pointer type convertible to or equal
 108   // to D, an integral/enum type equal to D, or a type equal to D that
 109   // is primitive convertible using PrimitiveConversions.
 110   template<typename T, typename D>
 111   inline static D xchg(T exchange_value, volatile D* dest);
 112 








 113   // Performs atomic compare of *dest and compare_value, and exchanges
 114   // *dest with exchange_value if the comparison succeeded. Returns prior
 115   // value of *dest. cmpxchg*() provide:
 116   // <fence> compare-and-exchange <membar StoreLoad|StoreStore>
 117 
 118   template<typename T, typename D, typename U>
 119   inline static D cmpxchg(T exchange_value,
 120                           D volatile* dest,
 121                           U compare_value,
 122                           cmpxchg_memory_order order = memory_order_conservative);
 123 
 124   // Performs atomic compare of *dest and NULL, and replaces *dest
 125   // with exchange_value if the comparison succeeded.  Returns true if
 126   // the comparison succeeded and the exchange occurred.  This is
 127   // often used as part of lazy initialization, as a lock-free
 128   // alternative to the Double-Checked Locking Pattern.
 129   template<typename T, typename D>
 130   inline static bool replace_if_null(T* value, D* volatile* dest,
 131                                      cmpxchg_memory_order order = memory_order_conservative);
 132 

















 133 private:
 134   // Test whether From is implicitly convertible to To.
 135   // From and To must be pointer types.
 136   // Note: Provides the limited subset of C++11 std::is_convertible
 137   // that is needed here.
 138   template<typename From, typename To> struct IsPointerConvertible;
 139 
 140 protected:
 141   // Dispatch handler for store.  Provides type-based validity
 142   // checking and limited conversions around calls to the platform-
 143   // specific implementation layer provided by PlatformOp.
 144   template<typename T, typename D, typename PlatformOp, typename Enable = void>
 145   struct StoreImpl;
 146 
 147   // Platform-specific implementation of store.  Support for sizes
 148   // of 1, 2, 4, and (if different) pointer size bytes are required.
 149   // The class is a function object that must be default constructable,
 150   // with these requirements:
 151   //
 152   // either:


 498 template<typename Derived>
 499 struct Atomic::AddAndFetch VALUE_OBJ_CLASS_SPEC {
 500   template<typename I, typename D>
 501   D operator()(I add_value, D volatile* dest) const;
 502 };
 503 
 504 template<typename D>
 505 inline void Atomic::inc(D volatile* dest) {
 506   STATIC_ASSERT(IsPointer<D>::value || IsIntegral<D>::value);
 507   typedef typename Conditional<IsPointer<D>::value, ptrdiff_t, D>::type I;
 508   Atomic::add(I(1), dest);
 509 }
 510 
 511 template<typename D>
 512 inline void Atomic::dec(D volatile* dest) {
 513   STATIC_ASSERT(IsPointer<D>::value || IsIntegral<D>::value);
 514   typedef typename Conditional<IsPointer<D>::value, ptrdiff_t, D>::type I;
 515   // Assumes two's complement integer representation.
 516   #pragma warning(suppress: 4146)
 517   Atomic::add(I(-1), dest);
 518 }
 519 
 520 template<typename I, typename D>
 521 inline D Atomic::sub(I sub_value, D volatile* dest) {
 522   STATIC_ASSERT(IsPointer<D>::value || IsIntegral<D>::value);
 523   STATIC_ASSERT(IsIntegral<I>::value);
 524   typedef typename Conditional<IsPointer<D>::value, ptrdiff_t, D>::type AddendType;
 525   AddendType addend = sub_value;
 526   STATIC_ASSERT((IsIntegral<D>::value && IsSigned<I>::value == IsSigned<AddendType>::value) ||
 527                 IsPointer<D>::value);
 528   // Assumes two's complement integer representation.
 529   #pragma warning(suppress: 4146)
 530   return Atomic::add(-addend, dest);
 531 }
 532 
 533 // Define the class before including platform file, which may specialize
 534 // the operator definition.  No generic definition of specializations
 535 // of the operator template are provided, nor are there any generic
 536 // specializations of the class.  The platform file is responsible for
 537 // providing those.
 538 template<size_t byte_size>
 539 struct Atomic::PlatformCmpxchg VALUE_OBJ_CLASS_SPEC {
 540   template<typename T>
 541   T operator()(T exchange_value,
 542                T volatile* dest,
 543                T compare_value,
 544                cmpxchg_memory_order order) const;
 545 };
 546 
 547 // Define the class before including platform file, which may use this
 548 // as a base class, requiring it be complete.  The definition is later
 549 // in this file, near the other definitions related to cmpxchg.
 550 struct Atomic::CmpxchgByteUsingInt VALUE_OBJ_CLASS_SPEC {


< prev index next >