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(volatile int *ptr, int add_value) {
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(volatile int *ptr, int newval) {
91 for (;;) {
92 // Loop until success.
93 int prev = *ptr;
94
95 if (__m68k_cmpxchg (prev, newval, ptr) == prev)
96 return prev;
97 }
118 /* Perform an atomic compare and swap: if the current value of `*PTR'
119 is OLDVAL, then write NEWVAL into `*PTR'. Return the contents of
120 `*PTR' before the operation.*/
121 static inline int arm_compare_and_swap(int newval,
122 volatile int *ptr,
123 int oldval) {
124 for (;;) {
125 int prev = *ptr;
126 if (prev != oldval)
127 return prev;
128
129 if (__kernel_cmpxchg (prev, newval, ptr) == 0)
130 // Success.
131 return prev;
132
133 // We failed even though prev == oldval. Try again.
134 }
135 }
136
137 /* Atomically add an int to memory. */
138 static inline int arm_add_and_fetch(volatile int *ptr, int add_value) {
139 for (;;) {
140 // Loop until a __kernel_cmpxchg succeeds.
141
142 int prev = *ptr;
143
144 if (__kernel_cmpxchg (prev, prev + add_value, ptr) == 0)
145 return prev + add_value;
146 }
147 }
148
149 /* Atomically write VALUE into `*PTR' and returns the previous
150 contents of `*PTR'. */
151 static inline int arm_lock_test_and_set(volatile int *ptr, int newval) {
152 for (;;) {
153 // Loop until a __kernel_cmpxchg succeeds.
154 int prev = *ptr;
155
156 if (__kernel_cmpxchg (prev, newval, ptr) == 0)
157 return prev;
158 }
159 }
160 #endif // ARM
161
162 inline void Atomic::store(jint store_value, volatile jint* dest) {
163 *dest = store_value;
164 }
165
166 inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) {
167 *dest = store_value;
168 }
169
170 inline jint Atomic::add(jint add_value, volatile jint* dest) {
171 #ifdef ARM
172 return arm_add_and_fetch(dest, add_value);
173 #else
174 #ifdef M68K
175 return m68k_add_and_fetch(dest, add_value);
176 #else
177 return __sync_add_and_fetch(dest, add_value);
178 #endif // M68K
179 #endif // ARM
180 }
181
182 inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
183 #ifdef ARM
184 return arm_add_and_fetch(dest, add_value);
185 #else
186 #ifdef M68K
187 return m68k_add_and_fetch(dest, add_value);
188 #else
189 return __sync_add_and_fetch(dest, add_value);
190 #endif // M68K
191 #endif // ARM
192 }
193
194 inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) {
195 return (void *) add_ptr(add_value, (volatile intptr_t *) dest);
196 }
197
198 inline void Atomic::inc(volatile jint* dest) {
199 add(1, dest);
200 }
201
202 inline void Atomic::inc_ptr(volatile intptr_t* dest) {
203 add_ptr(1, dest);
204 }
205
206 inline void Atomic::inc_ptr(volatile void* dest) {
207 add_ptr(1, dest);
208 }
209
210 inline void Atomic::dec(volatile jint* dest) {
211 add(-1, dest);
212 }
213
214 inline void Atomic::dec_ptr(volatile intptr_t* dest) {
215 add_ptr(-1, dest);
216 }
|
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(volatile int *ptr, int newval) {
91 for (;;) {
92 // Loop until success.
93 int prev = *ptr;
94
95 if (__m68k_cmpxchg (prev, newval, ptr) == prev)
96 return prev;
97 }
118 /* Perform an atomic compare and swap: if the current value of `*PTR'
119 is OLDVAL, then write NEWVAL into `*PTR'. Return the contents of
120 `*PTR' before the operation.*/
121 static inline int arm_compare_and_swap(int newval,
122 volatile int *ptr,
123 int oldval) {
124 for (;;) {
125 int prev = *ptr;
126 if (prev != oldval)
127 return prev;
128
129 if (__kernel_cmpxchg (prev, newval, ptr) == 0)
130 // Success.
131 return prev;
132
133 // We failed even though prev == oldval. Try again.
134 }
135 }
136
137 /* Atomically add an int to memory. */
138 static inline int arm_add_and_fetch(int add_value, volatile int *ptr) {
139 for (;;) {
140 // Loop until a __kernel_cmpxchg succeeds.
141
142 int prev = *ptr;
143
144 if (__kernel_cmpxchg (prev, prev + add_value, ptr) == 0)
145 return prev + add_value;
146 }
147 }
148
149 /* Atomically write VALUE into `*PTR' and returns the previous
150 contents of `*PTR'. */
151 static inline int arm_lock_test_and_set(volatile int *ptr, int newval) {
152 for (;;) {
153 // Loop until a __kernel_cmpxchg succeeds.
154 int prev = *ptr;
155
156 if (__kernel_cmpxchg (prev, newval, ptr) == 0)
157 return prev;
158 }
159 }
160 #endif // ARM
161
162 inline void Atomic::store(jint store_value, volatile jint* dest) {
163 *dest = store_value;
164 }
165
166 inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) {
167 *dest = store_value;
168 }
169
170 template<size_t byte_size>
171 struct Atomic::PlatformAdd
172 : Atomic::AddAndFetch<Atomic::PlatformAdd<byte_size> >
173 {
174 template<typename I, typename D>
175 D add_and_fetch(I add_value, D volatile* dest) const;
176 };
177
178 template<>
179 template<typename I, typename D>
180 inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const {
181 STATIC_CAST(4 == sizeof(I));
182 STATIC_CAST(4 == sizeof(D));
183
184 #ifdef ARM
185 return add_using_helper<int>(arm_add_and_fetch, add_value, dest);
186 #else
187 #ifdef M68K
188 return add_using_helper<int>(m68k_add_and_fetch, add_value, dest);
189 #else
190 return __sync_add_and_fetch(dest, add_value);
191 #endif // M68K
192 #endif // ARM
193 }
194
195 template<>
196 template<typename I, typename D>
197 inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) const {
198 STATIC_CAST(8 == sizeof(I));
199 STATIC_CAST(8 == sizeof(D));
200
201 return __sync_add_and_fetch(dest, add_value);
202 }
203
204 template<>
205 struct Atomic::PlatformAdd<2>: Atomic::AddShortUsingInt {};
206
207 inline void Atomic::inc(volatile jint* dest) {
208 add(1, dest);
209 }
210
211 inline void Atomic::inc_ptr(volatile intptr_t* dest) {
212 add_ptr(1, dest);
213 }
214
215 inline void Atomic::inc_ptr(volatile void* dest) {
216 add_ptr(1, dest);
217 }
218
219 inline void Atomic::dec(volatile jint* dest) {
220 add(-1, dest);
221 }
222
223 inline void Atomic::dec_ptr(volatile intptr_t* dest) {
224 add_ptr(-1, dest);
225 }
|