51 inline void Atomic::dec_ptr(volatile void* dest) { (void)add_ptr(-1, dest); }
52
53 // For Sun Studio - implementation is in solaris_x86_[32/64].il.
54 // For gcc - implementation is just below.
55
56 // The lock prefix can be omitted for certain instructions on uniprocessors; to
57 // facilitate this, os::is_MP() is passed as an additional argument. 64-bit
58 // processors are assumed to be multi-threaded and/or multi-core, so the extra
59 // argument is unnecessary.
60 #ifndef _LP64
61 #define IS_MP_DECL() , int is_mp
62 #define IS_MP_ARG() , (int) os::is_MP()
63 #else
64 #define IS_MP_DECL()
65 #define IS_MP_ARG()
66 #endif // _LP64
67
68 extern "C" {
69 jint _Atomic_add(jint add_value, volatile jint* dest IS_MP_DECL());
70 jint _Atomic_xchg(jint exchange_value, volatile jint* dest);
71 jint _Atomic_cmpxchg(jint exchange_value, volatile jint* dest,
72 jint compare_value IS_MP_DECL());
73 jlong _Atomic_cmpxchg_long(jlong exchange_value, volatile jlong* dest,
74 jlong compare_value IS_MP_DECL());
75 }
76
77 inline jint Atomic::add (jint add_value, volatile jint* dest) {
78 return _Atomic_add(add_value, dest IS_MP_ARG());
79 }
80
81 inline jint Atomic::xchg (jint exchange_value, volatile jint* dest) {
82 return _Atomic_xchg(exchange_value, dest);
83 }
84
85 inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) {
86 return _Atomic_cmpxchg(exchange_value, dest, compare_value IS_MP_ARG());
87 }
88
89 inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) {
90 return _Atomic_cmpxchg_long(exchange_value, dest, compare_value IS_MP_ARG());
91 }
92
93
94 #ifdef AMD64
95 inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
96 inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
97 extern "C" jlong _Atomic_add_long(jlong add_value, volatile jlong* dest);
98 extern "C" jlong _Atomic_xchg_long(jlong exchange_value, volatile jlong* dest);
99
100 inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
101 return (intptr_t)_Atomic_add_long((jlong)add_value, (volatile jlong*)dest);
102 }
103
104 inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) {
200 }
201
202 #endif // AMD64
203
204 inline jint _Atomic_xchg(jint exchange_value, volatile jint* dest) {
205 __asm__ __volatile__ ("xchgl (%2),%0"
206 : "=r" (exchange_value)
207 : "0" (exchange_value), "r" (dest)
208 : "memory");
209 return exchange_value;
210 }
211
212 inline jint _Atomic_cmpxchg(jint exchange_value, volatile jint* dest, jint compare_value, int mp) {
213 __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)"
214 : "=a" (exchange_value)
215 : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp)
216 : "cc", "memory");
217 return exchange_value;
218 }
219
220 // This is the interface to the atomic instruction in solaris_i486.s.
221 jlong _Atomic_cmpxchg_long_gcc(jlong exchange_value, volatile jlong* dest, jlong compare_value, int mp);
222
223 inline jlong _Atomic_cmpxchg_long(jlong exchange_value, volatile jlong* dest, jlong compare_value, int mp) {
224 #ifdef AMD64
225 __asm__ __volatile__ (LOCK_IF_MP(%4) "cmpxchgq %1,(%3)"
226 : "=a" (exchange_value)
227 : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp)
228 : "cc", "memory");
229 return exchange_value;
230 #else
231 return _Atomic_cmpxchg_long_gcc(exchange_value, dest, compare_value, os::is_MP());
232
233 #if 0
234 // The code below does not work presumably because of the bug in gcc
235 // The error message says:
236 // can't find a register in class BREG while reloading asm
237 // However I want to save this code and later replace _Atomic_cmpxchg_long_gcc
238 // with such inline asm code:
239
|
51 inline void Atomic::dec_ptr(volatile void* dest) { (void)add_ptr(-1, dest); }
52
53 // For Sun Studio - implementation is in solaris_x86_[32/64].il.
54 // For gcc - implementation is just below.
55
56 // The lock prefix can be omitted for certain instructions on uniprocessors; to
57 // facilitate this, os::is_MP() is passed as an additional argument. 64-bit
58 // processors are assumed to be multi-threaded and/or multi-core, so the extra
59 // argument is unnecessary.
60 #ifndef _LP64
61 #define IS_MP_DECL() , int is_mp
62 #define IS_MP_ARG() , (int) os::is_MP()
63 #else
64 #define IS_MP_DECL()
65 #define IS_MP_ARG()
66 #endif // _LP64
67
68 extern "C" {
69 jint _Atomic_add(jint add_value, volatile jint* dest IS_MP_DECL());
70 jint _Atomic_xchg(jint exchange_value, volatile jint* dest);
71 jbyte _Atomic_cmpxchg_byte(jbyte exchange_value, volatile jbyte* dest,
72 jbyte compare_value IS_MP_DECL());
73 jint _Atomic_cmpxchg(jint exchange_value, volatile jint* dest,
74 jint compare_value IS_MP_DECL());
75 jlong _Atomic_cmpxchg_long(jlong exchange_value, volatile jlong* dest,
76 jlong compare_value IS_MP_DECL());
77 }
78
79 inline jint Atomic::add (jint add_value, volatile jint* dest) {
80 return _Atomic_add(add_value, dest IS_MP_ARG());
81 }
82
83 inline jint Atomic::xchg (jint exchange_value, volatile jint* dest) {
84 return _Atomic_xchg(exchange_value, dest);
85 }
86
87 inline jbyte Atomic::cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) {
88 return _Atomic_cmpxchg_byte(exchange_value, dest, compare_value IS_MP_ARG());
89 }
90
91 inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) {
92 return _Atomic_cmpxchg(exchange_value, dest, compare_value IS_MP_ARG());
93 }
94
95 inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) {
96 return _Atomic_cmpxchg_long(exchange_value, dest, compare_value IS_MP_ARG());
97 }
98
99
100 #ifdef AMD64
101 inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
102 inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
103 extern "C" jlong _Atomic_add_long(jlong add_value, volatile jlong* dest);
104 extern "C" jlong _Atomic_xchg_long(jlong exchange_value, volatile jlong* dest);
105
106 inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
107 return (intptr_t)_Atomic_add_long((jlong)add_value, (volatile jlong*)dest);
108 }
109
110 inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) {
206 }
207
208 #endif // AMD64
209
210 inline jint _Atomic_xchg(jint exchange_value, volatile jint* dest) {
211 __asm__ __volatile__ ("xchgl (%2),%0"
212 : "=r" (exchange_value)
213 : "0" (exchange_value), "r" (dest)
214 : "memory");
215 return exchange_value;
216 }
217
218 inline jint _Atomic_cmpxchg(jint exchange_value, volatile jint* dest, jint compare_value, int mp) {
219 __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)"
220 : "=a" (exchange_value)
221 : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp)
222 : "cc", "memory");
223 return exchange_value;
224 }
225
226
227 inline jbyte _Atomic_cmpxchg_byte(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value, int mp) {
228 __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgb %1,(%3)"
229 : "=a" (exchange_value)
230 : "q" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp)
231 : "cc", "memory");
232 return exchange_value;
233 }
234
235 // This is the interface to the atomic instruction in solaris_i486.s.
236 jlong _Atomic_cmpxchg_long_gcc(jlong exchange_value, volatile jlong* dest, jlong compare_value, int mp);
237
238 inline jlong _Atomic_cmpxchg_long(jlong exchange_value, volatile jlong* dest, jlong compare_value, int mp) {
239 #ifdef AMD64
240 __asm__ __volatile__ (LOCK_IF_MP(%4) "cmpxchgq %1,(%3)"
241 : "=a" (exchange_value)
242 : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp)
243 : "cc", "memory");
244 return exchange_value;
245 #else
246 return _Atomic_cmpxchg_long_gcc(exchange_value, dest, compare_value, os::is_MP());
247
248 #if 0
249 // The code below does not work presumably because of the bug in gcc
250 // The error message says:
251 // can't find a register in class BREG while reloading asm
252 // However I want to save this code and later replace _Atomic_cmpxchg_long_gcc
253 // with such inline asm code:
254
|