41 |
41 |
42 inline void Atomic::store(jlong store_value, jlong* dest) { *dest = store_value; } |
42 inline void Atomic::store(jlong store_value, jlong* dest) { *dest = store_value; } |
43 inline void Atomic::store(jlong store_value, volatile jlong* dest) { *dest = store_value; } |
43 inline void Atomic::store(jlong store_value, volatile jlong* dest) { *dest = store_value; } |
44 inline jlong Atomic::load(const volatile jlong* src) { return *src; } |
44 inline jlong Atomic::load(const volatile jlong* src) { return *src; } |
45 |
45 |
46 |
|
47 // This is the interface to the atomic instructions in solaris_sparc.il. |
|
48 // It's very messy because we need to support v8 and these instructions |
|
49 // are illegal there. When sparc v8 is dropped, we can drop out lots of |
|
50 // this code. Also compiler2 does not support v8 so the conditional code |
|
51 // omits the instruction set check. |
|
52 |
|
53 extern "C" jint _Atomic_swap32(jint exchange_value, volatile jint* dest); |
|
54 extern "C" intptr_t _Atomic_swap64(intptr_t exchange_value, volatile intptr_t* dest); |
|
55 |
|
56 // Implement ADD using a CAS loop. |
46 // Implement ADD using a CAS loop. |
57 template<size_t byte_size> |
47 template<size_t byte_size> |
58 struct Atomic::PlatformAdd VALUE_OBJ_CLASS_SPEC { |
48 struct Atomic::PlatformAdd VALUE_OBJ_CLASS_SPEC { |
59 template<typename I, typename D> |
49 template<typename I, typename D> |
60 inline D operator()(I add_value, D volatile* dest) const { |
50 inline D operator()(I add_value, D volatile* dest) const { |
67 } |
57 } |
68 return old_value + add_value; |
58 return old_value + add_value; |
69 } |
59 } |
70 }; |
60 }; |
71 |
61 |
72 inline jint Atomic::xchg (jint exchange_value, volatile jint* dest) { |
62 template<> |
73 return _Atomic_swap32(exchange_value, dest); |
63 template<typename T> |
|
64 inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, |
|
65 T volatile* dest) const { |
|
66 STATIC_ASSERT(4 == sizeof(T)); |
|
67 __asm__ volatile ( "swap [%2],%0" |
|
68 : "=r" (exchange_value) |
|
69 : "0" (exchange_value), "r" (dest) |
|
70 : "memory"); |
|
71 return exchange_value; |
74 } |
72 } |
75 |
73 |
76 inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) { |
74 template<> |
77 return _Atomic_swap64(exchange_value, dest); |
75 template<typename T> |
78 } |
76 inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, |
79 |
77 T volatile* dest) const { |
80 inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* dest) { |
78 STATIC_ASSERT(8 == sizeof(T)); |
81 return (void*)xchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest); |
79 T old_value = *dest; |
|
80 while (true) { |
|
81 T result = cmpxchg(exchange_value, dest, old_value); |
|
82 if (result == old_value) break; |
|
83 old_value = result; |
|
84 } |
|
85 return old_value; |
82 } |
86 } |
83 |
87 |
84 // No direct support for cmpxchg of bytes; emulate using int. |
88 // No direct support for cmpxchg of bytes; emulate using int. |
85 template<> |
89 template<> |
86 struct Atomic::PlatformCmpxchg<1> : Atomic::CmpxchgByteUsingInt {}; |
90 struct Atomic::PlatformCmpxchg<1> : Atomic::CmpxchgByteUsingInt {}; |