00001
00002
00003 #ifndef atomic_h
00004 #define atomic_h
00005
00006 #include "types.h"
00007
00008
00009
00010
00011
00012
00013 extern "C" void cas_error_type_with_bad_size_used(void);
00014
00015 #define MACRO_CAS_ASSERT(rs,cs) \
00016 if( (rs) != (cs) ) \
00017 cas_error_type_with_bad_size_used()
00018
00019 template< typename Type > inline bool cas(Type *ptr, Type oldval, Type newval);
00020
00021 template< typename Type > inline bool cas2(Type *ptr, Type *oldval, Type *newval);
00022
00023 template <typename T> inline T atomic_change(T *ptr, T mask, T bits);
00024
00025 inline void atomic_add(Mword *l, Mword value);
00026
00027 inline void atomic_and(Mword *l, Mword mask);
00028
00029 inline void atomic_or(Mword *l, Mword bits);
00030
00031
00032
00033
00034
00035 inline bool cas_unsafe(Mword *ptr, Mword oldval, Mword newval);
00036
00037 inline bool cas2_unsafe(Mword *ptr, Mword *oldval, Mword *newval);
00038
00039 inline bool tas(Mword *l);
00040
00041
00042
00043
00044
00045
00046
00047
00048 template< typename Type > inline bool
00049 cas(Type *ptr, Type oldval, Type newval)
00050 {
00051 MACRO_CAS_ASSERT(sizeof(Type),sizeof(Mword));
00052 return cas_unsafe (reinterpret_cast<Mword*>(ptr),
00053 (Mword)oldval, (Mword)newval);
00054 }
00055
00056
00057
00058 template< typename Type > inline bool
00059 cas2(Type *ptr, Type *oldval, Type *newval)
00060 {
00061 MACRO_CAS_ASSERT(sizeof(Type),(sizeof(Mword)*2));
00062 return cas2_unsafe (reinterpret_cast<Mword*>(ptr),
00063 reinterpret_cast<Mword*>(oldval),
00064 reinterpret_cast<Mword*>(newval));
00065 }
00066
00067
00068
00069 template <typename T> inline T
00070 atomic_change(T *ptr, T mask, T bits)
00071 {
00072 T old;
00073 do
00074 {
00075 old = *ptr;
00076 }
00077 while (! cas (ptr, old, (old & mask) | bits));
00078 return old;
00079 }
00080
00081
00082
00083 inline void
00084 atomic_add(Mword *l, Mword value)
00085 {
00086 asm volatile ("addl %1, %2" : "=m"(*l) : "ir"(value), "m"(*l));
00087 }
00088
00089
00090
00091 inline void
00092 atomic_and(Mword *l, Mword mask)
00093 {
00094 asm volatile ("andl %1, %2" : "=m"(*l) : "ir"(mask), "m"(*l));
00095 }
00096
00097
00098
00099 inline void
00100 atomic_or(Mword *l, Mword bits)
00101 {
00102 asm volatile ("orl %1, %2" : "=m"(*l) : "ir"(bits), "m"(*l));
00103 }
00104
00105
00106
00107
00108
00109
00110
00111 inline bool
00112 cas_unsafe(Mword *ptr, Mword oldval, Mword newval)
00113 {
00114 Mword tmp;
00115
00116 asm volatile
00117 ("cmpxchgl %1, %2"
00118 : "=a" (tmp)
00119 : "r" (newval), "m" (*ptr), "a" (oldval)
00120 : "memory");
00121
00122 return tmp == oldval;
00123 }
00124
00125
00126
00127 inline bool
00128 cas2_unsafe(Mword *ptr, Mword *oldval, Mword *newval)
00129 {
00130 char ret;
00131 asm volatile
00132 ("cmpxchg8b %3 ; sete %%cl"
00133 : "=c" (ret),
00134 "=a" (* oldval),
00135 "=d" (*(oldval+1))
00136 : "m" (*ptr) ,
00137 "a" (* oldval), "d" (*(oldval+1)),
00138 "b" (* newval), "c" (*(newval+1))
00139 : "memory");
00140
00141 return ret;
00142 }
00143
00144
00145
00146 inline bool
00147 tas(Mword *l)
00148 {
00149 Mword tmp;
00150 asm volatile ("xchg %0, %1" : "=r"(tmp) : "m"(*l), "0"(1) : "memory");
00151 return tmp;
00152 }
00153
00154 #endif // atomic_h