00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef _OASYS_ATOMIC_ARM_H_
00019 #define _OASYS_ATOMIC_ARM_H_
00020
00021 #include "../compat/inttypes.h"
00022
00023 namespace oasys {
00024
00032 struct atomic_t {
00033 atomic_t(u_int32_t v = 0)
00034 : value(v), lock(0) {}
00035
00036 volatile u_int32_t value;
00037 volatile u_int32_t lock;
00038 };
00039
00043 static inline void
00044 atomic_lock(volatile atomic_t* v)
00045 {
00046 u_int32_t tmp;
00047
00048 __asm__ __volatile__("@ atomic_lock\n"
00049 "1: mov %0, #1\n"
00050 " swp %0, %0, [%1]\n"
00051 " teq %0, #0\n"
00052 " bne 1b"
00053 : "=&r" (tmp)
00054 : "r" (&v->lock)
00055 : "cc", "memory");
00056 }
00057
00061 static inline bool
00062 atomic_try_lock(volatile atomic_t* v)
00063 {
00064 u_int32_t tmp;
00065
00066 __asm__ __volatile__("@ atomic_lock\n"
00067 "1: mov %0, #1\n"
00068 " swp %0, %0, [%1]\n"
00069 : "=&r" (tmp)
00070 : "r" (&v->lock)
00071 : "cc", "memory");
00072
00073 return (tmp == 0);
00074 }
00075
00076 static inline void
00077 atomic_unlock(volatile atomic_t* v)
00078 {
00079 v->lock = 0;
00080 }
00081
00089 static inline u_int32_t
00090 atomic_add_ret(volatile atomic_t* v, u_int32_t i)
00091 {
00092 u_int32_t ret;
00093
00094 atomic_lock(v);
00095 v->value += i;
00096 ret = v->value;
00097 atomic_unlock(v);
00098
00099 return ret;
00100 }
00101
00108 static inline u_int32_t
00109 atomic_sub_ret(volatile atomic_t* v, u_int32_t i)
00110 {
00111 u_int32_t ret;
00112
00113 atomic_lock(v);
00114 v->value -= i;
00115 ret = v->value;
00116 atomic_unlock(v);
00117
00118 return ret;
00119 }
00120
00123
00124 static inline void
00125 atomic_add(volatile atomic_t* v, u_int32_t i)
00126 {
00127 atomic_add_ret(v, i);
00128 }
00129
00130 static inline void
00131 atomic_sub(volatile atomic_t* v, u_int32_t i)
00132 {
00133 atomic_sub_ret(v, i);
00134 }
00135
00136 static inline void
00137 atomic_incr(volatile atomic_t* v)
00138 {
00139 atomic_add(v, 1);
00140 }
00141
00142 static inline void
00143 atomic_decr(volatile atomic_t* v)
00144 {
00145 atomic_sub(v, 1);
00146 }
00147
00148 static inline u_int32_t
00149 atomic_incr_ret(volatile atomic_t* v)
00150 {
00151 return atomic_add_ret(v, 1);
00152 }
00153
00154 static inline u_int32_t
00155 atomic_decr_ret(volatile atomic_t* v)
00156 {
00157 return atomic_sub_ret(v, 1);
00158 }
00159
00160 static inline bool
00161 atomic_decr_test(volatile atomic_t* v)
00162 {
00163 return (atomic_sub_ret(v, 1) == 0);
00164 }
00165
00167
00178 static inline u_int32_t
00179 atomic_cmpxchg32(volatile atomic_t* v, u_int32_t o, u_int32_t n)
00180 {
00181 u_int32_t ret;
00182
00183 atomic_lock(v);
00184 ret = v->value;
00185 if (v->value == o) {
00186 v->value = n;
00187 }
00188 atomic_unlock(v);
00189
00190 return ret;
00191 }
00192
00193 }
00194
00195 #endif