-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
x86: Split atomic64_t functions into seperate headers
Split atomic64_t functions out into separate headers, since they will not be practical to merge between 32 and 64 bits. Signed-off-by: Brian Gerst <brgerst@gmail.com> LKML-Reference: <1262883215-4034-2-git-send-email-brgerst@gmail.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
- Loading branch information
Brian Gerst
authored and
H. Peter Anvin
committed
Jan 7, 2010
1 parent
7269e88
commit 1a3b1d8
Showing
4 changed files
with
386 additions
and
367 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
#ifndef _ASM_X86_ATOMIC64_32_H | ||
#define _ASM_X86_ATOMIC64_32_H | ||
|
||
#include <linux/compiler.h> | ||
#include <linux/types.h> | ||
#include <asm/processor.h> | ||
//#include <asm/cmpxchg.h> | ||
|
||
/* An 64bit atomic type */ | ||
|
||
typedef struct { | ||
u64 __aligned(8) counter; | ||
} atomic64_t; | ||
|
||
#define ATOMIC64_INIT(val) { (val) } | ||
|
||
extern u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val); | ||
|
||
/** | ||
* atomic64_xchg - xchg atomic64 variable | ||
* @ptr: pointer to type atomic64_t | ||
* @new_val: value to assign | ||
* | ||
* Atomically xchgs the value of @ptr to @new_val and returns | ||
* the old value. | ||
*/ | ||
extern u64 atomic64_xchg(atomic64_t *ptr, u64 new_val); | ||
|
||
/** | ||
* atomic64_set - set atomic64 variable | ||
* @ptr: pointer to type atomic64_t | ||
* @new_val: value to assign | ||
* | ||
* Atomically sets the value of @ptr to @new_val. | ||
*/ | ||
extern void atomic64_set(atomic64_t *ptr, u64 new_val); | ||
|
||
/** | ||
* atomic64_read - read atomic64 variable | ||
* @ptr: pointer to type atomic64_t | ||
* | ||
* Atomically reads the value of @ptr and returns it. | ||
*/ | ||
static inline u64 atomic64_read(atomic64_t *ptr) | ||
{ | ||
u64 res; | ||
|
||
/* | ||
* Note, we inline this atomic64_t primitive because | ||
* it only clobbers EAX/EDX and leaves the others | ||
* untouched. We also (somewhat subtly) rely on the | ||
* fact that cmpxchg8b returns the current 64-bit value | ||
* of the memory location we are touching: | ||
*/ | ||
asm volatile( | ||
"mov %%ebx, %%eax\n\t" | ||
"mov %%ecx, %%edx\n\t" | ||
LOCK_PREFIX "cmpxchg8b %1\n" | ||
: "=&A" (res) | ||
: "m" (*ptr) | ||
); | ||
|
||
return res; | ||
} | ||
|
||
extern u64 atomic64_read(atomic64_t *ptr); | ||
|
||
/** | ||
* atomic64_add_return - add and return | ||
* @delta: integer value to add | ||
* @ptr: pointer to type atomic64_t | ||
* | ||
* Atomically adds @delta to @ptr and returns @delta + *@ptr | ||
*/ | ||
extern u64 atomic64_add_return(u64 delta, atomic64_t *ptr); | ||
|
||
/* | ||
* Other variants with different arithmetic operators: | ||
*/ | ||
extern u64 atomic64_sub_return(u64 delta, atomic64_t *ptr); | ||
extern u64 atomic64_inc_return(atomic64_t *ptr); | ||
extern u64 atomic64_dec_return(atomic64_t *ptr); | ||
|
||
/** | ||
* atomic64_add - add integer to atomic64 variable | ||
* @delta: integer value to add | ||
* @ptr: pointer to type atomic64_t | ||
* | ||
* Atomically adds @delta to @ptr. | ||
*/ | ||
extern void atomic64_add(u64 delta, atomic64_t *ptr); | ||
|
||
/** | ||
* atomic64_sub - subtract the atomic64 variable | ||
* @delta: integer value to subtract | ||
* @ptr: pointer to type atomic64_t | ||
* | ||
* Atomically subtracts @delta from @ptr. | ||
*/ | ||
extern void atomic64_sub(u64 delta, atomic64_t *ptr); | ||
|
||
/** | ||
* atomic64_sub_and_test - subtract value from variable and test result | ||
* @delta: integer value to subtract | ||
* @ptr: pointer to type atomic64_t | ||
* | ||
* Atomically subtracts @delta from @ptr and returns | ||
* true if the result is zero, or false for all | ||
* other cases. | ||
*/ | ||
extern int atomic64_sub_and_test(u64 delta, atomic64_t *ptr); | ||
|
||
/** | ||
* atomic64_inc - increment atomic64 variable | ||
* @ptr: pointer to type atomic64_t | ||
* | ||
* Atomically increments @ptr by 1. | ||
*/ | ||
extern void atomic64_inc(atomic64_t *ptr); | ||
|
||
/** | ||
* atomic64_dec - decrement atomic64 variable | ||
* @ptr: pointer to type atomic64_t | ||
* | ||
* Atomically decrements @ptr by 1. | ||
*/ | ||
extern void atomic64_dec(atomic64_t *ptr); | ||
|
||
/** | ||
* atomic64_dec_and_test - decrement and test | ||
* @ptr: pointer to type atomic64_t | ||
* | ||
* Atomically decrements @ptr by 1 and | ||
* returns true if the result is 0, or false for all other | ||
* cases. | ||
*/ | ||
extern int atomic64_dec_and_test(atomic64_t *ptr); | ||
|
||
/** | ||
* atomic64_inc_and_test - increment and test | ||
* @ptr: pointer to type atomic64_t | ||
* | ||
* Atomically increments @ptr by 1 | ||
* and returns true if the result is zero, or false for all | ||
* other cases. | ||
*/ | ||
extern int atomic64_inc_and_test(atomic64_t *ptr); | ||
|
||
/** | ||
* atomic64_add_negative - add and test if negative | ||
* @delta: integer value to add | ||
* @ptr: pointer to type atomic64_t | ||
* | ||
* Atomically adds @delta to @ptr and returns true | ||
* if the result is negative, or false when | ||
* result is greater than or equal to zero. | ||
*/ | ||
extern int atomic64_add_negative(u64 delta, atomic64_t *ptr); | ||
|
||
#endif /* _ASM_X86_ATOMIC64_32_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
#ifndef _ASM_X86_ATOMIC64_64_H | ||
#define _ASM_X86_ATOMIC64_64_H | ||
|
||
#include <linux/types.h> | ||
#include <asm/alternative.h> | ||
#include <asm/cmpxchg.h> | ||
|
||
/* The 64-bit atomic type */ | ||
|
||
#define ATOMIC64_INIT(i) { (i) } | ||
|
||
/** | ||
* atomic64_read - read atomic64 variable | ||
* @v: pointer of type atomic64_t | ||
* | ||
* Atomically reads the value of @v. | ||
* Doesn't imply a read memory barrier. | ||
*/ | ||
static inline long atomic64_read(const atomic64_t *v) | ||
{ | ||
return v->counter; | ||
} | ||
|
||
/** | ||
* atomic64_set - set atomic64 variable | ||
* @v: pointer to type atomic64_t | ||
* @i: required value | ||
* | ||
* Atomically sets the value of @v to @i. | ||
*/ | ||
static inline void atomic64_set(atomic64_t *v, long i) | ||
{ | ||
v->counter = i; | ||
} | ||
|
||
/** | ||
* atomic64_add - add integer to atomic64 variable | ||
* @i: integer value to add | ||
* @v: pointer to type atomic64_t | ||
* | ||
* Atomically adds @i to @v. | ||
*/ | ||
static inline void atomic64_add(long i, atomic64_t *v) | ||
{ | ||
asm volatile(LOCK_PREFIX "addq %1,%0" | ||
: "=m" (v->counter) | ||
: "er" (i), "m" (v->counter)); | ||
} | ||
|
||
/** | ||
* atomic64_sub - subtract the atomic64 variable | ||
* @i: integer value to subtract | ||
* @v: pointer to type atomic64_t | ||
* | ||
* Atomically subtracts @i from @v. | ||
*/ | ||
static inline void atomic64_sub(long i, atomic64_t *v) | ||
{ | ||
asm volatile(LOCK_PREFIX "subq %1,%0" | ||
: "=m" (v->counter) | ||
: "er" (i), "m" (v->counter)); | ||
} | ||
|
||
/** | ||
* atomic64_sub_and_test - subtract value from variable and test result | ||
* @i: integer value to subtract | ||
* @v: pointer to type atomic64_t | ||
* | ||
* Atomically subtracts @i from @v and returns | ||
* true if the result is zero, or false for all | ||
* other cases. | ||
*/ | ||
static inline int atomic64_sub_and_test(long i, atomic64_t *v) | ||
{ | ||
unsigned char c; | ||
|
||
asm volatile(LOCK_PREFIX "subq %2,%0; sete %1" | ||
: "=m" (v->counter), "=qm" (c) | ||
: "er" (i), "m" (v->counter) : "memory"); | ||
return c; | ||
} | ||
|
||
/** | ||
* atomic64_inc - increment atomic64 variable | ||
* @v: pointer to type atomic64_t | ||
* | ||
* Atomically increments @v by 1. | ||
*/ | ||
static inline void atomic64_inc(atomic64_t *v) | ||
{ | ||
asm volatile(LOCK_PREFIX "incq %0" | ||
: "=m" (v->counter) | ||
: "m" (v->counter)); | ||
} | ||
|
||
/** | ||
* atomic64_dec - decrement atomic64 variable | ||
* @v: pointer to type atomic64_t | ||
* | ||
* Atomically decrements @v by 1. | ||
*/ | ||
static inline void atomic64_dec(atomic64_t *v) | ||
{ | ||
asm volatile(LOCK_PREFIX "decq %0" | ||
: "=m" (v->counter) | ||
: "m" (v->counter)); | ||
} | ||
|
||
/** | ||
* atomic64_dec_and_test - decrement and test | ||
* @v: pointer to type atomic64_t | ||
* | ||
* Atomically decrements @v by 1 and | ||
* returns true if the result is 0, or false for all other | ||
* cases. | ||
*/ | ||
static inline int atomic64_dec_and_test(atomic64_t *v) | ||
{ | ||
unsigned char c; | ||
|
||
asm volatile(LOCK_PREFIX "decq %0; sete %1" | ||
: "=m" (v->counter), "=qm" (c) | ||
: "m" (v->counter) : "memory"); | ||
return c != 0; | ||
} | ||
|
||
/** | ||
* atomic64_inc_and_test - increment and test | ||
* @v: pointer to type atomic64_t | ||
* | ||
* Atomically increments @v by 1 | ||
* and returns true if the result is zero, or false for all | ||
* other cases. | ||
*/ | ||
static inline int atomic64_inc_and_test(atomic64_t *v) | ||
{ | ||
unsigned char c; | ||
|
||
asm volatile(LOCK_PREFIX "incq %0; sete %1" | ||
: "=m" (v->counter), "=qm" (c) | ||
: "m" (v->counter) : "memory"); | ||
return c != 0; | ||
} | ||
|
||
/** | ||
* atomic64_add_negative - add and test if negative | ||
* @i: integer value to add | ||
* @v: pointer to type atomic64_t | ||
* | ||
* Atomically adds @i to @v and returns true | ||
* if the result is negative, or false when | ||
* result is greater than or equal to zero. | ||
*/ | ||
static inline int atomic64_add_negative(long i, atomic64_t *v) | ||
{ | ||
unsigned char c; | ||
|
||
asm volatile(LOCK_PREFIX "addq %2,%0; sets %1" | ||
: "=m" (v->counter), "=qm" (c) | ||
: "er" (i), "m" (v->counter) : "memory"); | ||
return c; | ||
} | ||
|
||
/** | ||
* atomic64_add_return - add and return | ||
* @i: integer value to add | ||
* @v: pointer to type atomic64_t | ||
* | ||
* Atomically adds @i to @v and returns @i + @v | ||
*/ | ||
static inline long atomic64_add_return(long i, atomic64_t *v) | ||
{ | ||
long __i = i; | ||
asm volatile(LOCK_PREFIX "xaddq %0, %1;" | ||
: "+r" (i), "+m" (v->counter) | ||
: : "memory"); | ||
return i + __i; | ||
} | ||
|
||
static inline long atomic64_sub_return(long i, atomic64_t *v) | ||
{ | ||
return atomic64_add_return(-i, v); | ||
} | ||
|
||
#define atomic64_inc_return(v) (atomic64_add_return(1, (v))) | ||
#define atomic64_dec_return(v) (atomic64_sub_return(1, (v))) | ||
|
||
static inline long atomic64_cmpxchg(atomic64_t *v, long old, long new) | ||
{ | ||
return cmpxchg(&v->counter, old, new); | ||
} | ||
|
||
static inline long atomic64_xchg(atomic64_t *v, long new) | ||
{ | ||
return xchg(&v->counter, new); | ||
} | ||
|
||
/** | ||
* atomic64_add_unless - add unless the number is a given value | ||
* @v: pointer of type atomic64_t | ||
* @a: the amount to add to v... | ||
* @u: ...unless v is equal to u. | ||
* | ||
* Atomically adds @a to @v, so long as it was not @u. | ||
* Returns non-zero if @v was not @u, and zero otherwise. | ||
*/ | ||
static inline int atomic64_add_unless(atomic64_t *v, long a, long u) | ||
{ | ||
long c, old; | ||
c = atomic64_read(v); | ||
for (;;) { | ||
if (unlikely(c == (u))) | ||
break; | ||
old = atomic64_cmpxchg((v), c, c + (a)); | ||
if (likely(old == c)) | ||
break; | ||
c = old; | ||
} | ||
return c != (u); | ||
} | ||
|
||
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) | ||
|
||
#endif /* _ASM_X86_ATOMIC64_64_H */ |
Oops, something went wrong.