Mercurial > hg > truffle
comparison src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp @ 14415:666e6ce3976c
8023038: PPC64 (part 15): Platform files for AIX/PPC64 support
Reviewed-by: kvn
author | simonis |
---|---|
date | Fri, 06 Sep 2013 20:16:09 +0200 |
parents | |
children | b858620b0081 |
comparison
equal
deleted
inserted
replaced
14414:b83f7d608548 | 14415: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 |