1 /*
2 * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2012, 2018 SAP SE. 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_LINUX_PPC_ATOMIC_LINUX_PPC_HPP
27 #define OS_CPU_LINUX_PPC_ATOMIC_LINUX_PPC_HPP
28
29 #ifndef PPC64
30 #error "Atomic currently only implemented for PPC64"
31 #endif
32
33 // Implementation of class atomic
34
35 //
36 // machine barrier instructions:
37 //
38 // - sync two-way memory barrier, aka fence
39 // - lwsync orders Store|Store,
40 // Load|Store,
41 // Load|Load,
42 // but not Store|Load
43 // - eieio orders memory accesses for device memory (only)
44 // - isync invalidates speculatively executed instructions
45 // From the POWER ISA 2.06 documentation:
46 // "[...] an isync instruction prevents the execution of
47 // instructions following the isync until instructions
48 // preceding the isync have completed, [...]"
49 // From IBM's AIX assembler reference:
50 // "The isync [...] instructions causes the processor to
51 // refetch any instructions that might have been fetched
52 // prior to the isync instruction. The instruction isync
53 // causes the processor to wait for all previous instructions
54 // to complete. Then any instructions already fetched are
55 // discarded and instruction processing continues in the
56 // environment established by the previous instructions."
57 //
58 // semantic barrier instructions:
59 // (as defined in orderAccess.hpp)
60 //
61 // - release orders Store|Store, (maps to lwsync)
62 // Load|Store
63 // - acquire orders Load|Store, (maps to lwsync)
64 // Load|Load
65 // - fence orders Store|Store, (maps to sync)
66 // Load|Store,
67 // Load|Load,
68 // Store|Load
69 //
70
71 #define strasm_sync "\n sync \n"
72 #define strasm_lwsync "\n lwsync \n"
73 #define strasm_isync "\n isync \n"
74 #define strasm_release strasm_lwsync
75 #define strasm_acquire strasm_lwsync
76 #define strasm_fence strasm_sync
77 #define strasm_nobarrier ""
78 #define strasm_nobarrier_clobber_memory ""
79
80 inline void pre_membar(atomic_memory_order order) {
81 switch (order) {
82 case memory_order_relaxed:
83 case memory_order_acquire: break;
84 case memory_order_release:
85 case memory_order_acq_rel: __asm__ __volatile__ (strasm_lwsync); break;
86 default /*conservative*/ : __asm__ __volatile__ (strasm_sync); break;
87 }
88 }
89
90 inline void post_membar(atomic_memory_order order) {
91 switch (order) {
92 case memory_order_relaxed:
93 case memory_order_release: break;
94 case memory_order_acquire:
95 case memory_order_acq_rel: __asm__ __volatile__ (strasm_isync); break;
96 default /*conservative*/ : __asm__ __volatile__ (strasm_sync); break;
97 }
98 }
99
100
101 template<size_t byte_size>
102 struct Atomic::PlatformAdd
103 : Atomic::AddAndFetch<Atomic::PlatformAdd<byte_size> >
104 {
105 template<typename I, typename D>
106 D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const;
107 };
108
109 template<>
110 template<typename I, typename D>
111 inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest,
112 atomic_memory_order order) const {
113 STATIC_ASSERT(4 == sizeof(I));
114 STATIC_ASSERT(4 == sizeof(D));
115
116 D result;
388 /* exit */
389 "2: \n"
390 /* out */
391 : [old_value] "=&r" (old_value),
392 "=m" (*dest)
393 /* in */
394 : [dest] "b" (dest),
395 [zero] "r" (zero),
396 [compare_value] "r" (compare_value),
397 [exchange_value] "r" (exchange_value),
398 "m" (*dest)
399 /* clobber */
400 : "cc",
401 "memory"
402 );
403
404 post_membar(order);
405
406 return old_value;
407 }
408
409 #undef strasm_sync
410 #undef strasm_lwsync
411 #undef strasm_isync
412 #undef strasm_release
413 #undef strasm_acquire
414 #undef strasm_fence
415 #undef strasm_nobarrier
416 #undef strasm_nobarrier_clobber_memory
417
418 #endif // OS_CPU_LINUX_PPC_ATOMIC_LINUX_PPC_HPP
|
1 /*
2 * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2012, 2019 SAP SE. 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_LINUX_PPC_ATOMIC_LINUX_PPC_HPP
27 #define OS_CPU_LINUX_PPC_ATOMIC_LINUX_PPC_HPP
28
29 #ifndef PPC64
30 #error "Atomic currently only implemented for PPC64"
31 #endif
32
33 #include "utilities/debug.hpp"
34
35 // Implementation of class atomic
36
37 //
38 // machine barrier instructions:
39 //
40 // - sync two-way memory barrier, aka fence
41 // - lwsync orders Store|Store,
42 // Load|Store,
43 // Load|Load,
44 // but not Store|Load
45 // - eieio orders memory accesses for device memory (only)
46 // - isync invalidates speculatively executed instructions
47 // From the POWER ISA 2.06 documentation:
48 // "[...] an isync instruction prevents the execution of
49 // instructions following the isync until instructions
50 // preceding the isync have completed, [...]"
51 // From IBM's AIX assembler reference:
52 // "The isync [...] instructions causes the processor to
53 // refetch any instructions that might have been fetched
54 // prior to the isync instruction. The instruction isync
55 // causes the processor to wait for all previous instructions
56 // to complete. Then any instructions already fetched are
57 // discarded and instruction processing continues in the
58 // environment established by the previous instructions."
59 //
60 // semantic barrier instructions:
61 // (as defined in orderAccess.hpp)
62 //
63 // - release orders Store|Store, (maps to lwsync)
64 // Load|Store
65 // - acquire orders Load|Store, (maps to lwsync)
66 // Load|Load
67 // - fence orders Store|Store, (maps to sync)
68 // Load|Store,
69 // Load|Load,
70 // Store|Load
71 //
72
73 inline void pre_membar(atomic_memory_order order) {
74 switch (order) {
75 case memory_order_relaxed:
76 case memory_order_acquire: break;
77 case memory_order_release:
78 case memory_order_acq_rel: __asm__ __volatile__ ("lwsync" : : : "memory"); break;
79 default /*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break;
80 }
81 }
82
83 inline void post_membar(atomic_memory_order order) {
84 switch (order) {
85 case memory_order_relaxed:
86 case memory_order_release: break;
87 case memory_order_acquire:
88 case memory_order_acq_rel: __asm__ __volatile__ ("isync" : : : "memory"); break;
89 default /*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break;
90 }
91 }
92
93
94 template<size_t byte_size>
95 struct Atomic::PlatformAdd
96 : Atomic::AddAndFetch<Atomic::PlatformAdd<byte_size> >
97 {
98 template<typename I, typename D>
99 D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const;
100 };
101
102 template<>
103 template<typename I, typename D>
104 inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest,
105 atomic_memory_order order) const {
106 STATIC_ASSERT(4 == sizeof(I));
107 STATIC_ASSERT(4 == sizeof(D));
108
109 D result;
381 /* exit */
382 "2: \n"
383 /* out */
384 : [old_value] "=&r" (old_value),
385 "=m" (*dest)
386 /* in */
387 : [dest] "b" (dest),
388 [zero] "r" (zero),
389 [compare_value] "r" (compare_value),
390 [exchange_value] "r" (exchange_value),
391 "m" (*dest)
392 /* clobber */
393 : "cc",
394 "memory"
395 );
396
397 post_membar(order);
398
399 return old_value;
400 }
401
402 #endif // OS_CPU_LINUX_PPC_ATOMIC_LINUX_PPC_HPP
|