#ifndef BOOST_ATOMIC_DETAIL_GCC_ARMV6PLUS_HPP
#define BOOST_ATOMIC_DETAIL_GCC_ARMV6PLUS_HPP
#include <boost/cstdint.hpp>
#include <boost/atomic/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
namespace atomics {
namespace detail {
#if defined(__thumb__) && !defined(__thumb2__)
#define BOOST_ATOMIC_ARM_ASM_START(TMPREG) "adr " #TMPREG ", 1f\n" "bx " #TMPREG "\n" ".arm\n" ".align 4\n" "1: "
#define BOOST_ATOMIC_ARM_ASM_END(TMPREG) "adr " #TMPREG ", 1f + 1\n" "bx " #TMPREG "\n" ".thumb\n" ".align 2\n" "1: "
#else
#define BOOST_ATOMIC_ARM_ASM_START(TMPREG)
#define BOOST_ATOMIC_ARM_ASM_END(TMPREG)
#endif
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7S__)
#define BOOST_ATOMIC_ARM_DMB "dmb\n"
#else
#define BOOST_ATOMIC_ARM_DMB "mcr\tp15, 0, r0, c7, c10, 5\n"
#endif
inline void
arm_barrier(void) BOOST_NOEXCEPT
{
int brtmp;
__asm__ __volatile__
(
BOOST_ATOMIC_ARM_ASM_START(%0)
BOOST_ATOMIC_ARM_DMB
BOOST_ATOMIC_ARM_ASM_END(%0)
: "=&l" (brtmp) :: "memory"
);
}
inline void
platform_fence_before(memory_order order) BOOST_NOEXCEPT
{
switch(order)
{
case memory_order_release:
case memory_order_acq_rel:
case memory_order_seq_cst:
arm_barrier();
case memory_order_consume:
default:;
}
}
inline void
platform_fence_after(memory_order order) BOOST_NOEXCEPT
{
switch(order)
{
case memory_order_acquire:
case memory_order_acq_rel:
case memory_order_seq_cst:
arm_barrier();
default:;
}
}
inline void
platform_fence_before_store(memory_order order) BOOST_NOEXCEPT
{
platform_fence_before(order);
}
inline void
platform_fence_after_store(memory_order order) BOOST_NOEXCEPT
{
if (order == memory_order_seq_cst)
arm_barrier();
}
inline void
platform_fence_after_load(memory_order order) BOOST_NOEXCEPT
{
platform_fence_after(order);
}
template<typename T>
inline bool
platform_cmpxchg32(T & expected, T desired, volatile T * ptr) BOOST_NOEXCEPT
{
int success;
int tmp;
__asm__ __volatile__
(
BOOST_ATOMIC_ARM_ASM_START(%2)
"mov %1, #0\n" "ldrex %0, %3\n" "teq %0, %4\n" "ittt eq\n"
"strexeq %2, %5, %3\n" "teqeq %2, #0\n" "moveq %1, #1\n" BOOST_ATOMIC_ARM_ASM_END(%2)
: "=&r" (expected), "=&r" (success), "=&l" (tmp), "+Q" (*ptr) : "r" (expected), "r" (desired) : "cc"
);
return success;
}
}
}
#define BOOST_ATOMIC_THREAD_FENCE 2
inline void
atomic_thread_fence(memory_order order)
{
switch(order)
{
case memory_order_acquire:
case memory_order_release:
case memory_order_acq_rel:
case memory_order_seq_cst:
atomics::detail::arm_barrier();
default:;
}
}
#define BOOST_ATOMIC_SIGNAL_FENCE 2
inline void
atomic_signal_fence(memory_order)
{
__asm__ __volatile__ ("" ::: "memory");
}
class atomic_flag
{
private:
uint32_t v_;
public:
BOOST_CONSTEXPR atomic_flag(void) BOOST_NOEXCEPT : v_(0) {}
void
clear(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
atomics::detail::platform_fence_before_store(order);
const_cast<volatile uint32_t &>(v_) = 0;
atomics::detail::platform_fence_after_store(order);
}
bool
test_and_set(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
{
atomics::detail::platform_fence_before(order);
uint32_t expected = v_;
do {
if (expected == 1)
break;
} while (!atomics::detail::platform_cmpxchg32(expected, (uint32_t)1, &v_));
atomics::detail::platform_fence_after(order);
return expected;
}
BOOST_DELETED_FUNCTION(atomic_flag(const atomic_flag &))
BOOST_DELETED_FUNCTION(atomic_flag& operator=(const atomic_flag &))
};
#define BOOST_ATOMIC_FLAG_LOCK_FREE 2
}
#undef BOOST_ATOMIC_ARM_ASM_START
#undef BOOST_ATOMIC_ARM_ASM_END
#include <boost/atomic/detail/base.hpp>
#if !defined(BOOST_ATOMIC_FORCE_FALLBACK)
#define BOOST_ATOMIC_CHAR_LOCK_FREE 2
#define BOOST_ATOMIC_CHAR16_T_LOCK_FREE 2
#define BOOST_ATOMIC_CHAR32_T_LOCK_FREE 2
#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE 2
#define BOOST_ATOMIC_SHORT_LOCK_FREE 2
#define BOOST_ATOMIC_INT_LOCK_FREE 2
#define BOOST_ATOMIC_LONG_LOCK_FREE 2
#define BOOST_ATOMIC_LLONG_LOCK_FREE 0
#define BOOST_ATOMIC_POINTER_LOCK_FREE 2
#define BOOST_ATOMIC_BOOL_LOCK_FREE 2
#include <boost/atomic/detail/cas32weak.hpp>
#endif
#endif