00001
00004
00005
00006
00007
00008 #ifndef RUTZ_ATOMIC_IX86_H_UTC20050728203342_DEFINED
00009 #define RUTZ_ATOMIC_IX86_H_UTC20050728203342_DEFINED
00010
00011 namespace rutz
00012 {
00013
00014
00015
00016
00017
00018
00019 #define LOCK "lock ; "
00020
00021
00022
00023
00024
00025
00026 typedef struct { volatile int counter; } ix86_atomic_int_t;
00027
00035 #define ix86_atomic_read(v) ((v)->counter)
00036
00045 #define ix86_atomic_set(v,i) (((v)->counter) = (i))
00046
00054 static __inline__ void ix86_atomic_add(int i, ix86_atomic_int_t *v)
00055 {
00056 __asm__ __volatile__(
00057 LOCK "addl %1,%0"
00058 :"=m" (v->counter)
00059 :"ir" (i), "m" (v->counter));
00060 }
00061
00069 static __inline__ void ix86_atomic_sub(int i, ix86_atomic_int_t *v)
00070 {
00071 __asm__ __volatile__(
00072 LOCK "subl %1,%0"
00073 :"=m" (v->counter)
00074 :"ir" (i), "m" (v->counter));
00075 }
00076
00086 static __inline__ int ix86_atomic_sub_and_test(int i, ix86_atomic_int_t *v)
00087 {
00088 unsigned char c;
00089
00090 __asm__ __volatile__(
00091 LOCK "subl %2,%0; sete %1"
00092 :"=m" (v->counter), "=qm" (c)
00093 :"ir" (i), "m" (v->counter) : "memory");
00094 return c;
00095 }
00096
00104 static __inline__ void ix86_atomic_inc(ix86_atomic_int_t *v)
00105 {
00106 __asm__ __volatile__(
00107 LOCK "incl %0"
00108 :"=m" (v->counter)
00109 :"m" (v->counter));
00110 }
00111
00118 static __inline__ void ix86_atomic_dec(ix86_atomic_int_t *v)
00119 {
00120 __asm__ __volatile__(
00121 LOCK "decl %0"
00122 :"=m" (v->counter)
00123 :"m" (v->counter));
00124 }
00125
00135 static __inline__ int ix86_atomic_dec_and_test(ix86_atomic_int_t *v)
00136 {
00137 unsigned char c;
00138
00139 __asm__ __volatile__(
00140 LOCK "decl %0; sete %1"
00141 :"=m" (v->counter), "=qm" (c)
00142 :"m" (v->counter) : "memory");
00143 return c != 0;
00144 }
00145
00154 static __inline__ int ix86_atomic_inc_and_test(ix86_atomic_int_t *v)
00155 {
00156 unsigned char c;
00157
00158 __asm__ __volatile__(
00159 LOCK "incl %0; sete %1"
00160 :"=m" (v->counter), "=qm" (c)
00161 :"m" (v->counter) : "memory");
00162 return c != 0;
00163 }
00164
00172 static __inline__ int ix86_atomic_add_return(int i, ix86_atomic_int_t *v)
00173 {
00174
00175 int __i = i;
00176 __asm__ __volatile__(
00177 LOCK "xaddl %0, %1;"
00178 :"=r"(i)
00179 :"m"(v->counter), "0"(i));
00180 return i + __i;
00181 }
00182
00183 static __inline__ int ix86_atomic_sub_return(int i, ix86_atomic_int_t *v)
00184 {
00185 return ix86_atomic_add_return(-i,v);
00186 }
00187
00189 class ix86_atomic_int
00190 {
00191 private:
00192 ix86_atomic_int_t x;
00193
00194 ix86_atomic_int(const ix86_atomic_int&);
00195 ix86_atomic_int& operator=(const ix86_atomic_int&);
00196
00197 public:
00199 ix86_atomic_int() { this->atomic_set(0); }
00200
00202 static int max_value() { return ((1 << 24) - 1); }
00203
00205 int atomic_get() const
00206 { return ix86_atomic_read(&x); }
00207
00209 void atomic_set(int v)
00210 { ix86_atomic_set(&x, v); }
00211
00213 void atomic_add(int i)
00214 { ix86_atomic_add(i, &x); }
00215
00217 void atomic_sub(int i)
00218 { ix86_atomic_sub(i, &x); }
00219
00221 bool atomic_sub_test_zero(int i)
00222 { return bool(ix86_atomic_sub_and_test(i, &x)); }
00223
00225 void atomic_incr()
00226 { ix86_atomic_inc(&x); }
00227
00229 void atomic_decr()
00230 { ix86_atomic_dec(&x); }
00231
00233 bool atomic_decr_test_zero()
00234 { return bool(ix86_atomic_dec_and_test(&x)); }
00235
00237 bool atomic_incr_test_zero()
00238 { return bool(ix86_atomic_inc_and_test(&x)); }
00239
00241 int atomic_add_return(int i)
00242 { return ix86_atomic_add_return(i, &x); }
00243
00245 int atomic_sub_return(int i)
00246 { return ix86_atomic_sub_return(i, &x); }
00247
00249 int atomic_incr_return()
00250 { return ix86_atomic_add_return(1, &x); }
00251
00253 int atomic_decr_return()
00254 { return ix86_atomic_add_return(-1, &x); }
00255 };
00256
00257 }
00258
00259 #endif // !RUTZ_ATOMIC_IX86_H_UTC20050728203342DEFINED