src/hotspot/share/runtime/atomic.hpp
changeset 59251 4cbfa5077d68
parent 59250 a6deb69743d4
child 59252 623722a6aeb9
equal deleted inserted replaced
59250:a6deb69743d4 59251:4cbfa5077d68
   130   // prior value of *dest. xchg*() provide:
   130   // prior value of *dest. xchg*() provide:
   131   // <fence> exchange-value-with-dest <membar StoreLoad|StoreStore>
   131   // <fence> exchange-value-with-dest <membar StoreLoad|StoreStore>
   132   // The type T must be either a pointer type convertible to or equal
   132   // The type T must be either a pointer type convertible to or equal
   133   // to D, an integral/enum type equal to D, or a type equal to D that
   133   // to D, an integral/enum type equal to D, or a type equal to D that
   134   // is primitive convertible using PrimitiveConversions.
   134   // is primitive convertible using PrimitiveConversions.
   135   template<typename T, typename D>
   135   template<typename D, typename T>
   136   inline static D xchg(T exchange_value, volatile D* dest,
   136   inline static D xchg(volatile D* dest, T exchange_value,
   137                        atomic_memory_order order = memory_order_conservative);
   137                        atomic_memory_order order = memory_order_conservative);
   138 
   138 
   139   // Performs atomic compare of *dest and compare_value, and exchanges
   139   // Performs atomic compare of *dest and compare_value, and exchanges
   140   // *dest with exchange_value if the comparison succeeded. Returns prior
   140   // *dest with exchange_value if the comparison succeeded. Returns prior
   141   // value of *dest. cmpxchg*() provide:
   141   // value of *dest. cmpxchg*() provide:
   339 
   339 
   340   // Dispatch handler for xchg.  Provides type-based validity
   340   // Dispatch handler for xchg.  Provides type-based validity
   341   // checking and limited conversions around calls to the
   341   // checking and limited conversions around calls to the
   342   // platform-specific implementation layer provided by
   342   // platform-specific implementation layer provided by
   343   // PlatformXchg.
   343   // PlatformXchg.
   344   template<typename T, typename D, typename Enable = void>
   344   template<typename D, typename T, typename Enable = void>
   345   struct XchgImpl;
   345   struct XchgImpl;
   346 
   346 
   347   // Platform-specific implementation of xchg.  Support for sizes
   347   // Platform-specific implementation of xchg.  Support for sizes
   348   // of 4, and sizeof(intptr_t) are required.  The class is a function
   348   // of 4, and sizeof(intptr_t) are required.  The class is a function
   349   // object that must be default constructable, with these requirements:
   349   // object that must be default constructable, with these requirements:
   351   // - dest is of type T*.
   351   // - dest is of type T*.
   352   // - exchange_value is of type T.
   352   // - exchange_value is of type T.
   353   // - platform_xchg is an object of type PlatformXchg<sizeof(T)>.
   353   // - platform_xchg is an object of type PlatformXchg<sizeof(T)>.
   354   //
   354   //
   355   // Then
   355   // Then
   356   //   platform_xchg(exchange_value, dest)
   356   //   platform_xchg(dest, exchange_value)
   357   // must be a valid expression, returning a result convertible to T.
   357   // must be a valid expression, returning a result convertible to T.
   358   //
   358   //
   359   // A default definition is provided, which declares a function template
   359   // A default definition is provided, which declares a function template
   360   //   T operator()(T, T volatile*, T, atomic_memory_order) const
   360   //   T operator()(T volatile*, T, atomic_memory_order) const
   361   //
   361   //
   362   // For each required size, a platform must either provide an
   362   // For each required size, a platform must either provide an
   363   // appropriate definition of that function, or must entirely
   363   // appropriate definition of that function, or must entirely
   364   // specialize the class template for that size.
   364   // specialize the class template for that size.
   365   template<size_t byte_size> struct PlatformXchg;
   365   template<size_t byte_size> struct PlatformXchg;
   371   // helper invoked on the translated arguments, and the result
   371   // helper invoked on the translated arguments, and the result
   372   // translated back.  Type is the parameter / return type of the
   372   // translated back.  Type is the parameter / return type of the
   373   // helper function.
   373   // helper function.
   374   template<typename Type, typename Fn, typename T>
   374   template<typename Type, typename Fn, typename T>
   375   static T xchg_using_helper(Fn fn,
   375   static T xchg_using_helper(Fn fn,
   376                              T exchange_value,
   376                              T volatile* dest,
   377                              T volatile* dest);
   377                              T exchange_value);
   378 };
   378 };
   379 
   379 
   380 template<typename From, typename To>
   380 template<typename From, typename To>
   381 struct Atomic::IsPointerConvertible<From*, To*> : AllStatic {
   381 struct Atomic::IsPointerConvertible<From*, To*> : AllStatic {
   382   // Determine whether From* is implicitly convertible to To*, using
   382   // Determine whether From* is implicitly convertible to To*, using
   591 // specializations of the class.  The platform file is responsible for
   591 // specializations of the class.  The platform file is responsible for
   592 // providing those.
   592 // providing those.
   593 template<size_t byte_size>
   593 template<size_t byte_size>
   594 struct Atomic::PlatformXchg {
   594 struct Atomic::PlatformXchg {
   595   template<typename T>
   595   template<typename T>
   596   T operator()(T exchange_value,
   596   T operator()(T volatile* dest,
   597                T volatile* dest,
   597                T exchange_value,
   598                atomic_memory_order order) const;
   598                atomic_memory_order order) const;
   599 };
   599 };
   600 
   600 
   601 template <ScopedFenceType T>
   601 template <ScopedFenceType T>
   602 class ScopedFenceGeneral: public StackObj {
   602 class ScopedFenceGeneral: public StackObj {
   889 template<typename T>
   889 template<typename T>
   890 struct Atomic::XchgImpl<
   890 struct Atomic::XchgImpl<
   891   T, T,
   891   T, T,
   892   typename EnableIf<IsIntegral<T>::value || IsRegisteredEnum<T>::value>::type>
   892   typename EnableIf<IsIntegral<T>::value || IsRegisteredEnum<T>::value>::type>
   893 {
   893 {
   894   T operator()(T exchange_value, T volatile* dest, atomic_memory_order order) const {
   894   T operator()(T volatile* dest, T exchange_value, atomic_memory_order order) const {
   895     // Forward to the platform handler for the size of T.
   895     // Forward to the platform handler for the size of T.
   896     return PlatformXchg<sizeof(T)>()(exchange_value, dest, order);
   896     return PlatformXchg<sizeof(T)>()(dest, exchange_value, order);
   897   }
   897   }
   898 };
   898 };
   899 
   899 
   900 // Handle xchg for pointer types.
   900 // Handle xchg for pointer types.
   901 //
   901 //
   902 // The exchange_value must be implicitly convertible to the
   902 // The exchange_value must be implicitly convertible to the
   903 // destination's type; it must be type-correct to store the
   903 // destination's type; it must be type-correct to store the
   904 // exchange_value in the destination.
   904 // exchange_value in the destination.
   905 template<typename T, typename D>
   905 template<typename D, typename T>
   906 struct Atomic::XchgImpl<
   906 struct Atomic::XchgImpl<
   907   T*, D*,
   907   D*, T*,
   908   typename EnableIf<Atomic::IsPointerConvertible<T*, D*>::value>::type>
   908   typename EnableIf<Atomic::IsPointerConvertible<T*, D*>::value>::type>
   909 {
   909 {
   910   D* operator()(T* exchange_value, D* volatile* dest, atomic_memory_order order) const {
   910   D* operator()(D* volatile* dest, T* exchange_value, atomic_memory_order order) const {
   911     // Allow derived to base conversion, and adding cv-qualifiers.
   911     // Allow derived to base conversion, and adding cv-qualifiers.
   912     D* new_value = exchange_value;
   912     D* new_value = exchange_value;
   913     return PlatformXchg<sizeof(D*)>()(new_value, dest, order);
   913     return PlatformXchg<sizeof(D*)>()(dest, new_value, order);
   914   }
   914   }
   915 };
   915 };
   916 
   916 
   917 // Handle xchg for types that have a translator.
   917 // Handle xchg for types that have a translator.
   918 //
   918 //
   924 template<typename T>
   924 template<typename T>
   925 struct Atomic::XchgImpl<
   925 struct Atomic::XchgImpl<
   926   T, T,
   926   T, T,
   927   typename EnableIf<PrimitiveConversions::Translate<T>::value>::type>
   927   typename EnableIf<PrimitiveConversions::Translate<T>::value>::type>
   928 {
   928 {
   929   T operator()(T exchange_value, T volatile* dest, atomic_memory_order order) const {
   929   T operator()(T volatile* dest, T exchange_value, atomic_memory_order order) const {
   930     typedef PrimitiveConversions::Translate<T> Translator;
   930     typedef PrimitiveConversions::Translate<T> Translator;
   931     typedef typename Translator::Decayed Decayed;
   931     typedef typename Translator::Decayed Decayed;
   932     STATIC_ASSERT(sizeof(T) == sizeof(Decayed));
   932     STATIC_ASSERT(sizeof(T) == sizeof(Decayed));
   933     return Translator::recover(
   933     return Translator::recover(
   934       xchg(Translator::decay(exchange_value),
   934       xchg(reinterpret_cast<Decayed volatile*>(dest),
   935            reinterpret_cast<Decayed volatile*>(dest),
   935            Translator::decay(exchange_value),
   936            order));
   936            order));
   937   }
   937   }
   938 };
   938 };
   939 
   939 
   940 template<typename Type, typename Fn, typename T>
   940 template<typename Type, typename Fn, typename T>
   941 inline T Atomic::xchg_using_helper(Fn fn,
   941 inline T Atomic::xchg_using_helper(Fn fn,
   942                                    T exchange_value,
   942                                    T volatile* dest,
   943                                    T volatile* dest) {
   943                                    T exchange_value) {
   944   STATIC_ASSERT(sizeof(Type) == sizeof(T));
   944   STATIC_ASSERT(sizeof(Type) == sizeof(T));
       
   945   // Notice the swapped order of arguments. Change when/if stubs are rewritten.
   945   return PrimitiveConversions::cast<T>(
   946   return PrimitiveConversions::cast<T>(
   946     fn(PrimitiveConversions::cast<Type>(exchange_value),
   947     fn(PrimitiveConversions::cast<Type>(exchange_value),
   947        reinterpret_cast<Type volatile*>(dest)));
   948        reinterpret_cast<Type volatile*>(dest)));
   948 }
   949 }
   949 
   950 
   950 template<typename T, typename D>
   951 template<typename D, typename T>
   951 inline D Atomic::xchg(T exchange_value, volatile D* dest, atomic_memory_order order) {
   952 inline D Atomic::xchg(volatile D* dest, T exchange_value, atomic_memory_order order) {
   952   return XchgImpl<T, D>()(exchange_value, dest, order);
   953   return XchgImpl<D, T>()(dest, exchange_value, order);
   953 }
   954 }
   954 
   955 
   955 #endif // SHARE_RUNTIME_ATOMIC_HPP
   956 #endif // SHARE_RUNTIME_ATOMIC_HPP