mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8188224: Generalize Atomic::load/store to use templates
Reviewed-by: dholmes, coleenp
This commit is contained in:
parent
96d0817455
commit
b6bc02e70f
14 changed files with 279 additions and 285 deletions
|
@ -34,22 +34,6 @@
|
||||||
|
|
||||||
// Implementation of class atomic
|
// Implementation of class atomic
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; }
|
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
|
|
||||||
|
|
||||||
inline jlong Atomic::load(const volatile jlong* src) { return *src; }
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// machine barrier instructions:
|
// machine barrier instructions:
|
||||||
//
|
//
|
||||||
|
|
|
@ -27,19 +27,6 @@
|
||||||
|
|
||||||
// Implementation of class atomic
|
// Implementation of class atomic
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; }
|
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
|
|
||||||
|
|
||||||
|
|
||||||
template<size_t byte_size>
|
template<size_t byte_size>
|
||||||
struct Atomic::PlatformAdd
|
struct Atomic::PlatformAdd
|
||||||
: Atomic::FetchAndAdd<Atomic::PlatformAdd<byte_size> >
|
: Atomic::FetchAndAdd<Atomic::PlatformAdd<byte_size> >
|
||||||
|
@ -102,9 +89,6 @@ inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef AMD64
|
#ifdef AMD64
|
||||||
inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
template<typename I, typename D>
|
template<typename I, typename D>
|
||||||
inline D Atomic::PlatformAdd<8>::fetch_and_add(I add_value, D volatile* dest) const {
|
inline D Atomic::PlatformAdd<8>::fetch_and_add(I add_value, D volatile* dest) const {
|
||||||
|
@ -144,8 +128,6 @@ inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value,
|
||||||
return exchange_value;
|
return exchange_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline jlong Atomic::load(const volatile jlong* src) { return *src; }
|
|
||||||
|
|
||||||
#else // !AMD64
|
#else // !AMD64
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -164,18 +146,21 @@ inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value,
|
||||||
return cmpxchg_using_helper<jlong>(_Atomic_cmpxchg_long, exchange_value, dest, compare_value);
|
return cmpxchg_using_helper<jlong>(_Atomic_cmpxchg_long, exchange_value, dest, compare_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline jlong Atomic::load(const volatile jlong* src) {
|
template<>
|
||||||
|
template<typename T>
|
||||||
|
inline T Atomic::PlatformLoad<8>::operator()(T const volatile* src) const {
|
||||||
|
STATIC_ASSERT(8 == sizeof(T));
|
||||||
volatile jlong dest;
|
volatile jlong dest;
|
||||||
_Atomic_move_long(src, &dest);
|
_Atomic_move_long(reinterpret_cast<const volatile jlong*>(src), reinterpret_cast<volatile jlong*>(&dest));
|
||||||
return dest;
|
return PrimitiveConversions::cast<T>(dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Atomic::store(jlong store_value, jlong* dest) {
|
template<>
|
||||||
_Atomic_move_long((volatile jlong*)&store_value, (volatile jlong*)dest);
|
template<typename T>
|
||||||
}
|
inline void Atomic::PlatformStore<8>::operator()(T store_value,
|
||||||
|
T volatile* dest) const {
|
||||||
inline void Atomic::store(jlong store_value, volatile jlong* dest) {
|
STATIC_ASSERT(8 == sizeof(T));
|
||||||
_Atomic_move_long((volatile jlong*)&store_value, dest);
|
_Atomic_move_long(reinterpret_cast<const volatile jlong*>(&store_value), reinterpret_cast<volatile jlong*>(dest));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // AMD64
|
#endif // AMD64
|
||||||
|
|
|
@ -159,20 +159,6 @@ static inline int arm_lock_test_and_set(int newval, volatile int *ptr) {
|
||||||
}
|
}
|
||||||
#endif // ARM
|
#endif // ARM
|
||||||
|
|
||||||
inline void Atomic::store(jint store_value, volatile jint* dest) {
|
|
||||||
#if !defined(ARM) && !defined(M68K)
|
|
||||||
__sync_synchronize();
|
|
||||||
#endif
|
|
||||||
*dest = store_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) {
|
|
||||||
#if !defined(ARM) && !defined(M68K)
|
|
||||||
__sync_synchronize();
|
|
||||||
#endif
|
|
||||||
*dest = store_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<size_t byte_size>
|
template<size_t byte_size>
|
||||||
struct Atomic::PlatformAdd
|
struct Atomic::PlatformAdd
|
||||||
: Atomic::AddAndFetch<Atomic::PlatformAdd<byte_size> >
|
: Atomic::AddAndFetch<Atomic::PlatformAdd<byte_size> >
|
||||||
|
@ -275,18 +261,21 @@ inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value,
|
||||||
return __sync_val_compare_and_swap(dest, compare_value, exchange_value);
|
return __sync_val_compare_and_swap(dest, compare_value, exchange_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline jlong Atomic::load(const volatile jlong* src) {
|
template<>
|
||||||
|
template<typename T>
|
||||||
|
inline T Atomic::PlatformLoad<8>::operator()(T const volatile* src) const {
|
||||||
|
STATIC_ASSERT(8 == sizeof(T));
|
||||||
volatile jlong dest;
|
volatile jlong dest;
|
||||||
os::atomic_copy64(src, &dest);
|
os::atomic_copy64(reinterpret_cast<const volatile jlong*>(src), reinterpret_cast<volatile jlong*>(&dest));
|
||||||
return dest;
|
return PrimitiveConversions::cast<T>(dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Atomic::store(jlong store_value, jlong* dest) {
|
template<>
|
||||||
os::atomic_copy64((volatile jlong*)&store_value, (volatile jlong*)dest);
|
template<typename T>
|
||||||
}
|
inline void Atomic::PlatformStore<8>::operator()(T store_value,
|
||||||
|
T volatile* dest) const {
|
||||||
inline void Atomic::store(jlong store_value, volatile jlong* dest) {
|
STATIC_ASSERT(8 == sizeof(T));
|
||||||
os::atomic_copy64((volatile jlong*)&store_value, dest);
|
os::atomic_copy64(reinterpret_cast<const volatile jlong*>(&store_value), reinterpret_cast<volatile jlong*>(dest));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // OS_CPU_BSD_ZERO_VM_ATOMIC_BSD_ZERO_HPP
|
#endif // OS_CPU_BSD_ZERO_VM_ATOMIC_BSD_ZERO_HPP
|
||||||
|
|
|
@ -34,19 +34,6 @@
|
||||||
#define READ_MEM_BARRIER __atomic_thread_fence(__ATOMIC_ACQUIRE);
|
#define READ_MEM_BARRIER __atomic_thread_fence(__ATOMIC_ACQUIRE);
|
||||||
#define WRITE_MEM_BARRIER __atomic_thread_fence(__ATOMIC_RELEASE);
|
#define WRITE_MEM_BARRIER __atomic_thread_fence(__ATOMIC_RELEASE);
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; }
|
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
|
|
||||||
|
|
||||||
|
|
||||||
template<size_t byte_size>
|
template<size_t byte_size>
|
||||||
struct Atomic::PlatformAdd
|
struct Atomic::PlatformAdd
|
||||||
: Atomic::AddAndFetch<Atomic::PlatformAdd<byte_size> >
|
: Atomic::AddAndFetch<Atomic::PlatformAdd<byte_size> >
|
||||||
|
@ -84,9 +71,4 @@ inline T Atomic::PlatformCmpxchg<byte_size>::operator()(T exchange_value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
|
|
||||||
|
|
||||||
inline jlong Atomic::load(const volatile jlong* src) { return *src; }
|
|
||||||
|
|
||||||
#endif // OS_CPU_LINUX_AARCH64_VM_ATOMIC_LINUX_AARCH64_HPP
|
#endif // OS_CPU_LINUX_AARCH64_VM_ATOMIC_LINUX_AARCH64_HPP
|
||||||
|
|
|
@ -44,39 +44,24 @@
|
||||||
* kernel source or kernel_user_helpers.txt in Linux Doc.
|
* kernel source or kernel_user_helpers.txt in Linux Doc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; }
|
#ifndef AARCH64
|
||||||
inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; }
|
template<>
|
||||||
inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; }
|
template<typename T>
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
|
inline T Atomic::PlatformLoad<8>::operator()(T const volatile* src) const {
|
||||||
inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; }
|
STATIC_ASSERT(8 == sizeof(T));
|
||||||
|
return PrimitiveConversions::cast<T>(
|
||||||
|
(*os::atomic_load_long_func)(reinterpret_cast<const volatile jlong*>(src)));
|
||||||
|
}
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; }
|
template<>
|
||||||
inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; }
|
template<typename T>
|
||||||
inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; }
|
inline void Atomic::PlatformStore<8>::operator()(T store_value,
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
|
T volatile* dest) const {
|
||||||
inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
|
STATIC_ASSERT(8 == sizeof(T));
|
||||||
|
(*os::atomic_store_long_func)(
|
||||||
inline jlong Atomic::load (const volatile jlong* src) {
|
PrimitiveConversions::cast<jlong>(store_value), reinterpret_cast<volatile jlong*>(dest));
|
||||||
assert(((intx)src & (sizeof(jlong)-1)) == 0, "Atomic load jlong mis-aligned");
|
}
|
||||||
#ifdef AARCH64
|
|
||||||
return *src;
|
|
||||||
#else
|
|
||||||
return (*os::atomic_load_long_func)(src);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
inline void Atomic::store (jlong value, volatile jlong* dest) {
|
|
||||||
assert(((intx)dest & (sizeof(jlong)-1)) == 0, "Atomic store jlong mis-aligned");
|
|
||||||
#ifdef AARCH64
|
|
||||||
*dest = value;
|
|
||||||
#else
|
|
||||||
(*os::atomic_store_long_func)(value, dest);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Atomic::store (jlong value, jlong* dest) {
|
|
||||||
store(value, (volatile jlong*)dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
// As per atomic.hpp all read-modify-write operations have to provide two-way
|
// As per atomic.hpp all read-modify-write operations have to provide two-way
|
||||||
// barriers semantics. For AARCH64 we are using load-acquire-with-reservation and
|
// barriers semantics. For AARCH64 we are using load-acquire-with-reservation and
|
||||||
|
|
|
@ -32,22 +32,6 @@
|
||||||
|
|
||||||
// Implementation of class atomic
|
// Implementation of class atomic
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; }
|
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
|
|
||||||
|
|
||||||
inline jlong Atomic::load(const volatile jlong* src) { return *src; }
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// machine barrier instructions:
|
// machine barrier instructions:
|
||||||
//
|
//
|
||||||
|
|
|
@ -53,20 +53,6 @@
|
||||||
// is an integer multiple of the data length. Furthermore, all stores are ordered:
|
// is an integer multiple of the data length. Furthermore, all stores are ordered:
|
||||||
// a store which occurs conceptually before another store becomes visible to other CPUs
|
// a store which occurs conceptually before another store becomes visible to other CPUs
|
||||||
// before the other store becomes visible.
|
// before the other store becomes visible.
|
||||||
inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; }
|
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
|
|
||||||
|
|
||||||
|
|
||||||
//------------
|
//------------
|
||||||
// Atomic::add
|
// Atomic::add
|
||||||
|
@ -335,6 +321,4 @@ inline T Atomic::PlatformCmpxchg<8>::operator()(T xchg_val,
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline jlong Atomic::load(const volatile jlong* src) { return *src; }
|
|
||||||
|
|
||||||
#endif // OS_CPU_LINUX_S390_VM_ATOMIC_LINUX_S390_INLINE_HPP
|
#endif // OS_CPU_LINUX_S390_VM_ATOMIC_LINUX_S390_INLINE_HPP
|
||||||
|
|
|
@ -27,22 +27,6 @@
|
||||||
|
|
||||||
// Implementation of class atomic
|
// Implementation of class atomic
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; }
|
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
|
|
||||||
|
|
||||||
inline jlong Atomic::load(const volatile jlong* src) { return *src; }
|
|
||||||
|
|
||||||
template<size_t byte_size>
|
template<size_t byte_size>
|
||||||
struct Atomic::PlatformAdd
|
struct Atomic::PlatformAdd
|
||||||
: Atomic::AddAndFetch<Atomic::PlatformAdd<byte_size> >
|
: Atomic::AddAndFetch<Atomic::PlatformAdd<byte_size> >
|
||||||
|
|
|
@ -27,19 +27,6 @@
|
||||||
|
|
||||||
// Implementation of class atomic
|
// Implementation of class atomic
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; }
|
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
|
|
||||||
|
|
||||||
|
|
||||||
template<size_t byte_size>
|
template<size_t byte_size>
|
||||||
struct Atomic::PlatformAdd
|
struct Atomic::PlatformAdd
|
||||||
: Atomic::FetchAndAdd<Atomic::PlatformAdd<byte_size> >
|
: Atomic::FetchAndAdd<Atomic::PlatformAdd<byte_size> >
|
||||||
|
@ -102,8 +89,6 @@ inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef AMD64
|
#ifdef AMD64
|
||||||
inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
template<typename I, typename D>
|
template<typename I, typename D>
|
||||||
|
@ -144,8 +129,6 @@ inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value,
|
||||||
return exchange_value;
|
return exchange_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline jlong Atomic::load(const volatile jlong* src) { return *src; }
|
|
||||||
|
|
||||||
#else // !AMD64
|
#else // !AMD64
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -164,18 +147,21 @@ inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value,
|
||||||
return cmpxchg_using_helper<jlong>(_Atomic_cmpxchg_long, exchange_value, dest, compare_value);
|
return cmpxchg_using_helper<jlong>(_Atomic_cmpxchg_long, exchange_value, dest, compare_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline jlong Atomic::load(const volatile jlong* src) {
|
template<>
|
||||||
|
template<typename T>
|
||||||
|
inline T Atomic::PlatformLoad<8>::operator()(T const volatile* src) const {
|
||||||
|
STATIC_ASSERT(8 == sizeof(T));
|
||||||
volatile jlong dest;
|
volatile jlong dest;
|
||||||
_Atomic_move_long(src, &dest);
|
_Atomic_move_long(reinterpret_cast<const volatile jlong*>(src), reinterpret_cast<volatile jlong*>(&dest));
|
||||||
return dest;
|
return PrimitiveConversions::cast<T>(dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Atomic::store(jlong store_value, jlong* dest) {
|
template<>
|
||||||
_Atomic_move_long((volatile jlong*)&store_value, (volatile jlong*)dest);
|
template<typename T>
|
||||||
}
|
inline void Atomic::PlatformStore<8>::operator()(T store_value,
|
||||||
|
T volatile* dest) const {
|
||||||
inline void Atomic::store(jlong store_value, volatile jlong* dest) {
|
STATIC_ASSERT(8 == sizeof(T));
|
||||||
_Atomic_move_long((volatile jlong*)&store_value, dest);
|
_Atomic_move_long(reinterpret_cast<const volatile jlong*>(&store_value), reinterpret_cast<volatile jlong*>(dest));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // AMD64
|
#endif // AMD64
|
||||||
|
|
|
@ -159,14 +159,6 @@ static inline int arm_lock_test_and_set(int newval, volatile int *ptr) {
|
||||||
}
|
}
|
||||||
#endif // ARM
|
#endif // ARM
|
||||||
|
|
||||||
inline void Atomic::store(jint store_value, volatile jint* dest) {
|
|
||||||
*dest = store_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) {
|
|
||||||
*dest = store_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<size_t byte_size>
|
template<size_t byte_size>
|
||||||
struct Atomic::PlatformAdd
|
struct Atomic::PlatformAdd
|
||||||
: Atomic::AddAndFetch<Atomic::PlatformAdd<byte_size> >
|
: Atomic::AddAndFetch<Atomic::PlatformAdd<byte_size> >
|
||||||
|
@ -269,18 +261,21 @@ inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value,
|
||||||
return __sync_val_compare_and_swap(dest, compare_value, exchange_value);
|
return __sync_val_compare_and_swap(dest, compare_value, exchange_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline jlong Atomic::load(const volatile jlong* src) {
|
template<>
|
||||||
|
template<typename T>
|
||||||
|
inline T Atomic::PlatformLoad<8>::operator()(T const volatile* src) const {
|
||||||
|
STATIC_ASSERT(8 == sizeof(T));
|
||||||
volatile jlong dest;
|
volatile jlong dest;
|
||||||
os::atomic_copy64(src, &dest);
|
os::atomic_copy64(reinterpret_cast<const volatile jlong*>(src), reinterpret_cast<volatile jlong*>(&dest));
|
||||||
return dest;
|
return PrimitiveConversions::cast<T>(dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Atomic::store(jlong store_value, jlong* dest) {
|
template<>
|
||||||
os::atomic_copy64((volatile jlong*)&store_value, (volatile jlong*)dest);
|
template<typename T>
|
||||||
}
|
inline void Atomic::PlatformStore<8>::operator()(T store_value,
|
||||||
|
T volatile* dest) const {
|
||||||
inline void Atomic::store(jlong store_value, volatile jlong* dest) {
|
STATIC_ASSERT(8 == sizeof(T));
|
||||||
os::atomic_copy64((volatile jlong*)&store_value, dest);
|
os::atomic_copy64(reinterpret_cast<const volatile jlong*>(&store_value), reinterpret_cast<volatile jlong*>(dest));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // OS_CPU_LINUX_ZERO_VM_ATOMIC_LINUX_ZERO_HPP
|
#endif // OS_CPU_LINUX_ZERO_VM_ATOMIC_LINUX_ZERO_HPP
|
||||||
|
|
|
@ -27,22 +27,6 @@
|
||||||
|
|
||||||
// Implementation of class atomic
|
// Implementation of class atomic
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; }
|
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
|
|
||||||
|
|
||||||
inline void Atomic::store(jlong store_value, jlong* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store(jlong store_value, volatile jlong* dest) { *dest = store_value; }
|
|
||||||
inline jlong Atomic::load(const volatile jlong* src) { return *src; }
|
|
||||||
|
|
||||||
// Implement ADD using a CAS loop.
|
// Implement ADD using a CAS loop.
|
||||||
template<size_t byte_size>
|
template<size_t byte_size>
|
||||||
struct Atomic::PlatformAdd VALUE_OBJ_CLASS_SPEC {
|
struct Atomic::PlatformAdd VALUE_OBJ_CLASS_SPEC {
|
||||||
|
|
|
@ -25,20 +25,6 @@
|
||||||
#ifndef OS_CPU_SOLARIS_X86_VM_ATOMIC_SOLARIS_X86_HPP
|
#ifndef OS_CPU_SOLARIS_X86_VM_ATOMIC_SOLARIS_X86_HPP
|
||||||
#define OS_CPU_SOLARIS_X86_VM_ATOMIC_SOLARIS_X86_HPP
|
#define OS_CPU_SOLARIS_X86_VM_ATOMIC_SOLARIS_X86_HPP
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; }
|
|
||||||
|
|
||||||
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; }
|
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
|
|
||||||
|
|
||||||
// For Sun Studio - implementation is in solaris_x86_64.il.
|
// For Sun Studio - implementation is in solaris_x86_64.il.
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -151,8 +137,4 @@ inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value,
|
||||||
PrimitiveConversions::cast<jlong>(compare_value)));
|
PrimitiveConversions::cast<jlong>(compare_value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
|
|
||||||
inline jlong Atomic::load(const volatile jlong* src) { return *src; }
|
|
||||||
|
|
||||||
#endif // OS_CPU_SOLARIS_X86_VM_ATOMIC_SOLARIS_X86_HPP
|
#endif // OS_CPU_SOLARIS_X86_VM_ATOMIC_SOLARIS_X86_HPP
|
||||||
|
|
|
@ -42,21 +42,6 @@
|
||||||
|
|
||||||
#pragma warning(disable: 4035) // Disables warnings reporting missing return statement
|
#pragma warning(disable: 4035) // Disables warnings reporting missing return statement
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; }
|
|
||||||
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; }
|
|
||||||
|
|
||||||
inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; }
|
|
||||||
|
|
||||||
|
|
||||||
inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
|
|
||||||
|
|
||||||
template<size_t byte_size>
|
template<size_t byte_size>
|
||||||
struct Atomic::PlatformAdd
|
struct Atomic::PlatformAdd
|
||||||
: Atomic::AddAndFetch<Atomic::PlatformAdd<byte_size> >
|
: Atomic::AddAndFetch<Atomic::PlatformAdd<byte_size> >
|
||||||
|
@ -66,9 +51,6 @@ struct Atomic::PlatformAdd
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef AMD64
|
#ifdef AMD64
|
||||||
inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
|
|
||||||
inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
template<typename I, typename D>
|
template<typename I, typename D>
|
||||||
inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const {
|
inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const {
|
||||||
|
@ -112,8 +94,6 @@ DEFINE_STUB_CMPXCHG(8, jlong, os::atomic_cmpxchg_long_func)
|
||||||
|
|
||||||
#undef DEFINE_STUB_CMPXCHG
|
#undef DEFINE_STUB_CMPXCHG
|
||||||
|
|
||||||
inline jlong Atomic::load(const volatile jlong* src) { return *src; }
|
|
||||||
|
|
||||||
#else // !AMD64
|
#else // !AMD64
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
@ -200,9 +180,12 @@ inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline jlong Atomic::load(const volatile jlong* src) {
|
template<>
|
||||||
volatile jlong dest;
|
template<typename T>
|
||||||
volatile jlong* pdest = &dest;
|
inline T Atomic::PlatformLoad<8>::operator()(T const volatile* src) const {
|
||||||
|
STATIC_ASSERT(8 == sizeof(T));
|
||||||
|
volatile T dest;
|
||||||
|
volatile T* pdest = &dest;
|
||||||
__asm {
|
__asm {
|
||||||
mov eax, src
|
mov eax, src
|
||||||
fild qword ptr [eax]
|
fild qword ptr [eax]
|
||||||
|
@ -212,8 +195,12 @@ inline jlong Atomic::load(const volatile jlong* src) {
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Atomic::store(jlong store_value, volatile jlong* dest) {
|
template<>
|
||||||
volatile jlong* src = &store_value;
|
template<typename T>
|
||||||
|
inline void Atomic::PlatformStore<8>::operator()(T store_value,
|
||||||
|
T volatile* dest) const {
|
||||||
|
STATIC_ASSERT(8 == sizeof(T));
|
||||||
|
volatile T* src = &store_value;
|
||||||
__asm {
|
__asm {
|
||||||
mov eax, src
|
mov eax, src
|
||||||
fild qword ptr [eax]
|
fild qword ptr [eax]
|
||||||
|
@ -222,10 +209,6 @@ inline void Atomic::store(jlong store_value, volatile jlong* dest) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Atomic::store(jlong store_value, jlong* dest) {
|
|
||||||
Atomic::store(store_value, (volatile jlong*)dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // AMD64
|
#endif // AMD64
|
||||||
|
|
||||||
#pragma warning(default: 4035) // Enables warnings reporting missing return statement
|
#pragma warning(default: 4035) // Enables warnings reporting missing return statement
|
||||||
|
|
|
@ -64,24 +64,25 @@ class Atomic : AllStatic {
|
||||||
// we can prove that a weaker form is sufficiently safe.
|
// we can prove that a weaker form is sufficiently safe.
|
||||||
|
|
||||||
// Atomically store to a location
|
// Atomically store to a location
|
||||||
inline static void store (jbyte store_value, jbyte* dest);
|
// The type T must be either a pointer type convertible to or equal
|
||||||
inline static void store (jshort store_value, jshort* dest);
|
// to D, an integral/enum type equal to D, or a type equal to D that
|
||||||
inline static void store (jint store_value, jint* dest);
|
// is primitive convertible using PrimitiveConversions.
|
||||||
// See comment above about using jlong atomics on 32-bit platforms
|
template<typename T, typename D>
|
||||||
inline static void store (jlong store_value, jlong* dest);
|
inline static void store(T store_value, volatile D* 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_ptr(intptr_t store_value, volatile intptr_t* dest) {
|
||||||
inline static void store (jshort store_value, volatile jshort* dest);
|
Atomic::store(store_value, 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 void store_ptr(void* store_value, volatile void* dest) {
|
||||||
inline static jlong load(const volatile jlong* src);
|
Atomic::store(store_value, reinterpret_cast<void* volatile*>(dest));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Atomically load from a location
|
||||||
|
// 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:
|
// Atomically add to a location. Returns updated value. add*() provide:
|
||||||
// <fence> add-value-to-dest <membar StoreLoad|StoreStore>
|
// <fence> add-value-to-dest <membar StoreLoad|StoreStore>
|
||||||
|
@ -174,6 +175,57 @@ private:
|
||||||
// that is needed here.
|
// that is needed here.
|
||||||
template<typename From, typename To> struct IsPointerConvertible;
|
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
|
// Dispatch handler for add. Provides type-based validity checking
|
||||||
// and limited conversions around calls to the platform-specific
|
// and limited conversions around calls to the platform-specific
|
||||||
// implementation layer provided by PlatformAdd.
|
// implementation layer provided by PlatformAdd.
|
||||||
|
@ -344,6 +396,131 @@ struct Atomic::IsPointerConvertible<From*, To*> : AllStatic {
|
||||||
static const bool value = (sizeof(yes) == sizeof(test(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
|
// Define FetchAndAdd and AddAndFetch helper classes before including
|
||||||
// platform file, which may use these as base classes, requiring they
|
// platform file, which may use these as base classes, requiring they
|
||||||
// be complete.
|
// be complete.
|
||||||
|
@ -424,6 +601,16 @@ struct Atomic::PlatformXchg VALUE_OBJ_CLASS_SPEC {
|
||||||
#error size_t is not WORD_SIZE, interesting platform, but missing implementation here
|
#error size_t is not WORD_SIZE, interesting platform, but missing implementation here
|
||||||
#endif
|
#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>
|
template<typename I, typename D>
|
||||||
inline D Atomic::add(I add_value, D volatile* dest) {
|
inline D Atomic::add(I add_value, D volatile* dest) {
|
||||||
return AddImpl<I, D>()(add_value, dest);
|
return AddImpl<I, D>()(add_value, dest);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue