about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--include/atomic.h52
1 files changed, 47 insertions, 5 deletions
diff --git a/include/atomic.h b/include/atomic.h
index 813fb80a03..517776452b 100644
--- a/include/atomic.h
+++ b/include/atomic.h
@@ -49,6 +49,24 @@
 #endif
 
 
+/* Store NEWVALUE in *MEM and return the old value.  */
+#ifndef atomic_exchange
+# define atomic_exchange(mem, newvalue) \
+  ({ __typeof (*mem) __oldval;						      \
+     __typeof (mem) __memp = (mem);					      \
+     __typeof (*mem) __value = (newvalue);				      \
+									      \
+     do									      \
+       __oldval = (*__memp);						      \
+     while (__builtin_expect (atomic_compare_and_exchange_acq (__memp,	      \
+							       __value,	      \
+							       __oldval), 0));\
+									      \
+     __oldval; })
+#endif
+
+
+/* Add VALUE to *MEM and return the old value of *MEM.  */
 #ifndef atomic_exchange_and_add
 # define atomic_exchange_and_add(mem, value) \
   ({ __typeof (*mem) __oldval;						      \
@@ -57,10 +75,12 @@
 									      \
      do									      \
        __oldval = (*__memp);						      \
-     while (atomic_compare_and_exchange_acq (__memp, __oldval + __value,      \
-					     __oldval));		      \
+     while (__builtin_expect (atomic_compare_and_exchange_acq (__memp,	      \
+							       __oldval	      \
+							       + __value,     \
+							       __oldval), 0));\
 									      \
-     __oldval + __value; })
+     __oldval; })
 #endif
 
 
@@ -91,6 +111,26 @@
 #endif
 
 
+/* Decrement *MEM if it is > 0, and return the old value.  */
+#ifndef atomic_decrement_if_positive(mem) \
+  ({ __typeof (*mem) __val;						      \
+     __typeof (*mem) __oldval;						      \
+     __typeof (mem) __memp;						      \
+     									      \
+     __val = *__memp;							      \
+     do									      \
+       {								      \
+	 if (__builtin_expect (__val <= 0, 0))				      \
+	   break;							      \
+	 __oldval = __val;						      \
+	 __val = atomic_compare_and_exchange_acq (__memp, __oldval - 1,	      \
+						  __oldval);		      \
+       }								      \
+     while (__builtin_expect (__val != __oldval, 0));			      \
+     __val; })
+#endif
+
+
 #ifndef atomic_add_negative
 # define atomic_add_negative(mem, value) \
   (atomic_exchange_and_add (mem, value) < 0)
@@ -117,8 +157,10 @@
 									      \
      do									      \
        __oldval = (*__memp);						      \
-     while (atomic_compare_and_exchange_acq (__memp,			      \
-					     __oldval | __mask, __oldval));   \
+     while (__builtin_expect (atomic_compare_and_exchange_acq (__memp,	      \
+							       __oldval	      \
+							       | __mask,      \
+							       __oldval), 0));\
 									      \
      __oldval & __mask; })
 #endif