src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp

changeset 6465
666e6ce3976c
child 6501
c668f307a4c0
equal deleted inserted replaced
6464:b83f7d608548 6465:666e6ce3976c
1 /*
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3 * Copyright 2012, 2013 SAP AG. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 #ifndef OS_CPU_AIX_OJDKPPC_VM_ATOMIC_AIX_PPC_INLINE_HPP
27 #define OS_CPU_AIX_OJDKPPC_VM_ATOMIC_AIX_PPC_INLINE_HPP
28
29 #include "orderAccess_aix_ppc.inline.hpp"
30 #include "runtime/atomic.hpp"
31 #include "runtime/os.hpp"
32 #include "vm_version_ppc.hpp"
33
34 #ifndef _LP64
35 #error "Atomic currently only impleneted for PPC64"
36 #endif
37
38 // Implementation of class atomic
39
40 inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; }
41 inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; }
42 inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; }
43 inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
44 inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
45 inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; }
46
47 inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; }
48 inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; }
49 inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; }
50 inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
51 inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
52 inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
53
54 inline jlong Atomic::load(volatile jlong* src) { return *src; }
55
56 /*
57 machine barrier instructions:
58
59 - ppc_sync two-way memory barrier, aka fence
60 - ppc_lwsync orders Store|Store,
61 Load|Store,
62 Load|Load,
63 but not Store|Load
64 - ppc_eieio orders memory accesses for device memory (only)
65 - ppc_isync invalidates speculatively executed instructions
66 From the POWER ISA 2.06 documentation:
67 "[...] an isync instruction prevents the execution of
68 instructions following the isync until instructions
69 preceding the isync have completed, [...]"
70 From IBM's AIX assembler reference:
71 "The isync [...] instructions causes the processor to
72 refetch any instructions that might have been fetched
73 prior to the isync instruction. The instruction isync
74 causes the processor to wait for all previous instructions
75 to complete. Then any instructions already fetched are
76 discarded and instruction processing continues in the
77 environment established by the previous instructions."
78
79 semantic barrier instructions:
80 (as defined in orderAccess.hpp)
81
82 - ppc_release orders Store|Store, (maps to ppc_lwsync)
83 Load|Store
84 - ppc_acquire orders Load|Store, (maps to ppc_lwsync)
85 Load|Load
86 - ppc_fence orders Store|Store, (maps to ppc_sync)
87 Load|Store,
88 Load|Load,
89 Store|Load
90 */
91
92 #define strasm_ppc_sync "\n sync \n"
93 #define strasm_ppc_lwsync "\n lwsync \n"
94 #define strasm_ppc_isync "\n isync \n"
95 #define strasm_ppc_release strasm_ppc_lwsync
96 #define strasm_ppc_acquire strasm_ppc_lwsync
97 #define strasm_ppc_fence strasm_ppc_sync
98 #define strasm_ppc_nobarrier ""
99 #define strasm_ppc_nobarrier_clobber_memory ""
100
101 inline jint Atomic::add (jint add_value, volatile jint* dest) {
102
103 unsigned int result;
104
105 __asm__ __volatile__ (
106 strasm_ppc_lwsync
107 "1: lwarx %0, 0, %2 \n"
108 " add %0, %0, %1 \n"
109 " stwcx. %0, 0, %2 \n"
110 " bne- 1b \n"
111 strasm_ppc_isync
112 : /*%0*/"=&r" (result)
113 : /*%1*/"r" (add_value), /*%2*/"r" (dest)
114 : "cc", "memory" );
115
116 return (jint) result;
117 }
118
119
120 inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
121
122 long result;
123
124 __asm__ __volatile__ (
125 strasm_ppc_lwsync
126 "1: ldarx %0, 0, %2 \n"
127 " add %0, %0, %1 \n"
128 " stdcx. %0, 0, %2 \n"
129 " bne- 1b \n"
130 strasm_ppc_isync
131 : /*%0*/"=&r" (result)
132 : /*%1*/"r" (add_value), /*%2*/"r" (dest)
133 : "cc", "memory" );
134
135 return (intptr_t) result;
136 }
137
138 inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) {
139 return (void*)add_ptr(add_value, (volatile intptr_t*)dest);
140 }
141
142
143 inline void Atomic::inc (volatile jint* dest) {
144
145 unsigned int temp;
146
147 __asm__ __volatile__ (
148 strasm_ppc_nobarrier
149 "1: lwarx %0, 0, %2 \n"
150 " addic %0, %0, 1 \n"
151 " stwcx. %0, 0, %2 \n"
152 " bne- 1b \n"
153 strasm_ppc_nobarrier
154 : /*%0*/"=&r" (temp), "=m" (*dest)
155 : /*%2*/"r" (dest), "m" (*dest)
156 : "cc" strasm_ppc_nobarrier_clobber_memory);
157
158 }
159
160 inline void Atomic::inc_ptr(volatile intptr_t* dest) {
161
162 long temp;
163
164 __asm__ __volatile__ (
165 strasm_ppc_nobarrier
166 "1: ldarx %0, 0, %2 \n"
167 " addic %0, %0, 1 \n"
168 " stdcx. %0, 0, %2 \n"
169 " bne- 1b \n"
170 strasm_ppc_nobarrier
171 : /*%0*/"=&r" (temp), "=m" (*dest)
172 : /*%2*/"r" (dest), "m" (*dest)
173 : "cc" strasm_ppc_nobarrier_clobber_memory);
174
175 }
176
177 inline void Atomic::inc_ptr(volatile void* dest) {
178 inc_ptr((volatile intptr_t*)dest);
179 }
180
181
182 inline void Atomic::dec (volatile jint* dest) {
183
184 unsigned int temp;
185
186 __asm__ __volatile__ (
187 strasm_ppc_nobarrier
188 "1: lwarx %0, 0, %2 \n"
189 " addic %0, %0, -1 \n"
190 " stwcx. %0, 0, %2 \n"
191 " bne- 1b \n"
192 strasm_ppc_nobarrier
193 : /*%0*/"=&r" (temp), "=m" (*dest)
194 : /*%2*/"r" (dest), "m" (*dest)
195 : "cc" strasm_ppc_nobarrier_clobber_memory);
196
197 }
198
199 inline void Atomic::dec_ptr(volatile intptr_t* dest) {
200
201 long temp;
202
203 __asm__ __volatile__ (
204 strasm_ppc_nobarrier
205 "1: ldarx %0, 0, %2 \n"
206 " addic %0, %0, -1 \n"
207 " stdcx. %0, 0, %2 \n"
208 " bne- 1b \n"
209 strasm_ppc_nobarrier
210 : /*%0*/"=&r" (temp), "=m" (*dest)
211 : /*%2*/"r" (dest), "m" (*dest)
212 : "cc" strasm_ppc_nobarrier_clobber_memory);
213
214 }
215
216 inline void Atomic::dec_ptr(volatile void* dest) {
217 dec_ptr((volatile intptr_t*)dest);
218 }
219
220 inline jint Atomic::xchg(jint exchange_value, volatile jint* dest) {
221
222 // Note that xchg_ptr doesn't necessarily do an acquire
223 // (see synchronizer.cpp).
224
225 unsigned int old_value;
226 const uint64_t zero = 0;
227
228 __asm__ __volatile__ (
229 /* lwsync */
230 strasm_ppc_lwsync
231 /* atomic loop */
232 "1: \n"
233 " lwarx %[old_value], %[dest], %[zero] \n"
234 " stwcx. %[exchange_value], %[dest], %[zero] \n"
235 " bne- 1b \n"
236 /* isync */
237 strasm_ppc_sync
238 /* exit */
239 "2: \n"
240 /* out */
241 : [old_value] "=&r" (old_value),
242 "=m" (*dest)
243 /* in */
244 : [dest] "b" (dest),
245 [zero] "r" (zero),
246 [exchange_value] "r" (exchange_value),
247 "m" (*dest)
248 /* clobber */
249 : "cc",
250 "memory"
251 );
252
253 return (jint) old_value;
254 }
255
256 inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) {
257
258 // Note that xchg_ptr doesn't necessarily do an acquire
259 // (see synchronizer.cpp).
260
261 long old_value;
262 const uint64_t zero = 0;
263
264 __asm__ __volatile__ (
265 /* lwsync */
266 strasm_ppc_lwsync
267 /* atomic loop */
268 "1: \n"
269 " ldarx %[old_value], %[dest], %[zero] \n"
270 " stdcx. %[exchange_value], %[dest], %[zero] \n"
271 " bne- 1b \n"
272 /* isync */
273 strasm_ppc_sync
274 /* exit */
275 "2: \n"
276 /* out */
277 : [old_value] "=&r" (old_value),
278 "=m" (*dest)
279 /* in */
280 : [dest] "b" (dest),
281 [zero] "r" (zero),
282 [exchange_value] "r" (exchange_value),
283 "m" (*dest)
284 /* clobber */
285 : "cc",
286 "memory"
287 );
288
289 return (intptr_t) old_value;
290 }
291
292 inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* dest) {
293 return (void*)xchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest);
294 }
295
296 inline jint Atomic::cmpxchg(jint exchange_value, volatile jint* dest, jint compare_value) {
297
298 // Note that cmpxchg guarantees a two-way memory barrier across
299 // the cmpxchg, so it's really a a 'fence_cmpxchg_acquire'
300 // (see atomic.hpp).
301
302 unsigned int old_value;
303 const uint64_t zero = 0;
304
305 __asm__ __volatile__ (
306 /* fence */
307 strasm_ppc_sync
308 /* simple guard */
309 " lwz %[old_value], 0(%[dest]) \n"
310 " cmpw %[compare_value], %[old_value] \n"
311 " bne- 2f \n"
312 /* atomic loop */
313 "1: \n"
314 " lwarx %[old_value], %[dest], %[zero] \n"
315 " cmpw %[compare_value], %[old_value] \n"
316 " bne- 2f \n"
317 " stwcx. %[exchange_value], %[dest], %[zero] \n"
318 " bne- 1b \n"
319 /* acquire */
320 strasm_ppc_sync
321 /* exit */
322 "2: \n"
323 /* out */
324 : [old_value] "=&r" (old_value),
325 "=m" (*dest)
326 /* in */
327 : [dest] "b" (dest),
328 [zero] "r" (zero),
329 [compare_value] "r" (compare_value),
330 [exchange_value] "r" (exchange_value),
331 "m" (*dest)
332 /* clobber */
333 : "cc",
334 "memory"
335 );
336
337 return (jint) old_value;
338 }
339
340 inline jlong Atomic::cmpxchg(jlong exchange_value, volatile jlong* dest, jlong compare_value) {
341
342 // Note that cmpxchg guarantees a two-way memory barrier across
343 // the cmpxchg, so it's really a a 'fence_cmpxchg_acquire'
344 // (see atomic.hpp).
345
346 long old_value;
347 const uint64_t zero = 0;
348
349 __asm__ __volatile__ (
350 /* fence */
351 strasm_ppc_sync
352 /* simple guard */
353 " ld %[old_value], 0(%[dest]) \n"
354 " cmpd %[compare_value], %[old_value] \n"
355 " bne- 2f \n"
356 /* atomic loop */
357 "1: \n"
358 " ldarx %[old_value], %[dest], %[zero] \n"
359 " cmpd %[compare_value], %[old_value] \n"
360 " bne- 2f \n"
361 " stdcx. %[exchange_value], %[dest], %[zero] \n"
362 " bne- 1b \n"
363 /* acquire */
364 strasm_ppc_sync
365 /* exit */
366 "2: \n"
367 /* out */
368 : [old_value] "=&r" (old_value),
369 "=m" (*dest)
370 /* in */
371 : [dest] "b" (dest),
372 [zero] "r" (zero),
373 [compare_value] "r" (compare_value),
374 [exchange_value] "r" (exchange_value),
375 "m" (*dest)
376 /* clobber */
377 : "cc",
378 "memory"
379 );
380
381 return (jlong) old_value;
382 }
383
384 inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) {
385 return (intptr_t)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value);
386 }
387
388 inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) {
389 return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value);
390 }
391
392 #undef strasm_ppc_sync
393 #undef strasm_ppc_lwsync
394 #undef strasm_ppc_isync
395 #undef strasm_ppc_release
396 #undef strasm_ppc_acquire
397 #undef strasm_ppc_fence
398 #undef strasm_ppc_nobarrier
399 #undef strasm_ppc_nobarrier_clobber_memory
400
401 #endif // OS_CPU_AIX_OJDKPPC_VM_ATOMIC_AIX_PPC_INLINE_HPP

mercurial