Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:33:53

0001 /*
0002  * Distributed under the Boost Software License, Version 1.0.
0003  * (See accompanying file LICENSE_1_0.txt or copy at
0004  * http://www.boost.org/LICENSE_1_0.txt)
0005  *
0006  * Copyright (c) 2009, 2011 Helge Bahmann
0007  * Copyright (c) 2009 Phil Endecott
0008  * Copyright (c) 2013 Tim Blechmann
0009  * Linux-specific code by Phil Endecott
0010  * Copyright (c) 2014 Andrey Semashev
0011  */
0012 /*!
0013  * \file   atomic/detail/core_ops_linux_arm.hpp
0014  *
0015  * This header contains implementation of the \c core_operations template.
0016  */
0017 
0018 #ifndef BOOST_ATOMIC_DETAIL_CORE_OPS_LINUX_ARM_HPP_INCLUDED_
0019 #define BOOST_ATOMIC_DETAIL_CORE_OPS_LINUX_ARM_HPP_INCLUDED_
0020 
0021 #include <cstddef>
0022 #include <boost/memory_order.hpp>
0023 #include <boost/atomic/detail/config.hpp>
0024 #include <boost/atomic/detail/storage_traits.hpp>
0025 #include <boost/atomic/detail/core_operations_fwd.hpp>
0026 #include <boost/atomic/detail/core_ops_cas_based.hpp>
0027 #include <boost/atomic/detail/cas_based_exchange.hpp>
0028 #include <boost/atomic/detail/extending_cas_based_arithmetic.hpp>
0029 #include <boost/atomic/detail/fence_operations.hpp>
0030 #include <boost/atomic/detail/header.hpp>
0031 
0032 #ifdef BOOST_HAS_PRAGMA_ONCE
0033 #pragma once
0034 #endif
0035 
0036 namespace boost {
0037 namespace atomics {
0038 namespace detail {
0039 
0040 // Different ARM processors have different atomic instructions.  In particular,
0041 // architecture versions before v6 (which are still in widespread use, e.g. the
0042 // Intel/Marvell XScale chips like the one in the NSLU2) have only atomic swap.
0043 // On Linux the kernel provides some support that lets us abstract away from
0044 // these differences: it provides emulated CAS and barrier functions at special
0045 // addresses that are guaranteed not to be interrupted by the kernel.  Using
0046 // this facility is slightly slower than inline assembler would be, but much
0047 // faster than a system call.
0048 //
0049 // https://lwn.net/Articles/314561/
0050 //
0051 // While this emulated CAS is "strong" in the sense that it does not fail
0052 // "spuriously" (i.e.: it never fails to perform the exchange when the value
0053 // found equals the value expected), it does not return the found value on
0054 // failure. To satisfy the atomic API, compare_exchange_{weak|strong} must
0055 // return the found value on failure, and we have to manually load this value
0056 // after the emulated CAS reports failure. This in turn introduces a race
0057 // between the CAS failing (due to the "wrong" value being found) and subsequently
0058 // loading (which might turn up the "right" value). From an application's
0059 // point of view this looks like "spurious failure", and therefore the
0060 // emulated CAS is only good enough to provide compare_exchange_weak
0061 // semantics.
0062 
0063 struct linux_arm_cas_base
0064 {
0065     static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = true;
0066     static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true;
0067 
0068     static BOOST_FORCEINLINE void fence_before_store(memory_order order) BOOST_NOEXCEPT
0069     {
0070         if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u)
0071             fence_operations::hardware_full_fence();
0072     }
0073 
0074     static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT
0075     {
0076         if (order == memory_order_seq_cst)
0077             fence_operations::hardware_full_fence();
0078     }
0079 
0080     static BOOST_FORCEINLINE void fence_after_load(memory_order order) BOOST_NOEXCEPT
0081     {
0082         if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u)
0083             fence_operations::hardware_full_fence();
0084     }
0085 };
0086 
0087 template< bool Signed, bool Interprocess >
0088 struct linux_arm_cas :
0089     public linux_arm_cas_base
0090 {
0091     typedef typename storage_traits< 4u >::type storage_type;
0092 
0093     static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u;
0094     static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 4u;
0095     static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed;
0096     static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess;
0097 
0098     static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
0099     {
0100         fence_before_store(order);
0101         storage = v;
0102         fence_after_store(order);
0103     }
0104 
0105     static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
0106     {
0107         storage_type v = storage;
0108         fence_after_load(order);
0109         return v;
0110     }
0111 
0112     static BOOST_FORCEINLINE bool compare_exchange_strong(
0113         storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
0114     {
0115         while (true)
0116         {
0117             storage_type tmp = expected;
0118             if (compare_exchange_weak(storage, tmp, desired, success_order, failure_order))
0119                 return true;
0120             if (tmp != expected)
0121             {
0122                 expected = tmp;
0123                 return false;
0124             }
0125         }
0126     }
0127 
0128     static BOOST_FORCEINLINE bool compare_exchange_weak(
0129         storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
0130     {
0131         typedef storage_type (*kernel_cmpxchg32_t)(storage_type oldval, storage_type newval, volatile storage_type* ptr);
0132 
0133         if (((kernel_cmpxchg32_t)0xffff0fc0)(expected, desired, &storage) == 0)
0134         {
0135             return true;
0136         }
0137         else
0138         {
0139             expected = storage;
0140             return false;
0141         }
0142     }
0143 };
0144 
0145 template< bool Signed, bool Interprocess >
0146 struct core_operations< 1u, Signed, Interprocess > :
0147     public extending_cas_based_arithmetic< core_operations_cas_based< cas_based_exchange< linux_arm_cas< Signed, Interprocess > > >, 1u, Signed >
0148 {
0149 };
0150 
0151 template< bool Signed, bool Interprocess >
0152 struct core_operations< 2u, Signed, Interprocess > :
0153     public extending_cas_based_arithmetic< core_operations_cas_based< cas_based_exchange< linux_arm_cas< Signed, Interprocess > > >, 2u, Signed >
0154 {
0155 };
0156 
0157 template< bool Signed, bool Interprocess >
0158 struct core_operations< 4u, Signed, Interprocess > :
0159     public core_operations_cas_based< cas_based_exchange< linux_arm_cas< Signed, Interprocess > > >
0160 {
0161 };
0162 
0163 } // namespace detail
0164 } // namespace atomics
0165 } // namespace boost
0166 
0167 #include <boost/atomic/detail/footer.hpp>
0168 
0169 #endif // BOOST_ATOMIC_DETAIL_CORE_OPS_LINUX_ARM_HPP_INCLUDED_