mutex subsystem, add atomic_*_call_if_*() to x86_64
PATCH 3/9 mutex subsystem, add atomic_*_call_if_*() to x86_64
add two new atomic ops to x86_64: atomic_dec_call_if_negative() and atomic_inc_call_if_nonpositive(), which are conditional-call-if atomic operations. Needed by the new mutex code.
Signed-off-by Ingo Molnar <[email protected]>
----
include/asm-x86_64/atomic.h | 58 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 58 insertions(+)
include/asm-x86_64/atomic.h +58 -0
@@ -203,6 +203,64 @@ static __inline__ int atomic_sub_return(#define atomic_inc_return (v) (atomic_add_return(1,v))#define atomic_dec_return (v) (atomic_sub_return(1,v)) +/** +* atomic_dec_call_if_negative - decrement and call function if negative +* @v: pointer of type atomic_t +* @fn: function to call if the result is negative +* +* Atomically decrements @v and calls a function if the result is negative. +*/ +#define atomic_dec_call_if_negative (v, fn_name) \ +do { \ + fastcall void (*__tmp)(atomic_t *) = fn_name; \ + unsigned long dummy; \ + \ + (void)__tmp; \ + typecheck(atomic_t *, v); \ + \ + __asm__ __volatile__( \ + LOCK "decl (%%rdi)\n" \ + "js 2f\n" \ + "1:\n" \ + LOCK_SECTION_START("") \ + "2: call "#fn_name"\n\t" \ + "jmp 1b\n" \ + LOCK_SECTION_END \ + :"=D" (dummy) \ + :"D" (v) \ + :"rax", "rsi", "rdx", "rcx", \ + "r8", "r9", "r10", "r11", "memory"); \ +} while (0) + +/** +* atomic_inc_call_if_nonpositive - increment and call function if nonpositive +* @v: pointer of type atomic_t +* @fn: function to call if the result is nonpositive +* +* Atomically increments @v and calls a function if the result is nonpositive. +*/ +#define atomic_inc_call_if_nonpositive (v, fn_name) \ +do { \ + fastcall void (*__tmp)(atomic_t *) = fn_name; \ + unsigned long dummy; \ + \ + (void)__tmp; \ + typecheck(atomic_t *, v); \ + \ + __asm__ __volatile__( \ + LOCK "incl (%%rdi)\n" \ + "jle 2f\n" \ + "1:\n" \ + LOCK_SECTION_START("") \ + "2: call "#fn_name"\n\t" \ + "jmp 1b\n" \ + LOCK_SECTION_END \ + :"=D" (dummy) \ + :"D" (v) \ + :"rax", "rsi", "rdx", "rcx", \ + "r8", "r9", "r10", "r11", "memory"); \ +} while (0) +/* An 64bit atomic type */ typedef struct {volatile long counter; }atomic64_t ;