27 #define OS_CPU_LINUX_ZERO_VM_ATOMIC_LINUX_ZERO_HPP |
27 #define OS_CPU_LINUX_ZERO_VM_ATOMIC_LINUX_ZERO_HPP |
28 |
28 |
29 #include "runtime/os.hpp" |
29 #include "runtime/os.hpp" |
30 |
30 |
31 // Implementation of class atomic |
31 // Implementation of class atomic |
32 |
|
33 #ifdef M68K |
|
34 |
|
35 /* |
|
36 * __m68k_cmpxchg |
|
37 * |
|
38 * Atomically store newval in *ptr if *ptr is equal to oldval for user space. |
|
39 * Returns newval on success and oldval if no exchange happened. |
|
40 * This implementation is processor specific and works on |
|
41 * 68020 68030 68040 and 68060. |
|
42 * |
|
43 * It will not work on ColdFire, 68000 and 68010 since they lack the CAS |
|
44 * instruction. |
|
45 * Using a kernelhelper would be better for arch complete implementation. |
|
46 * |
|
47 */ |
|
48 |
|
49 static inline int __m68k_cmpxchg(int oldval, int newval, volatile int *ptr) { |
|
50 int ret; |
|
51 __asm __volatile ("cas%.l %0,%2,%1" |
|
52 : "=d" (ret), "+m" (*(ptr)) |
|
53 : "d" (newval), "0" (oldval)); |
|
54 return ret; |
|
55 } |
|
56 |
|
57 /* Perform an atomic compare and swap: if the current value of `*PTR' |
|
58 is OLDVAL, then write NEWVAL into `*PTR'. Return the contents of |
|
59 `*PTR' before the operation.*/ |
|
60 static inline int m68k_compare_and_swap(int newval, |
|
61 volatile int *ptr, |
|
62 int oldval) { |
|
63 for (;;) { |
|
64 int prev = *ptr; |
|
65 if (prev != oldval) |
|
66 return prev; |
|
67 |
|
68 if (__m68k_cmpxchg (prev, newval, ptr) == newval) |
|
69 // Success. |
|
70 return prev; |
|
71 |
|
72 // We failed even though prev == oldval. Try again. |
|
73 } |
|
74 } |
|
75 |
|
76 /* Atomically add an int to memory. */ |
|
77 static inline int m68k_add_and_fetch(int add_value, volatile int *ptr) { |
|
78 for (;;) { |
|
79 // Loop until success. |
|
80 |
|
81 int prev = *ptr; |
|
82 |
|
83 if (__m68k_cmpxchg (prev, prev + add_value, ptr) == prev + add_value) |
|
84 return prev + add_value; |
|
85 } |
|
86 } |
|
87 |
|
88 /* Atomically write VALUE into `*PTR' and returns the previous |
|
89 contents of `*PTR'. */ |
|
90 static inline int m68k_lock_test_and_set(int newval, volatile int *ptr) { |
|
91 for (;;) { |
|
92 // Loop until success. |
|
93 int prev = *ptr; |
|
94 |
|
95 if (__m68k_cmpxchg (prev, newval, ptr) == prev) |
|
96 return prev; |
|
97 } |
|
98 } |
|
99 #endif // M68K |
|
100 |
32 |
101 #ifdef ARM |
33 #ifdef ARM |
102 |
34 |
103 /* |
35 /* |
104 * __kernel_cmpxchg |
36 * __kernel_cmpxchg |
174 STATIC_ASSERT(4 == sizeof(D)); |
106 STATIC_ASSERT(4 == sizeof(D)); |
175 |
107 |
176 #ifdef ARM |
108 #ifdef ARM |
177 return add_using_helper<int>(arm_add_and_fetch, add_value, dest); |
109 return add_using_helper<int>(arm_add_and_fetch, add_value, dest); |
178 #else |
110 #else |
179 #ifdef M68K |
|
180 return add_using_helper<int>(m68k_add_and_fetch, add_value, dest); |
|
181 #else |
|
182 return __sync_add_and_fetch(dest, add_value); |
111 return __sync_add_and_fetch(dest, add_value); |
183 #endif // M68K |
|
184 #endif // ARM |
112 #endif // ARM |
185 } |
113 } |
186 |
114 |
187 template<> |
115 template<> |
188 template<typename I, typename D> |
116 template<typename I, typename D> |
198 inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, |
126 inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, |
199 T volatile* dest) const { |
127 T volatile* dest) const { |
200 STATIC_ASSERT(4 == sizeof(T)); |
128 STATIC_ASSERT(4 == sizeof(T)); |
201 #ifdef ARM |
129 #ifdef ARM |
202 return xchg_using_helper<int>(arm_lock_test_and_set, exchange_value, dest); |
130 return xchg_using_helper<int>(arm_lock_test_and_set, exchange_value, dest); |
203 #else |
|
204 #ifdef M68K |
|
205 return xchg_using_helper<int>(m68k_lock_test_and_set, exchange_value, dest); |
|
206 #else |
131 #else |
207 // __sync_lock_test_and_set is a bizarrely named atomic exchange |
132 // __sync_lock_test_and_set is a bizarrely named atomic exchange |
208 // operation. Note that some platforms only support this with the |
133 // operation. Note that some platforms only support this with the |
209 // limitation that the only valid value to store is the immediate |
134 // limitation that the only valid value to store is the immediate |
210 // constant 1. There is a test for this in JNI_CreateJavaVM(). |
135 // constant 1. There is a test for this in JNI_CreateJavaVM(). |
241 cmpxchg_memory_order order) const { |
165 cmpxchg_memory_order order) const { |
242 STATIC_ASSERT(4 == sizeof(T)); |
166 STATIC_ASSERT(4 == sizeof(T)); |
243 #ifdef ARM |
167 #ifdef ARM |
244 return cmpxchg_using_helper<int>(arm_compare_and_swap, exchange_value, dest, compare_value); |
168 return cmpxchg_using_helper<int>(arm_compare_and_swap, exchange_value, dest, compare_value); |
245 #else |
169 #else |
246 #ifdef M68K |
|
247 return cmpxchg_using_helper<int>(m68k_compare_and_swap, exchange_value, dest, compare_value); |
|
248 #else |
|
249 return __sync_val_compare_and_swap(dest, compare_value, exchange_value); |
170 return __sync_val_compare_and_swap(dest, compare_value, exchange_value); |
250 #endif // M68K |
|
251 #endif // ARM |
171 #endif // ARM |
252 } |
172 } |
253 |
173 |
254 template<> |
174 template<> |
255 template<typename T> |
175 template<typename T> |