00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef _OASYS_ATOMIC_ARM_H_
00040 #define _OASYS_ATOMIC_ARM_H_
00041
00042 #include "../compat/inttypes.h"
00043
00044 namespace oasys {
00045
00053 struct atomic_t {
00054 atomic_t(u_int32_t v = 0)
00055 : value(v), lock(0) {}
00056
00057 volatile u_int32_t value;
00058 volatile u_int32_t lock;
00059 };
00060
00064 static inline void
00065 atomic_lock(volatile atomic_t* v)
00066 {
00067 u_int32_t tmp;
00068
00069 __asm__ __volatile__("@ atomic_lock\n"
00070 "1: mov %0, #1\n"
00071 " swp %0, %0, [%1]\n"
00072 " teq %0, #0\n"
00073 " bne 1b"
00074 : "=&r" (tmp)
00075 : "r" (&v->lock)
00076 : "cc", "memory");
00077 }
00078
00082 static inline bool
00083 atomic_try_lock(volatile atomic_t* v)
00084 {
00085 u_int32_t tmp;
00086
00087 __asm__ __volatile__("@ atomic_lock\n"
00088 "1: mov %0, #1\n"
00089 " swp %0, %0, [%1]\n"
00090 : "=&r" (tmp)
00091 : "r" (&v->lock)
00092 : "cc", "memory");
00093
00094 return (tmp == 0);
00095 }
00096
00097 static inline void
00098 atomic_unlock(volatile atomic_t* v)
00099 {
00100 v->lock = 0;
00101 }
00102
00110 static inline u_int32_t
00111 atomic_add_ret(volatile atomic_t* v, u_int32_t i)
00112 {
00113 u_int32_t ret;
00114
00115 atomic_lock(v);
00116 v->value += i;
00117 ret = v->value;
00118 atomic_unlock(v);
00119
00120 return ret;
00121 }
00122
00129 static inline u_int32_t
00130 atomic_sub_ret(volatile atomic_t* v, u_int32_t i)
00131 {
00132 u_int32_t ret;
00133
00134 atomic_lock(v);
00135 v->value -= i;
00136 ret = v->value;
00137 atomic_unlock(v);
00138
00139 return ret;
00140 }
00141
00144
00145 static inline void
00146 atomic_add(volatile atomic_t* v, u_int32_t i)
00147 {
00148 atomic_add_ret(v, i);
00149 }
00150
00151 static inline void
00152 atomic_sub(volatile atomic_t* v, u_int32_t i)
00153 {
00154 atomic_sub_ret(v, i);
00155 }
00156
00157 static inline void
00158 atomic_incr(volatile atomic_t* v)
00159 {
00160 atomic_add(v, 1);
00161 }
00162
00163 static inline void
00164 atomic_decr(volatile atomic_t* v)
00165 {
00166 atomic_sub(v, 1);
00167 }
00168
00169 static inline u_int32_t
00170 atomic_incr_ret(volatile atomic_t* v)
00171 {
00172 return atomic_add_ret(v, 1);
00173 }
00174
00175 static inline u_int32_t
00176 atomic_decr_ret(volatile atomic_t* v)
00177 {
00178 return atomic_sub_ret(v, 1);
00179 }
00180
00181 static inline bool
00182 atomic_decr_test(volatile atomic_t* v)
00183 {
00184 return (atomic_sub_ret(v, 1) == 0);
00185 }
00186
00188
00199 static inline u_int32_t
00200 atomic_cmpxchg32(volatile atomic_t* v, u_int32_t o, u_int32_t n)
00201 {
00202 u_int32_t ret;
00203
00204 atomic_lock(v);
00205 ret = v->value;
00206 if (v->value == o) {
00207 v->value = n;
00208 }
00209 atomic_unlock(v);
00210
00211 return ret;
00212 }
00213
00214 }
00215
00216 #endif