atomic_ix86.h

Go to the documentation of this file.
00001 
00004 // Primary maintainer for this file: Rob Peters <rjpeters@klab.caltech.edu>
00005 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/rutz/atomic_ix86.h $
00006 // $Id: atomic_ix86.h 10031 2006-10-05 17:55:50Z rjpeters $
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  * Atomic operations that C can't guarantee us.  Useful for
00016  * resource counting etc..
00017  */
00018 
00019 #define LOCK "lock ; "
00020 
00021 /*
00022  * Make sure gcc doesn't try to be clever and move things around
00023  * on us. We need to use _exactly_ the address the user gave us,
00024  * not some alias that contains the same information.
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         /* Modern 486+ processor */
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&); // not implemented
00195   ix86_atomic_int& operator=(const ix86_atomic_int&); // not implemented
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 } // end namespace rutz
00258 
00259 #endif // !RUTZ_ATOMIC_IX86_H_UTC20050728203342DEFINED

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:40 2008 by Doxygen version 1.5.5.