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_
20 #include <boost/memory_order.hpp>
21 #include <boost/atomic/detail/config.hpp>
22 #include <boost/atomic/detail/storage_type.hpp>
23 #include <boost/atomic/detail/operations_fwd.hpp>
24 #include <boost/atomic/capabilities.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 gcc_alpha_operations_base
67 static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
69 static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT
71 if ((order & memory_order_release) != 0)
72 __asm__ __volatile__ ("mb" ::: "memory");
75 static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT
77 if ((order & (memory_order_consume | memory_order_acquire)) != 0)
78 __asm__ __volatile__ ("mb" ::: "memory");
81 static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT
83 if (order == memory_order_seq_cst)
84 __asm__ __volatile__ ("mb" ::: "memory");
89 template< bool Signed >
90 struct operations< 4u, Signed > :
91 public gcc_alpha_operations_base
93 typedef typename make_storage_type< 4u, Signed >::type storage_type;
94 typedef typename make_storage_type< 4u, Signed >::aligned aligned_storage_type;
96 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u;
97 static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
99 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
103 fence_after_store(order);
106 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
108 storage_type v = storage;
113 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
115 storage_type original, tmp;
129 : "=&r" (original), // %0
131 : "m" (storage), // %2
133 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
139 static BOOST_FORCEINLINE bool compare_exchange_weak(
140 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
142 fence_before(success_order);
144 storage_type current;
148 "ldl_l %2, %4\n" // current = *(&storage)
149 "cmpeq %2, %0, %3\n" // success = current == expected
150 "mov %2, %0\n" // expected = current
151 "beq %3, 2f\n" // if (success == 0) goto end
152 "stl_c %1, %4\n" // storage = desired; desired = store succeeded
153 "mov %1, %3\n" // success = desired
155 : "+&r" (expected), // %0
156 "+&r" (desired), // %1
157 "=&r" (current), // %2
158 "=&r" (success) // %3
159 : "m" (storage) // %4
160 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
163 fence_after(success_order);
165 fence_after(failure_order);
169 static BOOST_FORCEINLINE bool compare_exchange_strong(
170 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
173 storage_type current, tmp;
174 fence_before(success_order);
178 "mov %5, %1\n" // tmp = desired
179 "ldl_l %2, %4\n" // current = *(&storage)
180 "cmpeq %2, %0, %3\n" // success = current == expected
181 "mov %2, %0\n" // expected = current
182 "beq %3, 2f\n" // if (success == 0) goto end
183 "stl_c %1, %4\n" // storage = tmp; tmp = store succeeded
184 "beq %1, 3f\n" // if (tmp == 0) goto retry
185 "mov %1, %3\n" // success = tmp
192 : "+&r" (expected), // %0
194 "=&r" (current), // %2
195 "=&r" (success) // %3
196 : "m" (storage), // %4
198 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
201 fence_after(success_order);
203 fence_after(failure_order);
207 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
209 storage_type original, modified;
223 : "=&r" (original), // %0
224 "=&r" (modified) // %1
225 : "m" (storage), // %2
227 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
233 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
235 storage_type original, modified;
249 : "=&r" (original), // %0
250 "=&r" (modified) // %1
251 : "m" (storage), // %2
253 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
259 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
261 storage_type original, modified;
275 : "=&r" (original), // %0
276 "=&r" (modified) // %1
277 : "m" (storage), // %2
279 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
285 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
287 storage_type original, modified;
301 : "=&r" (original), // %0
302 "=&r" (modified) // %1
303 : "m" (storage), // %2
305 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
311 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
313 storage_type original, modified;
327 : "=&r" (original), // %0
328 "=&r" (modified) // %1
329 : "m" (storage), // %2
331 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
337 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
339 return !!exchange(storage, (storage_type)1, order);
342 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
344 store(storage, 0, order);
350 struct operations< 1u, false > :
351 public operations< 4u, false >
353 typedef operations< 4u, false > base_type;
354 typedef base_type::storage_type storage_type;
356 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
358 storage_type original, modified;
365 "zapnot %1, #1, %1\n"
373 : "=&r" (original), // %0
374 "=&r" (modified) // %1
375 : "m" (storage), // %2
377 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
383 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
385 storage_type original, modified;
392 "zapnot %1, #1, %1\n"
400 : "=&r" (original), // %0
401 "=&r" (modified) // %1
402 : "m" (storage), // %2
404 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
412 struct operations< 1u, true > :
413 public operations< 4u, true >
415 typedef operations< 4u, true > base_type;
416 typedef base_type::storage_type storage_type;
418 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
420 storage_type original, modified;
435 : "=&r" (original), // %0
436 "=&r" (modified) // %1
437 : "m" (storage), // %2
439 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
445 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
447 storage_type original, modified;
462 : "=&r" (original), // %0
463 "=&r" (modified) // %1
464 : "m" (storage), // %2
466 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
475 struct operations< 2u, false > :
476 public operations< 4u, false >
478 typedef operations< 4u, false > base_type;
479 typedef base_type::storage_type storage_type;
481 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
483 storage_type original, modified;
490 "zapnot %1, #3, %1\n"
498 : "=&r" (original), // %0
499 "=&r" (modified) // %1
500 : "m" (storage), // %2
502 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
508 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
510 storage_type original, modified;
517 "zapnot %1, #3, %1\n"
525 : "=&r" (original), // %0
526 "=&r" (modified) // %1
527 : "m" (storage), // %2
529 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
537 struct operations< 2u, true > :
538 public operations< 4u, true >
540 typedef operations< 4u, true > base_type;
541 typedef base_type::storage_type storage_type;
543 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
545 storage_type original, modified;
560 : "=&r" (original), // %0
561 "=&r" (modified) // %1
562 : "m" (storage), // %2
564 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
570 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
572 storage_type original, modified;
587 : "=&r" (original), // %0
588 "=&r" (modified) // %1
589 : "m" (storage), // %2
591 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
599 template< bool Signed >
600 struct operations< 8u, Signed > :
601 public gcc_alpha_operations_base
603 typedef typename make_storage_type< 8u, Signed >::type storage_type;
604 typedef typename make_storage_type< 8u, Signed >::aligned aligned_storage_type;
606 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u;
607 static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
609 static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
613 fence_after_store(order);
616 static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
618 storage_type v = storage;
623 static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
625 storage_type original, tmp;
639 : "=&r" (original), // %0
641 : "m" (storage), // %2
643 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
649 static BOOST_FORCEINLINE bool compare_exchange_weak(
650 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
652 fence_before(success_order);
654 storage_type current;
658 "ldq_l %2, %4\n" // current = *(&storage)
659 "cmpeq %2, %0, %3\n" // success = current == expected
660 "mov %2, %0\n" // expected = current
661 "beq %3, 2f\n" // if (success == 0) goto end
662 "stq_c %1, %4\n" // storage = desired; desired = store succeeded
663 "mov %1, %3\n" // success = desired
665 : "+&r" (expected), // %0
666 "+&r" (desired), // %1
667 "=&r" (current), // %2
668 "=&r" (success) // %3
669 : "m" (storage) // %4
670 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
673 fence_after(success_order);
675 fence_after(failure_order);
679 static BOOST_FORCEINLINE bool compare_exchange_strong(
680 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
683 storage_type current, tmp;
684 fence_before(success_order);
688 "mov %5, %1\n" // tmp = desired
689 "ldq_l %2, %4\n" // current = *(&storage)
690 "cmpeq %2, %0, %3\n" // success = current == expected
691 "mov %2, %0\n" // expected = current
692 "beq %3, 2f\n" // if (success == 0) goto end
693 "stq_c %1, %4\n" // storage = tmp; tmp = store succeeded
694 "beq %1, 3f\n" // if (tmp == 0) goto retry
695 "mov %1, %3\n" // success = tmp
702 : "+&r" (expected), // %0
704 "=&r" (current), // %2
705 "=&r" (success) // %3
706 : "m" (storage), // %4
708 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
711 fence_after(success_order);
713 fence_after(failure_order);
717 static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
719 storage_type original, modified;
733 : "=&r" (original), // %0
734 "=&r" (modified) // %1
735 : "m" (storage), // %2
737 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
743 static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
745 storage_type original, modified;
759 : "=&r" (original), // %0
760 "=&r" (modified) // %1
761 : "m" (storage), // %2
763 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
769 static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
771 storage_type original, modified;
785 : "=&r" (original), // %0
786 "=&r" (modified) // %1
787 : "m" (storage), // %2
789 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
795 static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
797 storage_type original, modified;
811 : "=&r" (original), // %0
812 "=&r" (modified) // %1
813 : "m" (storage), // %2
815 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
821 static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
823 storage_type original, modified;
837 : "=&r" (original), // %0
838 "=&r" (modified) // %1
839 : "m" (storage), // %2
841 : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC
847 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
849 return !!exchange(storage, (storage_type)1, order);
852 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
854 store(storage, 0, order);
859 BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
861 if (order != memory_order_relaxed)
862 __asm__ __volatile__ ("mb" ::: "memory");
865 BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
867 if (order != memory_order_relaxed)
868 __asm__ __volatile__ ("" ::: "memory");
871 } // namespace detail
872 } // namespace atomics
875 #endif // BOOST_ATOMIC_DETAIL_OPS_GCC_ALPHA_HPP_INCLUDED_