00001 #ifndef BOOST_ATOMIC_DETAIL_ATOMIC_GCC_ARMV6P_HPP
00002 #define BOOST_ATOMIC_DETAIL_ATOMIC_GCC_ARMV6P_HPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "../memory_order2.hpp"
00014 #include "base.hpp"
00015 #include "builder.hpp"
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 namespace boost_atomic {
00043 namespace detail {
00044 namespace atomic {
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 #if defined(__thumb__) && !defined(__ARM_ARCH_7A__)
00068
00069 #define BOOST_ATOMIC_ARM_ASM_START(TMPREG) "adr " #TMPREG ", 1f\n" "bx " #TMPREG "\n" ".arm\n" ".align 4\n" "1: "
00070 #define BOOST_ATOMIC_ARM_ASM_END(TMPREG) "adr " #TMPREG ", 1f + 1\n" "bx " #TMPREG "\n" ".thumb\n" ".align 2\n" "1: "
00071
00072 #else
00073
00074 #define BOOST_ATOMIC_ARM_ASM_START(TMPREG)
00075 #define BOOST_ATOMIC_ARM_ASM_END(TMPREG)
00076 #endif
00077
00078
00079 #if defined(__ARM_ARCH_7A__)
00080
00081 #define BOOST_ATOMIC_ARM_DMB "dmb\n"
00082 #else
00083 #define BOOST_ATOMIC_ARM_DMB "mcr\tp15, 0, r0, c7, c10, 5\n"
00084 #endif
00085
00086
00087
00088
00089
00090 static inline void fence_before(memory_order2 order)
00091 {
00092
00093 switch(order) {
00094 case memory_order2_release:
00095 case memory_order2_acq_rel:
00096 case memory_order2_seq_cst:
00097 int brtmp;
00098 __asm__ __volatile__ (
00099 BOOST_ATOMIC_ARM_ASM_START(%0)
00100 BOOST_ATOMIC_ARM_DMB
00101 BOOST_ATOMIC_ARM_ASM_END(%0)
00102 : "=&l" (brtmp) :: "memory"
00103 );
00104 default:;
00105 }
00106 }
00107
00108 static inline void fence_after(memory_order2 order)
00109 {
00110
00111 switch(order) {
00112 case memory_order2_acquire:
00113 case memory_order2_acq_rel:
00114 case memory_order2_seq_cst:
00115 int brtmp;
00116 __asm__ __volatile__ (
00117 BOOST_ATOMIC_ARM_ASM_START(%0)
00118 BOOST_ATOMIC_ARM_DMB
00119 BOOST_ATOMIC_ARM_ASM_END(%0)
00120 : "=&l" (brtmp) :: "memory"
00121 );
00122 case memory_order2_consume:
00123 __asm__ __volatile__ ("" ::: "memory");
00124 default:;
00125 }
00126 }
00127
00128 #undef BOOST_ATOMIC_ARM_DMB
00129
00130
00131 template<typename T>
00132 class atomic_arm_4 {
00133 public:
00134 typedef T integral_type;
00135 explicit atomic_arm_4(T v) : i(v) {}
00136 atomic_arm_4() {}
00137 T load(memory_order2 order=memory_order2_seq_cst) const volatile
00138 {
00139 T v=const_cast<volatile const T &>(i);
00140 fence_after(order);
00141 return v;
00142 }
00143 void store(T v, memory_order2 order=memory_order2_seq_cst) volatile
00144 {
00145 fence_before(order);
00146 const_cast<volatile T &>(i)=v;
00147 }
00148 bool compare_exchange_weak(
00149 T &expected,
00150 T desired,
00151 memory_order2 success_order,
00152 memory_order2 failure_order) volatile
00153 {
00154 fence_before(success_order);
00155 int success;
00156 int tmp;
00157 __asm__ __volatile__(
00158 BOOST_ATOMIC_ARM_ASM_START(%2)
00159 "mov %1, #0\n"
00160 "ldrex %0, [%3]\n"
00161 "teq %0, %4\n"
00162 "ittt eq\n"
00163 "strexeq %2, %5, [%3]\n"
00164 "teqeq %2, #0\n"
00165 "moveq %1, #1\n"
00166 BOOST_ATOMIC_ARM_ASM_END(%2)
00167 : "=&r" (expected),
00168 "=&r" (success),
00169 "=&l" (tmp)
00170 : "r" (&i),
00171 "r" (expected),
00172 "r" ((int)desired)
00173 : "cc"
00174 );
00175 if (success) fence_after(success_order);
00176 else fence_after(failure_order);
00177 return success;
00178 }
00179
00180 bool is_lock_free(void) const volatile {return true;}
00181 protected:
00182 inline T fetch_add_var(T c, memory_order2 order) volatile
00183 {
00184 fence_before(order);
00185 T original, tmp;
00186 int tmp2;
00187 __asm__ __volatile__(
00188 BOOST_ATOMIC_ARM_ASM_START(%2)
00189 "1: ldrex %0, [%3]\n"
00190 "add %1, %0, %4\n"
00191 "strex %2, %1, [%3]\n"
00192 "teq %2, #0\n"
00193 "it ne\n"
00194 "bne 1b\n"
00195 BOOST_ATOMIC_ARM_ASM_END(%2)
00196 : "=&r" (original),
00197 "=&r" (tmp),
00198 "=&l" (tmp2)
00199 : "r" (&i),
00200 "r" (c)
00201 : "cc"
00202 );
00203 fence_after(order);
00204 return original;
00205 }
00206 inline T fetch_inc(memory_order2 order) volatile
00207 {
00208 fence_before(order);
00209 T original, tmp;
00210 int tmp2;
00211 __asm__ __volatile__(
00212 BOOST_ATOMIC_ARM_ASM_START(%2)
00213 "1: ldrex %0, [%3]\n"
00214 "add %1, %0, #1\n"
00215 "strex %2, %1, [%3]\n"
00216 "teq %2, #0\n"
00217 "it ne\n"
00218 "bne 1b\n"
00219 BOOST_ATOMIC_ARM_ASM_END(%2)
00220 : "=&r" (original),
00221 "=&r" (tmp),
00222 "=&l" (tmp2)
00223 : "r" (&i)
00224 : "cc"
00225 );
00226 fence_after(order);
00227 return original;
00228 }
00229 inline T fetch_dec(memory_order2 order) volatile
00230 {
00231 fence_before(order);
00232 T original, tmp;
00233 int tmp2;
00234 __asm__ __volatile__(
00235 BOOST_ATOMIC_ARM_ASM_START(%2)
00236 "1: ldrex %0, [%3]\n"
00237 "sub %1, %0, #1\n"
00238 "strex %2, %1, [%3]\n"
00239 "teq %2, #0\n"
00240 "it ne\n"
00241 "bne 1b\n"
00242 BOOST_ATOMIC_ARM_ASM_END(%2)
00243 : "=&r" (original),
00244 "=&r" (tmp),
00245 "=&l" (tmp2)
00246 : "r" (&i)
00247 : "cc"
00248 );
00249 fence_after(order);
00250 return original;
00251 }
00252 private:
00253 T i;
00254 };
00255
00256
00257
00258
00259
00260
00261 template<typename T>
00262 class platform_atomic_integral<T, 4> : public build_atomic_from_typical<build_exchange<atomic_arm_4<T> > > {
00263 public:
00264 typedef build_atomic_from_typical<build_exchange<atomic_arm_4<T> > > super;
00265 explicit platform_atomic_integral(T v) : super(v) {}
00266 platform_atomic_integral(void) {}
00267 };
00268
00269 template<typename T>
00270 class platform_atomic_integral<T, 1>: public build_atomic_from_larger_type<atomic_arm_4<uint32_t>, T> {
00271 public:
00272 typedef build_atomic_from_larger_type<atomic_arm_4<uint32_t>, T> super;
00273
00274 explicit platform_atomic_integral(T v) : super(v) {}
00275 platform_atomic_integral(void) {}
00276 };
00277
00278 template<typename T>
00279 class platform_atomic_integral<T, 2>: public build_atomic_from_larger_type<atomic_arm_4<uint32_t>, T> {
00280 public:
00281 typedef build_atomic_from_larger_type<atomic_arm_4<uint32_t>, T> super;
00282
00283 explicit platform_atomic_integral(T v) : super(v) {}
00284 platform_atomic_integral(void) {}
00285 };
00286
00287
00288
00289 typedef build_exchange<atomic_arm_4<void *> > platform_atomic_address;
00290
00291 }
00292 }
00293 }
00294
00295 #undef BOOST_ATOMIC_ARM_ASM_START
00296 #undef BOOST_ATOMIC_ARM_ASM_END
00297
00298
00299 #endif