1*1a3b1d89SBrian Gerst #ifndef _ASM_X86_ATOMIC64_32_H 2*1a3b1d89SBrian Gerst #define _ASM_X86_ATOMIC64_32_H 3*1a3b1d89SBrian Gerst 4*1a3b1d89SBrian Gerst #include <linux/compiler.h> 5*1a3b1d89SBrian Gerst #include <linux/types.h> 6*1a3b1d89SBrian Gerst #include <asm/processor.h> 7*1a3b1d89SBrian Gerst //#include <asm/cmpxchg.h> 8*1a3b1d89SBrian Gerst 9*1a3b1d89SBrian Gerst /* An 64bit atomic type */ 10*1a3b1d89SBrian Gerst 11*1a3b1d89SBrian Gerst typedef struct { 12*1a3b1d89SBrian Gerst u64 __aligned(8) counter; 13*1a3b1d89SBrian Gerst } atomic64_t; 14*1a3b1d89SBrian Gerst 15*1a3b1d89SBrian Gerst #define ATOMIC64_INIT(val) { (val) } 16*1a3b1d89SBrian Gerst 17*1a3b1d89SBrian Gerst extern u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val); 18*1a3b1d89SBrian Gerst 19*1a3b1d89SBrian Gerst /** 20*1a3b1d89SBrian Gerst * atomic64_xchg - xchg atomic64 variable 21*1a3b1d89SBrian Gerst * @ptr: pointer to type atomic64_t 22*1a3b1d89SBrian Gerst * @new_val: value to assign 23*1a3b1d89SBrian Gerst * 24*1a3b1d89SBrian Gerst * Atomically xchgs the value of @ptr to @new_val and returns 25*1a3b1d89SBrian Gerst * the old value. 26*1a3b1d89SBrian Gerst */ 27*1a3b1d89SBrian Gerst extern u64 atomic64_xchg(atomic64_t *ptr, u64 new_val); 28*1a3b1d89SBrian Gerst 29*1a3b1d89SBrian Gerst /** 30*1a3b1d89SBrian Gerst * atomic64_set - set atomic64 variable 31*1a3b1d89SBrian Gerst * @ptr: pointer to type atomic64_t 32*1a3b1d89SBrian Gerst * @new_val: value to assign 33*1a3b1d89SBrian Gerst * 34*1a3b1d89SBrian Gerst * Atomically sets the value of @ptr to @new_val. 35*1a3b1d89SBrian Gerst */ 36*1a3b1d89SBrian Gerst extern void atomic64_set(atomic64_t *ptr, u64 new_val); 37*1a3b1d89SBrian Gerst 38*1a3b1d89SBrian Gerst /** 39*1a3b1d89SBrian Gerst * atomic64_read - read atomic64 variable 40*1a3b1d89SBrian Gerst * @ptr: pointer to type atomic64_t 41*1a3b1d89SBrian Gerst * 42*1a3b1d89SBrian Gerst * Atomically reads the value of @ptr and returns it. 43*1a3b1d89SBrian Gerst */ 44*1a3b1d89SBrian Gerst static inline u64 atomic64_read(atomic64_t *ptr) 45*1a3b1d89SBrian Gerst { 46*1a3b1d89SBrian Gerst u64 res; 47*1a3b1d89SBrian Gerst 48*1a3b1d89SBrian Gerst /* 49*1a3b1d89SBrian Gerst * Note, we inline this atomic64_t primitive because 50*1a3b1d89SBrian Gerst * it only clobbers EAX/EDX and leaves the others 51*1a3b1d89SBrian Gerst * untouched. We also (somewhat subtly) rely on the 52*1a3b1d89SBrian Gerst * fact that cmpxchg8b returns the current 64-bit value 53*1a3b1d89SBrian Gerst * of the memory location we are touching: 54*1a3b1d89SBrian Gerst */ 55*1a3b1d89SBrian Gerst asm volatile( 56*1a3b1d89SBrian Gerst "mov %%ebx, %%eax\n\t" 57*1a3b1d89SBrian Gerst "mov %%ecx, %%edx\n\t" 58*1a3b1d89SBrian Gerst LOCK_PREFIX "cmpxchg8b %1\n" 59*1a3b1d89SBrian Gerst : "=&A" (res) 60*1a3b1d89SBrian Gerst : "m" (*ptr) 61*1a3b1d89SBrian Gerst ); 62*1a3b1d89SBrian Gerst 63*1a3b1d89SBrian Gerst return res; 64*1a3b1d89SBrian Gerst } 65*1a3b1d89SBrian Gerst 66*1a3b1d89SBrian Gerst extern u64 atomic64_read(atomic64_t *ptr); 67*1a3b1d89SBrian Gerst 68*1a3b1d89SBrian Gerst /** 69*1a3b1d89SBrian Gerst * atomic64_add_return - add and return 70*1a3b1d89SBrian Gerst * @delta: integer value to add 71*1a3b1d89SBrian Gerst * @ptr: pointer to type atomic64_t 72*1a3b1d89SBrian Gerst * 73*1a3b1d89SBrian Gerst * Atomically adds @delta to @ptr and returns @delta + *@ptr 74*1a3b1d89SBrian Gerst */ 75*1a3b1d89SBrian Gerst extern u64 atomic64_add_return(u64 delta, atomic64_t *ptr); 76*1a3b1d89SBrian Gerst 77*1a3b1d89SBrian Gerst /* 78*1a3b1d89SBrian Gerst * Other variants with different arithmetic operators: 79*1a3b1d89SBrian Gerst */ 80*1a3b1d89SBrian Gerst extern u64 atomic64_sub_return(u64 delta, atomic64_t *ptr); 81*1a3b1d89SBrian Gerst extern u64 atomic64_inc_return(atomic64_t *ptr); 82*1a3b1d89SBrian Gerst extern u64 atomic64_dec_return(atomic64_t *ptr); 83*1a3b1d89SBrian Gerst 84*1a3b1d89SBrian Gerst /** 85*1a3b1d89SBrian Gerst * atomic64_add - add integer to atomic64 variable 86*1a3b1d89SBrian Gerst * @delta: integer value to add 87*1a3b1d89SBrian Gerst * @ptr: pointer to type atomic64_t 88*1a3b1d89SBrian Gerst * 89*1a3b1d89SBrian Gerst * Atomically adds @delta to @ptr. 90*1a3b1d89SBrian Gerst */ 91*1a3b1d89SBrian Gerst extern void atomic64_add(u64 delta, atomic64_t *ptr); 92*1a3b1d89SBrian Gerst 93*1a3b1d89SBrian Gerst /** 94*1a3b1d89SBrian Gerst * atomic64_sub - subtract the atomic64 variable 95*1a3b1d89SBrian Gerst * @delta: integer value to subtract 96*1a3b1d89SBrian Gerst * @ptr: pointer to type atomic64_t 97*1a3b1d89SBrian Gerst * 98*1a3b1d89SBrian Gerst * Atomically subtracts @delta from @ptr. 99*1a3b1d89SBrian Gerst */ 100*1a3b1d89SBrian Gerst extern void atomic64_sub(u64 delta, atomic64_t *ptr); 101*1a3b1d89SBrian Gerst 102*1a3b1d89SBrian Gerst /** 103*1a3b1d89SBrian Gerst * atomic64_sub_and_test - subtract value from variable and test result 104*1a3b1d89SBrian Gerst * @delta: integer value to subtract 105*1a3b1d89SBrian Gerst * @ptr: pointer to type atomic64_t 106*1a3b1d89SBrian Gerst * 107*1a3b1d89SBrian Gerst * Atomically subtracts @delta from @ptr and returns 108*1a3b1d89SBrian Gerst * true if the result is zero, or false for all 109*1a3b1d89SBrian Gerst * other cases. 110*1a3b1d89SBrian Gerst */ 111*1a3b1d89SBrian Gerst extern int atomic64_sub_and_test(u64 delta, atomic64_t *ptr); 112*1a3b1d89SBrian Gerst 113*1a3b1d89SBrian Gerst /** 114*1a3b1d89SBrian Gerst * atomic64_inc - increment atomic64 variable 115*1a3b1d89SBrian Gerst * @ptr: pointer to type atomic64_t 116*1a3b1d89SBrian Gerst * 117*1a3b1d89SBrian Gerst * Atomically increments @ptr by 1. 118*1a3b1d89SBrian Gerst */ 119*1a3b1d89SBrian Gerst extern void atomic64_inc(atomic64_t *ptr); 120*1a3b1d89SBrian Gerst 121*1a3b1d89SBrian Gerst /** 122*1a3b1d89SBrian Gerst * atomic64_dec - decrement atomic64 variable 123*1a3b1d89SBrian Gerst * @ptr: pointer to type atomic64_t 124*1a3b1d89SBrian Gerst * 125*1a3b1d89SBrian Gerst * Atomically decrements @ptr by 1. 126*1a3b1d89SBrian Gerst */ 127*1a3b1d89SBrian Gerst extern void atomic64_dec(atomic64_t *ptr); 128*1a3b1d89SBrian Gerst 129*1a3b1d89SBrian Gerst /** 130*1a3b1d89SBrian Gerst * atomic64_dec_and_test - decrement and test 131*1a3b1d89SBrian Gerst * @ptr: pointer to type atomic64_t 132*1a3b1d89SBrian Gerst * 133*1a3b1d89SBrian Gerst * Atomically decrements @ptr by 1 and 134*1a3b1d89SBrian Gerst * returns true if the result is 0, or false for all other 135*1a3b1d89SBrian Gerst * cases. 136*1a3b1d89SBrian Gerst */ 137*1a3b1d89SBrian Gerst extern int atomic64_dec_and_test(atomic64_t *ptr); 138*1a3b1d89SBrian Gerst 139*1a3b1d89SBrian Gerst /** 140*1a3b1d89SBrian Gerst * atomic64_inc_and_test - increment and test 141*1a3b1d89SBrian Gerst * @ptr: pointer to type atomic64_t 142*1a3b1d89SBrian Gerst * 143*1a3b1d89SBrian Gerst * Atomically increments @ptr by 1 144*1a3b1d89SBrian Gerst * and returns true if the result is zero, or false for all 145*1a3b1d89SBrian Gerst * other cases. 146*1a3b1d89SBrian Gerst */ 147*1a3b1d89SBrian Gerst extern int atomic64_inc_and_test(atomic64_t *ptr); 148*1a3b1d89SBrian Gerst 149*1a3b1d89SBrian Gerst /** 150*1a3b1d89SBrian Gerst * atomic64_add_negative - add and test if negative 151*1a3b1d89SBrian Gerst * @delta: integer value to add 152*1a3b1d89SBrian Gerst * @ptr: pointer to type atomic64_t 153*1a3b1d89SBrian Gerst * 154*1a3b1d89SBrian Gerst * Atomically adds @delta to @ptr and returns true 155*1a3b1d89SBrian Gerst * if the result is negative, or false when 156*1a3b1d89SBrian Gerst * result is greater than or equal to zero. 157*1a3b1d89SBrian Gerst */ 158*1a3b1d89SBrian Gerst extern int atomic64_add_negative(u64 delta, atomic64_t *ptr); 159*1a3b1d89SBrian Gerst 160*1a3b1d89SBrian Gerst #endif /* _ASM_X86_ATOMIC64_32_H */ 161