< prev index next >

src/hotspot/share/runtime/atomic.hpp

Print this page
rev 47321 : [mq]: Atomic_loadstore

*** 62,89 **** // these semantics reflect the strength of atomic operations that are // provided on SPARC/X86. We assume that strength is necessary unless // we can prove that a weaker form is sufficiently safe. // Atomically store to a location - inline static void store (jbyte store_value, jbyte* dest); - inline static void store (jshort store_value, jshort* dest); - inline static void store (jint store_value, jint* dest); // See comment above about using jlong atomics on 32-bit platforms ! inline static void store (jlong store_value, jlong* dest); ! inline static void store_ptr(intptr_t store_value, intptr_t* dest); ! inline static void store_ptr(void* store_value, void* dest); ! ! inline static void store (jbyte store_value, volatile jbyte* dest); ! inline static void store (jshort store_value, volatile jshort* dest); ! inline static void store (jint store_value, volatile jint* dest); ! // See comment above about using jlong atomics on 32-bit platforms ! inline static void store (jlong store_value, volatile jlong* dest); ! inline static void store_ptr(intptr_t store_value, volatile intptr_t* dest); ! inline static void store_ptr(void* store_value, volatile void* dest); // See comment above about using jlong atomics on 32-bit platforms ! inline static jlong load(const volatile jlong* src); // Atomically add to a location. Returns updated value. add*() provide: // <fence> add-value-to-dest <membar StoreLoad|StoreStore> template<typename I, typename D> --- 62,92 ---- // these semantics reflect the strength of atomic operations that are // provided on SPARC/X86. We assume that strength is necessary unless // we can prove that a weaker form is sufficiently safe. // Atomically store to a location // See comment above about using jlong atomics on 32-bit platforms ! // The type T must be either a pointer type convertible to or equal ! // to D, an integral/enum type equal to D, or a type equal to D that ! // is primitive convertible using PrimitiveConversions. ! template<typename T, typename D> ! inline static void store(T store_value, volatile D* dest); ! ! inline static void store_ptr(intptr_t store_value, volatile intptr_t* dest) { ! Atomic::store(store_value, dest); ! } + inline static void store_ptr(void* store_value, volatile void* dest) { + Atomic::store(store_value, reinterpret_cast<void* volatile*>(dest)); + } + + // Atomically load from a location // See comment above about using jlong atomics on 32-bit platforms ! // The type T must be either a pointer type, an integral/enum type, ! // or a type that is primitive convertible using PrimitiveConversions. ! template<typename T> ! inline static T load(const volatile T* dest); // Atomically add to a location. Returns updated value. add*() provide: // <fence> add-value-to-dest <membar StoreLoad|StoreStore> template<typename I, typename D>
*** 172,181 **** --- 175,235 ---- // From and To must be pointer types. // Note: Provides the limited subset of C++11 std::is_convertible // that is needed here. template<typename From, typename To> struct IsPointerConvertible; + // Dispatch handler for store. Provides type-based validity + // checking and limited conversions around calls to the platform- + // specific implementation layer provided by PlatformOp. + template<typename T, typename D, typename PlatformOp, typename Enable = void> + struct StoreImpl; + + // Platform-specific implementation of store. Support for sizes + // of 1, 2, 4, and (if different) pointer size bytes are required. + // The class is a function object that must be default constructable, + // with these requirements: + // + // either: + // - dest is of type D*, an integral, enum or pointer type. + // - new_value are of type T, an integral, enum or pointer type D or + // pointer type convertible to D. + // or: + // - T and D are the same and are primitive convertible using PrimitiveConversions + // and either way: + // - platform_store is an object of type PlatformStore<sizeof(T)>. + // + // Then + // platform_store(new_value, dest) + // must be a valid expression. + // + // The default implementation is a volatile store. If a platform + // requires more for e.g. 64 bit stores, a specialization is required + template<size_t byte_size> struct PlatformStore; + + // Dispatch handler for load. Provides type-based validity + // checking and limited conversions around calls to the platform- + // specific implementation layer provided by PlatformOp. + template<typename T, typename PlatformOp, typename Enable = void> + struct LoadImpl; + + // Platform-specific implementation of load. Support for sizes of + // 1, 2, 4 bytes and (if different) pointer size bytes are required. + // The class is a function object that must be default + // constructable, with these requirements: + // + // - dest is of type T*, an integral, enum or pointer type, or + // T is convertible to a primitive type using PrimitiveConversions + // - platform_load is an object of type PlatformLoad<sizeof(T)>. + // + // Then + // platform_load(src) + // must be a valid expression, returning a result convertible to T. + // + // The default implementation is a volatile load. If a platform + // requires more for e.g. 64 bit loads, a specialization is required + template<size_t byte_size> struct PlatformLoad; + // Dispatch handler for add. Provides type-based validity checking // and limited conversions around calls to the platform-specific // implementation layer provided by PlatformAdd. template<typename I, typename D, typename Enable = void> struct AddImpl;
*** 342,351 **** --- 396,530 ---- static From* test_value; static const bool value = (sizeof(yes) == sizeof(test(test_value))); }; + // Handle load for pointer, integral and enum types. + template<typename T, typename PlatformOp> + struct Atomic::LoadImpl< + T, + PlatformOp, + typename EnableIf<IsIntegral<T>::value || IsRegisteredEnum<T>::value || IsPointer<T>::value>::type> + VALUE_OBJ_CLASS_SPEC + { + T operator()(T const volatile* dest) const { + // Forward to the platform handler for the size of T. + return PlatformOp()(dest); + } + }; + + // Handle load for types that have a translator. + // + // All the involved types must be identical. + // + // This translates the original call into a call on the decayed + // arguments, and returns the recovered result of that translated + // call. + template<typename T, typename PlatformOp> + struct Atomic::LoadImpl< + T, + PlatformOp, + typename EnableIf<PrimitiveConversions::Translate<T>::value>::type> + VALUE_OBJ_CLASS_SPEC + { + T operator()(T const volatile* dest) const { + typedef PrimitiveConversions::Translate<T> Translator; + typedef typename Translator::Decayed Decayed; + STATIC_ASSERT(sizeof(T) == sizeof(Decayed)); + Decayed result = PlatformOp()(reinterpret_cast<Decayed const volatile*>(dest)); + return Translator::recover(result); + } + }; + + // Default implementation of atomic load if a specific platform + // does not provide a specialization for a certain size class. + // For increased safety, the default implementation only allows + // load types that are pointer sized or smaller. If a platform still + // supports wide atomics, then it has to use specialization + // of Atomic::PlatformLoad for that wider size class. + template<size_t byte_size> + struct Atomic::PlatformLoad VALUE_OBJ_CLASS_SPEC { + template<typename T> + T operator()(T const volatile* dest) const { + STATIC_ASSERT(sizeof(T) <= sizeof(void*)); // wide atomics need specialization + return *dest; + } + }; + + // Handle store for integral and enum types. + // + // All the involved types must be identical. + template<typename T, typename PlatformOp> + struct Atomic::StoreImpl< + T, T, + PlatformOp, + typename EnableIf<IsIntegral<T>::value || IsRegisteredEnum<T>::value>::type> + VALUE_OBJ_CLASS_SPEC + { + void operator()(T new_value, T volatile* dest) const { + // Forward to the platform handler for the size of T. + PlatformOp()(new_value, dest); + } + }; + + // Handle store for pointer types. + // + // The new_value must be implicitly convertible to the + // destination's type; it must be type-correct to store the + // new_value in the destination. + template<typename T, typename D, typename PlatformOp> + struct Atomic::StoreImpl< + T*, D*, + PlatformOp, + typename EnableIf<Atomic::IsPointerConvertible<T*, D*>::value>::type> + VALUE_OBJ_CLASS_SPEC + { + void operator()(T* new_value, D* volatile* dest) const { + // Allow derived to base conversion, and adding cv-qualifiers. + D* value = new_value; + PlatformOp()(value, dest); + } + }; + + // Handle store for types that have a translator. + // + // All the involved types must be identical. + // + // This translates the original call into a call on the decayed + // arguments. + template<typename T, typename PlatformOp> + struct Atomic::StoreImpl< + T, T, + PlatformOp, + typename EnableIf<PrimitiveConversions::Translate<T>::value>::type> + VALUE_OBJ_CLASS_SPEC + { + void operator()(T new_value, T volatile* dest) const { + typedef PrimitiveConversions::Translate<T> Translator; + typedef typename Translator::Decayed Decayed; + STATIC_ASSERT(sizeof(T) == sizeof(Decayed)); + PlatformOp()(Translator::decay(new_value), + reinterpret_cast<Decayed volatile*>(dest)); + } + }; + + // Default implementation of atomic store if a specific platform + // does not provide a specialization for a certain size class. + // For increased safety, the default implementation only allows + // storing types that are pointer sized or smaller. If a platform still + // supports wide atomics, then it has to use specialization + // of Atomic::PlatformStore for that wider size class. + template<size_t byte_size> + struct Atomic::PlatformStore VALUE_OBJ_CLASS_SPEC { + template<typename T> + void operator()(T new_value, + T volatile* dest) const { + STATIC_ASSERT(sizeof(T) <= sizeof(void*)); // wide atomics need specialization + (void)const_cast<T&>(*dest = new_value); + } + }; + // Define FetchAndAdd and AddAndFetch helper classes before including // platform file, which may use these as base classes, requiring they // be complete. template<typename Derived>
*** 422,431 **** --- 601,620 ---- // size_t casts... #if (SIZE_MAX != UINTPTR_MAX) #error size_t is not WORD_SIZE, interesting platform, but missing implementation here #endif + template<typename T> + inline T Atomic::load(const volatile T* dest) { + return LoadImpl<T, PlatformLoad<sizeof(T)> >()(dest); + } + + template<typename T, typename D> + inline void Atomic::store(T store_value, volatile D* dest) { + StoreImpl<T, D, PlatformStore<sizeof(D)> >()(store_value, dest); + } + template<typename I, typename D> inline D Atomic::add(I add_value, D volatile* dest) { return AddImpl<I, D>()(add_value, dest); }
< prev index next >