Explorar o código

- added cmpxchg

Andrei Pelinescu-Onciul %!s(int64=18) %!d(string=hai) anos
pai
achega
494739a6b5
Modificáronse 1 ficheiros con 24 adicións e 0 borrados
  1. 24 0
      atomic/atomic_x86.h

+ 24 - 0
atomic/atomic_x86.h

@@ -42,6 +42,7 @@
  * History:
  * History:
  * --------
  * --------
  *  2006-03-08  created by andrei
  *  2006-03-08  created by andrei
+ *  2007-05-07  added cmpxchg (andrei)
  */
  */
 
 
 #ifndef _atomic_x86_h
 #ifndef _atomic_x86_h
@@ -165,6 +166,24 @@
 		return ret; \
 		return ret; \
 	}
 	}
 
 
+/* returns a value, 3 params (var, old, new)
+ * The returned value is the value before the xchg:
+ *  if ret!=old => cmpxchg failed and ret is var's value
+ *  else  => success and new_v is var's new value */
+#define ATOMIC_FUNC_CMPXCHG(NAME, OP, P_TYPE, RET_TYPE) \
+	inline static RET_TYPE atomic_##NAME##_##P_TYPE(volatile P_TYPE* var, \
+													P_TYPE old, P_TYPE new_v)\
+	{ \
+		P_TYPE ret; \
+		asm volatile( \
+				__LOCK_PREF " " OP "\n\t" \
+				: "=a"(ret), "=m" (*var) :\
+					"r"(new_v), "m"(*var), "0"(old):\
+					"cc", "memory" \
+				); \
+		return ret; \
+	}
+
 ATOMIC_FUNC_DECL1(inc, "incl %0", int)
 ATOMIC_FUNC_DECL1(inc, "incl %0", int)
 ATOMIC_FUNC_DECL1(dec, "decl %0", int)
 ATOMIC_FUNC_DECL1(dec, "decl %0", int)
 ATOMIC_FUNC_DECL2(and, "andl %1, %0", int)
 ATOMIC_FUNC_DECL2(and, "andl %1, %0", int)
@@ -172,6 +191,7 @@ ATOMIC_FUNC_DECL2(or,  "orl %1, %0", int)
 ATOMIC_FUNC_TEST(inc_and_test, "incl %0", int, int)
 ATOMIC_FUNC_TEST(inc_and_test, "incl %0", int, int)
 ATOMIC_FUNC_TEST(dec_and_test, "decl %0", int, int)
 ATOMIC_FUNC_TEST(dec_and_test, "decl %0", int, int)
 ATOMIC_FUNC_XCHG(get_and_set,  "xchgl %1, %0", int)
 ATOMIC_FUNC_XCHG(get_and_set,  "xchgl %1, %0", int)
+ATOMIC_FUNC_CMPXCHG(cmpxchg, "cmpxchgl %2, %1", int , int)
 #ifdef __CPU_x86_64
 #ifdef __CPU_x86_64
 ATOMIC_FUNC_DECL1(inc, "incq %0", long)
 ATOMIC_FUNC_DECL1(inc, "incq %0", long)
 ATOMIC_FUNC_DECL1(dec, "decq %0", long)
 ATOMIC_FUNC_DECL1(dec, "decq %0", long)
@@ -180,6 +200,7 @@ ATOMIC_FUNC_DECL2(or,  "orq %1, %0", long)
 ATOMIC_FUNC_TEST(inc_and_test, "incq %0", long, int)
 ATOMIC_FUNC_TEST(inc_and_test, "incq %0", long, int)
 ATOMIC_FUNC_TEST(dec_and_test, "decq %0", long, int)
 ATOMIC_FUNC_TEST(dec_and_test, "decq %0", long, int)
 ATOMIC_FUNC_XCHG(get_and_set,  "xchgq %1, %0", long)
 ATOMIC_FUNC_XCHG(get_and_set,  "xchgq %1, %0", long)
+ATOMIC_FUNC_CMPXCHG(cmpxchg, "cmpxchgq %2, %1", long , long)
 #else
 #else
 ATOMIC_FUNC_DECL1(inc, "incl %0", long)
 ATOMIC_FUNC_DECL1(inc, "incl %0", long)
 ATOMIC_FUNC_DECL1(dec, "decl %0", long)
 ATOMIC_FUNC_DECL1(dec, "decl %0", long)
@@ -188,6 +209,7 @@ ATOMIC_FUNC_DECL2(or,  "orl %1, %0", long)
 ATOMIC_FUNC_TEST(inc_and_test, "incl %0", long, int)
 ATOMIC_FUNC_TEST(inc_and_test, "incl %0", long, int)
 ATOMIC_FUNC_TEST(dec_and_test, "decl %0", long, int)
 ATOMIC_FUNC_TEST(dec_and_test, "decl %0", long, int)
 ATOMIC_FUNC_XCHG(get_and_set,  "xchgl %1, %0", long)
 ATOMIC_FUNC_XCHG(get_and_set,  "xchgl %1, %0", long)
+ATOMIC_FUNC_CMPXCHG(cmpxchg, "cmpxchgl %2, %1", long , long)
 #endif
 #endif
 
 
 #define atomic_inc(var) atomic_inc_int(&(var)->val)
 #define atomic_inc(var) atomic_inc_int(&(var)->val)
@@ -197,6 +219,8 @@ ATOMIC_FUNC_XCHG(get_and_set,  "xchgl %1, %0", long)
 #define atomic_dec_and_test(var) atomic_dec_and_test_int(&(var)->val)
 #define atomic_dec_and_test(var) atomic_dec_and_test_int(&(var)->val)
 #define atomic_inc_and_test(var) atomic_inc_and_test_int(&(var)->val)
 #define atomic_inc_and_test(var) atomic_inc_and_test_int(&(var)->val)
 #define atomic_get_and_set(var, i) atomic_get_and_set_int(&(var)->val, i)
 #define atomic_get_and_set(var, i) atomic_get_and_set_int(&(var)->val, i)
+#define atomic_cmpxchg(var, old, newv) \
+		atomic_cmpxchg_int(&(var)->val, old, newv)
 
 
 
 
 #ifdef NOSMP
 #ifdef NOSMP