2 * Distributed under the Boost Software License, Version 1.0.
3 * (See accompanying file LICENSE_1_0.txt or copy at
4 * http://www.boost.org/LICENSE_1_0.txt)
6 * Copyright (c) 2009 Helge Bahmann
7 * Copyright (c) 2013 Tim Blechmann
8 * Copyright (c) 2014 Andrey Semashev
11 * \file atomic/detail/ops_gcc_alpha.hpp
13 * This header contains implementation of the \c operations template.
16 #ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_ALPHA_HPP_INCLUDED_
17 #define BOOST_ATOMIC_DETAIL_OPS_GCC_ALPHA_HPP_INCLUDED_
19 #include <boost/memory_order.hpp>
20 #include <boost/atomic/detail/config.hpp>
21 #include <boost/atomic/detail/storage_type.hpp>
22 #include <boost/atomic/detail/operations_fwd.hpp>
23 #include <boost/atomic/capabilities.hpp>
25 #ifdef BOOST_HAS_PRAGMA_ONCE
34 Refer to http://h71000.www7.hp.com/doc/82final/5601/5601pro_004.html
35 (HP OpenVMS systems documentation) and the Alpha Architecture Reference Manual.
39 NB: The most natural thing would be to write the increment/decrement
40 operators along the following lines:
53 However according to the comments on the HP website and matching
54 comments in the Linux kernel sources this defies branch prediction,
55 as the cpu assumes that backward branches are always taken; so
56 instead copy the trick from the Linux kernel, introduce a forward
57 branch and back again.
59 I have, however, had a hard time measuring the difference between
60 the two versions in microbenchmarks -- I am leaving it in nevertheless
61 as it apparently does not hurt either.
64 struct gcc_alpha_operations_base
66 static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
68 static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
70 if ((order & memory_order_release) != 0)
71 __asm__ __volatile__ ("mb" ::: "memory");
74 static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT
76 if ((order & (memory_order_consume | memory_order_acquire)) != 0)
77 __asm__ __volatile__ ("mb" ::: "memory");
80 static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT
82 if (order == memory_order_seq_cst)
83 __asm__ __volatile__ ("mb" ::: "memory");
88 template< bool Signed >
89 struct operations< 4u, Signed > :
90 public gcc_alpha_operations_base
92 typedef typename make_storage_type< 4u, Signed >::type storage_type;
93 typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
95 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
99 fence_after_store(order);
102 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
104 storage_type v = storage;
109 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
111 storage_type original, tmp;
125 : "=&r" (original), // %0
127 : "m" (storage), // %2
129 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
135 static BOOST_FORCEINLINE bool compare_exchange_weak(
136 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
138 fence_before(success_order);
140 storage_type current;
144 "ldl_l %2, %4\n" // current = *(&storage)
145 "cmpeq %2, %0, %3\n" // success = current == expected
146 "mov %2, %0\n" // expected = current
147 "beq %3, 2f\n" // if (success == 0) goto end
148 "stl_c %1, %4\n" // storage = desired; desired = store succeeded
149 "mov %1, %3\n" // success = desired
151 : "+&r" (expected), // %0
152 "+&r" (desired), // %1
153 "=&r" (current), // %2
154 "=&r" (success) // %3
155 : "m" (storage) // %4
156 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
159 fence_after(success_order);
161 fence_after(failure_order);
165 static BOOST_FORCEINLINE bool compare_exchange_strong(
166 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
169 storage_type current, tmp;
170 fence_before(success_order);
174 "mov %5, %1\n" // tmp = desired
175 "ldl_l %2, %4\n" // current = *(&storage)
176 "cmpeq %2, %0, %3\n" // success = current == expected
177 "mov %2, %0\n" // expected = current
178 "beq %3, 2f\n" // if (success == 0) goto end
179 "stl_c %1, %4\n" // storage = tmp; tmp = store succeeded
180 "beq %1, 3f\n" // if (tmp == 0) goto retry
181 "mov %1, %3\n" // success = tmp
188 : "+&r" (expected), // %0
190 "=&r" (current), // %2
191 "=&r" (success) // %3
192 : "m" (storage), // %4
194 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
197 fence_after(success_order);
199 fence_after(failure_order);
203 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
205 storage_type original, modified;
219 : "=&r" (original), // %0
220 "=&r" (modified) // %1
221 : "m" (storage), // %2
223 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
229 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
231 storage_type original, modified;
245 : "=&r" (original), // %0
246 "=&r" (modified) // %1
247 : "m" (storage), // %2
249 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
255 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
257 storage_type original, modified;
271 : "=&r" (original), // %0
272 "=&r" (modified) // %1
273 : "m" (storage), // %2
275 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
281 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
283 storage_type original, modified;
297 : "=&r" (original), // %0
298 "=&r" (modified) // %1
299 : "m" (storage), // %2
301 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
307 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
309 storage_type original, modified;
323 : "=&r" (original), // %0
324 "=&r" (modified) // %1
325 : "m" (storage), // %2
327 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
333 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
335 return !!exchange(storage, (storage_type)1, order);
338 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
340 store(storage, 0, order);
343 static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
351 struct operations< 1u, false > :
352 public operations< 4u, false >
354 typedef operations< 4u, false > base_type;
355 typedef base_type::storage_type storage_type;
357 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
359 storage_type original, modified;
366 "zapnot %1, #1, %1\n"
374 : "=&r" (original), // %0
375 "=&r" (modified) // %1
376 : "m" (storage), // %2
378 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
384 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
386 storage_type original, modified;
393 "zapnot %1, #1, %1\n"
401 : "=&r" (original), // %0
402 "=&r" (modified) // %1
403 : "m" (storage), // %2
405 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
413 struct operations< 1u, true > :
414 public operations< 4u, true >
416 typedef operations< 4u, true > base_type;
417 typedef base_type::storage_type storage_type;
419 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
421 storage_type original, modified;
436 : "=&r" (original), // %0
437 "=&r" (modified) // %1
438 : "m" (storage), // %2
440 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
446 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
448 storage_type original, modified;
463 : "=&r" (original), // %0
464 "=&r" (modified) // %1
465 : "m" (storage), // %2
467 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
476 struct operations< 2u, false > :
477 public operations< 4u, false >
479 typedef operations< 4u, false > base_type;
480 typedef base_type::storage_type storage_type;
482 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
484 storage_type original, modified;
491 "zapnot %1, #3, %1\n"
499 : "=&r" (original), // %0
500 "=&r" (modified) // %1
501 : "m" (storage), // %2
503 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
509 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
511 storage_type original, modified;
518 "zapnot %1, #3, %1\n"
526 : "=&r" (original), // %0
527 "=&r" (modified) // %1
528 : "m" (storage), // %2
530 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
538 struct operations< 2u, true > :
539 public operations< 4u, true >
541 typedef operations< 4u, true > base_type;
542 typedef base_type::storage_type storage_type;
544 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
546 storage_type original, modified;
561 : "=&r" (original), // %0
562 "=&r" (modified) // %1
563 : "m" (storage), // %2
565 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
571 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
573 storage_type original, modified;
588 : "=&r" (original), // %0
589 "=&r" (modified) // %1
590 : "m" (storage), // %2
592 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
600 template< bool Signed >
601 struct operations< 8u, Signed > :
602 public gcc_alpha_operations_base
604 typedef typename make_storage_type< 8u, Signed >::type storage_type;
605 typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
607 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
611 fence_after_store(order);
614 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
616 storage_type v = storage;
621 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
623 storage_type original, tmp;
637 : "=&r" (original), // %0
639 : "m" (storage), // %2
641 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
647 static BOOST_FORCEINLINE bool compare_exchange_weak(
648 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
650 fence_before(success_order);
652 storage_type current;
656 "ldq_l %2, %4\n" // current = *(&storage)
657 "cmpeq %2, %0, %3\n" // success = current == expected
658 "mov %2, %0\n" // expected = current
659 "beq %3, 2f\n" // if (success == 0) goto end
660 "stq_c %1, %4\n" // storage = desired; desired = store succeeded
661 "mov %1, %3\n" // success = desired
663 : "+&r" (expected), // %0
664 "+&r" (desired), // %1
665 "=&r" (current), // %2
666 "=&r" (success) // %3
667 : "m" (storage) // %4
668 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
671 fence_after(success_order);
673 fence_after(failure_order);
677 static BOOST_FORCEINLINE bool compare_exchange_strong(
678 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
681 storage_type current, tmp;
682 fence_before(success_order);
686 "mov %5, %1\n" // tmp = desired
687 "ldq_l %2, %4\n" // current = *(&storage)
688 "cmpeq %2, %0, %3\n" // success = current == expected
689 "mov %2, %0\n" // expected = current
690 "beq %3, 2f\n" // if (success == 0) goto end
691 "stq_c %1, %4\n" // storage = tmp; tmp = store succeeded
692 "beq %1, 3f\n" // if (tmp == 0) goto retry
693 "mov %1, %3\n" // success = tmp
700 : "+&r" (expected), // %0
702 "=&r" (current), // %2
703 "=&r" (success) // %3
704 : "m" (storage), // %4
706 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
709 fence_after(success_order);
711 fence_after(failure_order);
715 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
717 storage_type original, modified;
731 : "=&r" (original), // %0
732 "=&r" (modified) // %1
733 : "m" (storage), // %2
735 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
741 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
743 storage_type original, modified;
757 : "=&r" (original), // %0
758 "=&r" (modified) // %1
759 : "m" (storage), // %2
761 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
767 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
769 storage_type original, modified;
783 : "=&r" (original), // %0
784 "=&r" (modified) // %1
785 : "m" (storage), // %2
787 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
793 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
795 storage_type original, modified;
809 : "=&r" (original), // %0
810 "=&r" (modified) // %1
811 : "m" (storage), // %2
813 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
819 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
821 storage_type original, modified;
835 : "=&r" (original), // %0
836 "=&r" (modified) // %1
837 : "m" (storage), // %2
839 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
845 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
847 return !!exchange(storage, (storage_type)1, order);
850 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
852 store(storage, 0, order);
855 static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
862 BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
864 if (order != memory_order_relaxed)
865 __asm__ __volatile__ ("mb" ::: "memory");
868 BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
870 if (order != memory_order_relaxed)
871 __asm__ __volatile__ ("" ::: "memory");
874 } // namespace detail
875 } // namespace atomics
878 #endif // BOOST_ATOMIC_DETAIL_OPS_GCC_ALPHA_HPP_INCLUDED_