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/core_arch_ops_gcc_alpha.hpp
13 * This header contains implementation of the \c core_arch_operations template.
16 #ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_ALPHA_HPP_INCLUDED_
17 #define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_ALPHA_HPP_INCLUDED_
20 #include <boost/memory_order.hpp>
21 #include <boost/atomic/detail/config.hpp>
22 #include <boost/atomic/detail/storage_traits.hpp>
23 #include <boost/atomic/detail/core_arch_operations_fwd.hpp>
24 #include <boost/atomic/detail/header.hpp>
26 #ifdef BOOST_HAS_PRAGMA_ONCE
35 Refer to http://h71000.www7.hp.com/doc/82final/5601/5601pro_004.html
36 (HP OpenVMS systems documentation) and the Alpha Architecture Reference Manual.
40 NB: The most natural thing would be to write the increment/decrement
41 operators along the following lines:
54 However according to the comments on the HP website and matching
55 comments in the Linux kernel sources this defies branch prediction,
56 as the cpu assumes that backward branches are always taken; so
57 instead copy the trick from the Linux kernel, introduce a forward
58 branch and back again.
60 I have, however, had a hard time measuring the difference between
61 the two versions in microbenchmarks -- I am leaving it in nevertheless
62 as it apparently does not hurt either.
65 struct core_arch_operations_gcc_alpha_base
67 static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false;
68 static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
70 static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
72 if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u)
73 __asm__ __volatile__ ("mb" ::: "memory");
76 static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT
78 if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
79 __asm__ __volatile__ ("mb" ::: "memory");
82 static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT
84 if (order == memory_order_seq_cst)
85 __asm__ __volatile__ ("mb" ::: "memory");
90 template< bool Signed, bool Interprocess >
91 struct core_arch_operations< 4u, Signed, Interprocess > :
92 public core_arch_operations_gcc_alpha_base
94 typedef typename storage_traits< 4u >::type storage_type;
96 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u;
97 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 4u;
98 static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
99 static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
101 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
105 fence_after_store(order);
108 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
110 storage_type v = storage;
115 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
117 storage_type original, tmp;
131 : "=&r" (original), // %0
133 : "m" (storage), // %2
135 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
141 static BOOST_FORCEINLINE bool compare_exchange_weak(
142 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
144 fence_before(success_order);
146 storage_type current;
150 "ldl_l %2, %4\n\t" // current = *(&storage)
151 "cmpeq %2, %0, %3\n\t" // success = current == expected
152 "mov %2, %0\n\t" // expected = current
153 "beq %3, 2f\n\t" // if (success == 0) goto end
154 "stl_c %1, %4\n\t" // storage = desired; desired = store succeeded
155 "mov %1, %3\n\t" // success = desired
157 : "+r" (expected), // %0
158 "+r" (desired), // %1
159 "=&r" (current), // %2
160 "=&r" (success) // %3
161 : "m" (storage) // %4
162 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
165 fence_after(success_order);
167 fence_after(failure_order);
171 static BOOST_FORCEINLINE bool compare_exchange_strong(
172 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
175 storage_type current, tmp;
176 fence_before(success_order);
180 "mov %5, %1\n\t" // tmp = desired
181 "ldl_l %2, %4\n\t" // current = *(&storage)
182 "cmpeq %2, %0, %3\n\t" // success = current == expected
183 "mov %2, %0\n\t" // expected = current
184 "beq %3, 2f\n\t" // if (success == 0) goto end
185 "stl_c %1, %4\n\t" // storage = tmp; tmp = store succeeded
186 "beq %1, 3f\n\t" // if (tmp == 0) goto retry
187 "mov %1, %3\n\t" // success = tmp
194 : "+r" (expected), // %0
196 "=&r" (current), // %2
197 "=&r" (success) // %3
198 : "m" (storage), // %4
200 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
203 fence_after(success_order);
205 fence_after(failure_order);
209 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
211 storage_type original, modified;
217 "addl %0, %3, %1\n\t"
225 : "=&r" (original), // %0
226 "=&r" (modified) // %1
227 : "m" (storage), // %2
229 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
235 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
237 storage_type original, modified;
243 "subl %0, %3, %1\n\t"
251 : "=&r" (original), // %0
252 "=&r" (modified) // %1
253 : "m" (storage), // %2
255 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
261 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
263 storage_type original, modified;
277 : "=&r" (original), // %0
278 "=&r" (modified) // %1
279 : "m" (storage), // %2
281 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
287 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
289 storage_type original, modified;
303 : "=&r" (original), // %0
304 "=&r" (modified) // %1
305 : "m" (storage), // %2
307 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
313 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
315 storage_type original, modified;
329 : "=&r" (original), // %0
330 "=&r" (modified) // %1
331 : "m" (storage), // %2
333 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
339 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
341 return !!exchange(storage, (storage_type)1, order);
344 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
346 store(storage, 0, order);
351 template< bool Interprocess >
352 struct core_arch_operations< 1u, false, Interprocess > :
353 public core_arch_operations< 4u, false, Interprocess >
355 typedef core_arch_operations< 4u, false, Interprocess > base_type;
356 typedef typename base_type::storage_type storage_type;
358 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
360 storage_type original, modified;
361 base_type::fence_before(order);
366 "addl %0, %3, %1\n\t"
367 "zapnot %1, 1, %1\n\t"
375 : "=&r" (original), // %0
376 "=&r" (modified) // %1
377 : "m" (storage), // %2
379 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
381 base_type::fence_after(order);
385 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
387 storage_type original, modified;
388 base_type::fence_before(order);
393 "subl %0, %3, %1\n\t"
394 "zapnot %1, 1, %1\n\t"
402 : "=&r" (original), // %0
403 "=&r" (modified) // %1
404 : "m" (storage), // %2
406 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
408 base_type::fence_after(order);
413 template< bool Interprocess >
414 struct core_arch_operations< 1u, true, Interprocess > :
415 public core_arch_operations< 4u, true, Interprocess >
417 typedef core_arch_operations< 4u, true, Interprocess > base_type;
418 typedef typename base_type::storage_type storage_type;
420 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
422 storage_type original, modified;
423 base_type::fence_before(order);
428 "addl %0, %3, %1\n\t"
437 : "=&r" (original), // %0
438 "=&r" (modified) // %1
439 : "m" (storage), // %2
441 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
443 base_type::fence_after(order);
447 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
449 storage_type original, modified;
450 base_type::fence_before(order);
455 "subl %0, %3, %1\n\t"
464 : "=&r" (original), // %0
465 "=&r" (modified) // %1
466 : "m" (storage), // %2
468 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
470 base_type::fence_after(order);
476 template< bool Interprocess >
477 struct core_arch_operations< 2u, false, Interprocess > :
478 public core_arch_operations< 4u, false, Interprocess >
480 typedef core_arch_operations< 4u, false, Interprocess > base_type;
481 typedef typename base_type::storage_type storage_type;
483 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
485 storage_type original, modified;
486 base_type::fence_before(order);
491 "addl %0, %3, %1\n\t"
492 "zapnot %1, 3, %1\n\t"
500 : "=&r" (original), // %0
501 "=&r" (modified) // %1
502 : "m" (storage), // %2
504 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
506 base_type::fence_after(order);
510 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
512 storage_type original, modified;
513 base_type::fence_before(order);
518 "subl %0, %3, %1\n\t"
519 "zapnot %1, 3, %1\n\t"
527 : "=&r" (original), // %0
528 "=&r" (modified) // %1
529 : "m" (storage), // %2
531 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
533 base_type::fence_after(order);
538 template< bool Interprocess >
539 struct core_arch_operations< 2u, true, Interprocess > :
540 public core_arch_operations< 4u, true, Interprocess >
542 typedef core_arch_operations< 4u, true, Interprocess > base_type;
543 typedef typename base_type::storage_type storage_type;
545 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
547 storage_type original, modified;
548 base_type::fence_before(order);
553 "addl %0, %3, %1\n\t"
562 : "=&r" (original), // %0
563 "=&r" (modified) // %1
564 : "m" (storage), // %2
566 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
568 base_type::fence_after(order);
572 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
574 storage_type original, modified;
575 base_type::fence_before(order);
580 "subl %0, %3, %1\n\t"
589 : "=&r" (original), // %0
590 "=&r" (modified) // %1
591 : "m" (storage), // %2
593 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
595 base_type::fence_after(order);
601 template< bool Signed, bool Interprocess >
602 struct core_arch_operations< 8u, Signed, Interprocess > :
603 public core_arch_operations_gcc_alpha_base
605 typedef typename storage_traits< 8u >::type storage_type;
607 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u;
608 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 8u;
609 static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
610 static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
612 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
616 fence_after_store(order);
619 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
621 storage_type v = storage;
626 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
628 storage_type original, tmp;
642 : "=&r" (original), // %0
644 : "m" (storage), // %2
646 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
652 static BOOST_FORCEINLINE bool compare_exchange_weak(
653 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
655 fence_before(success_order);
657 storage_type current;
661 "ldq_l %2, %4\n\t" // current = *(&storage)
662 "cmpeq %2, %0, %3\n\t" // success = current == expected
663 "mov %2, %0\n\t" // expected = current
664 "beq %3, 2f\n\t" // if (success == 0) goto end
665 "stq_c %1, %4\n\t" // storage = desired; desired = store succeeded
666 "mov %1, %3\n\t" // success = desired
668 : "+r" (expected), // %0
669 "+r" (desired), // %1
670 "=&r" (current), // %2
671 "=&r" (success) // %3
672 : "m" (storage) // %4
673 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
676 fence_after(success_order);
678 fence_after(failure_order);
682 static BOOST_FORCEINLINE bool compare_exchange_strong(
683 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
686 storage_type current, tmp;
687 fence_before(success_order);
691 "mov %5, %1\n\t" // tmp = desired
692 "ldq_l %2, %4\n\t" // current = *(&storage)
693 "cmpeq %2, %0, %3\n\t" // success = current == expected
694 "mov %2, %0\n\t" // expected = current
695 "beq %3, 2f\n\t" // if (success == 0) goto end
696 "stq_c %1, %4\n\t" // storage = tmp; tmp = store succeeded
697 "beq %1, 3f\n\t" // if (tmp == 0) goto retry
698 "mov %1, %3\n\t" // success = tmp
705 : "+r" (expected), // %0
707 "=&r" (current), // %2
708 "=&r" (success) // %3
709 : "m" (storage), // %4
711 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
714 fence_after(success_order);
716 fence_after(failure_order);
720 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
722 storage_type original, modified;
728 "addq %0, %3, %1\n\t"
736 : "=&r" (original), // %0
737 "=&r" (modified) // %1
738 : "m" (storage), // %2
740 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
746 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
748 storage_type original, modified;
754 "subq %0, %3, %1\n\t"
762 : "=&r" (original), // %0
763 "=&r" (modified) // %1
764 : "m" (storage), // %2
766 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
772 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
774 storage_type original, modified;
788 : "=&r" (original), // %0
789 "=&r" (modified) // %1
790 : "m" (storage), // %2
792 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
798 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
800 storage_type original, modified;
814 : "=&r" (original), // %0
815 "=&r" (modified) // %1
816 : "m" (storage), // %2
818 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
824 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
826 storage_type original, modified;
840 : "=&r" (original), // %0
841 "=&r" (modified) // %1
842 : "m" (storage), // %2
844 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
850 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
852 return !!exchange(storage, (storage_type)1, order);
855 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
857 store(storage, (storage_type)0, order);
861 } // namespace detail
862 } // namespace atomics
865 #include <boost/atomic/detail/footer.hpp>
867 #endif // BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_ALPHA_HPP_INCLUDED_