mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-21 11:13:30 +00:00
Add support for 8- and 16-bit atomic_(f)cmpset to x86.
Reviewed by: kib MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D10068
This commit is contained in:
parent
84eb6b9887
commit
3d6732549d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=315718
@ -23,7 +23,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd Jan 3, 2017
|
||||
.Dd March 22, 2017
|
||||
.Dt ATOMIC 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -226,9 +226,9 @@ if (*dst == old) {
|
||||
.Ed
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
Some architectures do not implement the
|
||||
.Fn atomic_cmpset
|
||||
functions are not implemented for the types
|
||||
functions for the types
|
||||
.Dq Li char ,
|
||||
.Dq Li short ,
|
||||
.Dq Li 8 ,
|
||||
@ -265,9 +265,9 @@ function also returns
|
||||
despite
|
||||
.Dl *old == *dst .
|
||||
.Pp
|
||||
The
|
||||
Some architectures do not implement the
|
||||
.Fn atomic_fcmpset
|
||||
functions are not implemented for the types
|
||||
functions for the types
|
||||
.Dq Li char ,
|
||||
.Dq Li short ,
|
||||
.Dq Li 8 ,
|
||||
|
@ -97,8 +97,13 @@
|
||||
void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v); \
|
||||
void atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v)
|
||||
|
||||
int atomic_cmpset_char(volatile u_char *dst, u_char expect, u_char src);
|
||||
int atomic_cmpset_short(volatile u_short *dst, u_short expect, u_short src);
|
||||
int atomic_cmpset_int(volatile u_int *dst, u_int expect, u_int src);
|
||||
int atomic_cmpset_long(volatile u_long *dst, u_long expect, u_long src);
|
||||
int atomic_fcmpset_char(volatile u_char *dst, u_char *expect, u_char src);
|
||||
int atomic_fcmpset_short(volatile u_short *dst, u_short *expect,
|
||||
u_short src);
|
||||
int atomic_fcmpset_int(volatile u_int *dst, u_int *expect, u_int src);
|
||||
int atomic_fcmpset_long(volatile u_long *dst, u_long *expect, u_long src);
|
||||
u_int atomic_fetchadd_int(volatile u_int *p, u_int v);
|
||||
@ -155,84 +160,61 @@ atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
|
||||
struct __hack
|
||||
|
||||
/*
|
||||
* Atomic compare and set, used by the mutex functions
|
||||
* Atomic compare and set, used by the mutex functions.
|
||||
*
|
||||
* if (*dst == expect) *dst = src (all 32 bit words)
|
||||
* cmpset:
|
||||
* if (*dst == expect)
|
||||
* *dst = src
|
||||
*
|
||||
* Returns 0 on failure, non-zero on success
|
||||
* fcmpset:
|
||||
* if (*dst == *expect)
|
||||
* *dst = src
|
||||
* else
|
||||
* *expect = *dst
|
||||
*
|
||||
* Returns 0 on failure, non-zero on success.
|
||||
*/
|
||||
|
||||
static __inline int
|
||||
atomic_cmpset_int(volatile u_int *dst, u_int expect, u_int src)
|
||||
{
|
||||
u_char res;
|
||||
|
||||
__asm __volatile(
|
||||
" " MPLOCKED " "
|
||||
" cmpxchgl %3,%1 ; "
|
||||
" sete %0 ; "
|
||||
"# atomic_cmpset_int"
|
||||
: "=q" (res), /* 0 */
|
||||
"+m" (*dst), /* 1 */
|
||||
"+a" (expect) /* 2 */
|
||||
: "r" (src) /* 3 */
|
||||
: "memory", "cc");
|
||||
return (res);
|
||||
#define ATOMIC_CMPSET(TYPE) \
|
||||
static __inline int \
|
||||
atomic_cmpset_##TYPE(volatile u_##TYPE *dst, u_##TYPE expect, u_##TYPE src) \
|
||||
{ \
|
||||
u_char res; \
|
||||
\
|
||||
__asm __volatile( \
|
||||
" " MPLOCKED " " \
|
||||
" cmpxchg %3,%1 ; " \
|
||||
" sete %0 ; " \
|
||||
"# atomic_cmpset_" #TYPE " " \
|
||||
: "=q" (res), /* 0 */ \
|
||||
"+m" (*dst), /* 1 */ \
|
||||
"+a" (expect) /* 2 */ \
|
||||
: "r" (src) /* 3 */ \
|
||||
: "memory", "cc"); \
|
||||
return (res); \
|
||||
} \
|
||||
\
|
||||
static __inline int \
|
||||
atomic_fcmpset_##TYPE(volatile u_##TYPE *dst, u_##TYPE *expect, u_##TYPE src) \
|
||||
{ \
|
||||
u_char res; \
|
||||
\
|
||||
__asm __volatile( \
|
||||
" " MPLOCKED " " \
|
||||
" cmpxchg %3,%1 ; " \
|
||||
" sete %0 ; " \
|
||||
"# atomic_fcmpset_" #TYPE " " \
|
||||
: "=q" (res), /* 0 */ \
|
||||
"+m" (*dst), /* 1 */ \
|
||||
"+a" (*expect) /* 2 */ \
|
||||
: "r" (src) /* 3 */ \
|
||||
: "memory", "cc"); \
|
||||
return (res); \
|
||||
}
|
||||
|
||||
static __inline int
|
||||
atomic_cmpset_long(volatile u_long *dst, u_long expect, u_long src)
|
||||
{
|
||||
u_char res;
|
||||
|
||||
__asm __volatile(
|
||||
" " MPLOCKED " "
|
||||
" cmpxchgq %3,%1 ; "
|
||||
" sete %0 ; "
|
||||
"# atomic_cmpset_long"
|
||||
: "=q" (res), /* 0 */
|
||||
"+m" (*dst), /* 1 */
|
||||
"+a" (expect) /* 2 */
|
||||
: "r" (src) /* 3 */
|
||||
: "memory", "cc");
|
||||
return (res);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
atomic_fcmpset_int(volatile u_int *dst, u_int *expect, u_int src)
|
||||
{
|
||||
u_char res;
|
||||
|
||||
__asm __volatile(
|
||||
" " MPLOCKED " "
|
||||
" cmpxchgl %3,%1 ; "
|
||||
" sete %0 ; "
|
||||
"# atomic_fcmpset_int"
|
||||
: "=r" (res), /* 0 */
|
||||
"+m" (*dst), /* 1 */
|
||||
"+a" (*expect) /* 2 */
|
||||
: "r" (src) /* 3 */
|
||||
: "memory", "cc");
|
||||
return (res);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
atomic_fcmpset_long(volatile u_long *dst, u_long *expect, u_long src)
|
||||
{
|
||||
u_char res;
|
||||
|
||||
__asm __volatile(
|
||||
" " MPLOCKED " "
|
||||
" cmpxchgq %3,%1 ; "
|
||||
" sete %0 ; "
|
||||
"# atomic_fcmpset_long"
|
||||
: "=r" (res), /* 0 */
|
||||
"+m" (*dst), /* 1 */
|
||||
"+a" (*expect) /* 2 */
|
||||
: "r" (src) /* 3 */
|
||||
: "memory", "cc");
|
||||
return (res);
|
||||
}
|
||||
ATOMIC_CMPSET(char);
|
||||
ATOMIC_CMPSET(short);
|
||||
ATOMIC_CMPSET(int);
|
||||
ATOMIC_CMPSET(long);
|
||||
|
||||
/*
|
||||
* Atomically add the value of v to the integer pointed to by p and return
|
||||
@ -522,6 +504,10 @@ u_long atomic_swap_long(volatile u_long *p, u_long v);
|
||||
#define atomic_add_rel_char atomic_add_barr_char
|
||||
#define atomic_subtract_acq_char atomic_subtract_barr_char
|
||||
#define atomic_subtract_rel_char atomic_subtract_barr_char
|
||||
#define atomic_cmpset_acq_char atomic_cmpset_char
|
||||
#define atomic_cmpset_rel_char atomic_cmpset_char
|
||||
#define atomic_fcmpset_acq_char atomic_fcmpset_char
|
||||
#define atomic_fcmpset_rel_char atomic_fcmpset_char
|
||||
|
||||
#define atomic_set_acq_short atomic_set_barr_short
|
||||
#define atomic_set_rel_short atomic_set_barr_short
|
||||
@ -531,6 +517,10 @@ u_long atomic_swap_long(volatile u_long *p, u_long v);
|
||||
#define atomic_add_rel_short atomic_add_barr_short
|
||||
#define atomic_subtract_acq_short atomic_subtract_barr_short
|
||||
#define atomic_subtract_rel_short atomic_subtract_barr_short
|
||||
#define atomic_cmpset_acq_short atomic_cmpset_short
|
||||
#define atomic_cmpset_rel_short atomic_cmpset_short
|
||||
#define atomic_fcmpset_acq_short atomic_fcmpset_short
|
||||
#define atomic_fcmpset_rel_short atomic_fcmpset_short
|
||||
|
||||
#define atomic_set_acq_int atomic_set_barr_int
|
||||
#define atomic_set_rel_int atomic_set_barr_int
|
||||
@ -542,8 +532,8 @@ u_long atomic_swap_long(volatile u_long *p, u_long v);
|
||||
#define atomic_subtract_rel_int atomic_subtract_barr_int
|
||||
#define atomic_cmpset_acq_int atomic_cmpset_int
|
||||
#define atomic_cmpset_rel_int atomic_cmpset_int
|
||||
#define atomic_fcmpset_acq_int atomic_fcmpset_int
|
||||
#define atomic_fcmpset_rel_int atomic_fcmpset_int
|
||||
#define atomic_fcmpset_acq_int atomic_fcmpset_int
|
||||
#define atomic_fcmpset_rel_int atomic_fcmpset_int
|
||||
|
||||
#define atomic_set_acq_long atomic_set_barr_long
|
||||
#define atomic_set_rel_long atomic_set_barr_long
|
||||
@ -555,8 +545,8 @@ u_long atomic_swap_long(volatile u_long *p, u_long v);
|
||||
#define atomic_subtract_rel_long atomic_subtract_barr_long
|
||||
#define atomic_cmpset_acq_long atomic_cmpset_long
|
||||
#define atomic_cmpset_rel_long atomic_cmpset_long
|
||||
#define atomic_fcmpset_acq_long atomic_fcmpset_long
|
||||
#define atomic_fcmpset_rel_long atomic_fcmpset_long
|
||||
#define atomic_fcmpset_acq_long atomic_fcmpset_long
|
||||
#define atomic_fcmpset_rel_long atomic_fcmpset_long
|
||||
|
||||
#define atomic_readandclear_int(p) atomic_swap_int(p, 0)
|
||||
#define atomic_readandclear_long(p) atomic_swap_long(p, 0)
|
||||
@ -576,6 +566,12 @@ u_long atomic_swap_long(volatile u_long *p, u_long v);
|
||||
#define atomic_subtract_rel_8 atomic_subtract_rel_char
|
||||
#define atomic_load_acq_8 atomic_load_acq_char
|
||||
#define atomic_store_rel_8 atomic_store_rel_char
|
||||
#define atomic_cmpset_8 atomic_cmpset_char
|
||||
#define atomic_cmpset_acq_8 atomic_cmpset_acq_char
|
||||
#define atomic_cmpset_rel_8 atomic_cmpset_rel_char
|
||||
#define atomic_fcmpset_8 atomic_fcmpset_char
|
||||
#define atomic_fcmpset_acq_8 atomic_fcmpset_acq_char
|
||||
#define atomic_fcmpset_rel_8 atomic_fcmpset_rel_char
|
||||
|
||||
/* Operations on 16-bit words. */
|
||||
#define atomic_set_16 atomic_set_short
|
||||
@ -592,6 +588,12 @@ u_long atomic_swap_long(volatile u_long *p, u_long v);
|
||||
#define atomic_subtract_rel_16 atomic_subtract_rel_short
|
||||
#define atomic_load_acq_16 atomic_load_acq_short
|
||||
#define atomic_store_rel_16 atomic_store_rel_short
|
||||
#define atomic_cmpset_16 atomic_cmpset_short
|
||||
#define atomic_cmpset_acq_16 atomic_cmpset_acq_short
|
||||
#define atomic_cmpset_rel_16 atomic_cmpset_rel_short
|
||||
#define atomic_fcmpset_16 atomic_fcmpset_short
|
||||
#define atomic_fcmpset_acq_16 atomic_fcmpset_acq_short
|
||||
#define atomic_fcmpset_rel_16 atomic_fcmpset_rel_short
|
||||
|
||||
/* Operations on 32-bit double words. */
|
||||
#define atomic_set_32 atomic_set_int
|
||||
|
@ -105,7 +105,12 @@ __mbu(void)
|
||||
void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v); \
|
||||
void atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v)
|
||||
|
||||
int atomic_cmpset_char(volatile u_char *dst, u_char expect, u_char src);
|
||||
int atomic_cmpset_short(volatile u_short *dst, u_short expect, u_short src);
|
||||
int atomic_cmpset_int(volatile u_int *dst, u_int expect, u_int src);
|
||||
int atomic_fcmpset_char(volatile u_char *dst, u_char *expect, u_char src);
|
||||
int atomic_fcmpset_short(volatile u_short *dst, u_short *expect,
|
||||
u_short src);
|
||||
int atomic_fcmpset_int(volatile u_int *dst, u_int *expect, u_int src);
|
||||
u_int atomic_fetchadd_int(volatile u_int *p, u_int v);
|
||||
int atomic_testandset_int(volatile u_int *p, u_int v);
|
||||
@ -163,48 +168,60 @@ atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
|
||||
struct __hack
|
||||
|
||||
/*
|
||||
* Atomic compare and set, used by the mutex functions
|
||||
* Atomic compare and set, used by the mutex functions.
|
||||
*
|
||||
* if (*dst == expect) *dst = src (all 32 bit words)
|
||||
* cmpset:
|
||||
* if (*dst == expect)
|
||||
* *dst = src
|
||||
*
|
||||
* Returns 0 on failure, non-zero on success
|
||||
* fcmpset:
|
||||
* if (*dst == *expect)
|
||||
* *dst = src
|
||||
* else
|
||||
* *expect = *dst
|
||||
*
|
||||
* Returns 0 on failure, non-zero on success.
|
||||
*/
|
||||
|
||||
static __inline int
|
||||
atomic_cmpset_int(volatile u_int *dst, u_int expect, u_int src)
|
||||
{
|
||||
u_char res;
|
||||
|
||||
__asm __volatile(
|
||||
" " MPLOCKED " "
|
||||
" cmpxchgl %3,%1 ; "
|
||||
" sete %0 ; "
|
||||
"# atomic_cmpset_int"
|
||||
: "=q" (res), /* 0 */
|
||||
"+m" (*dst), /* 1 */
|
||||
"+a" (expect) /* 2 */
|
||||
: "r" (src) /* 3 */
|
||||
: "memory", "cc");
|
||||
return (res);
|
||||
#define ATOMIC_CMPSET(TYPE) \
|
||||
static __inline int \
|
||||
atomic_cmpset_##TYPE(volatile u_##TYPE *dst, u_##TYPE expect, u_##TYPE src) \
|
||||
{ \
|
||||
u_char res; \
|
||||
\
|
||||
__asm __volatile( \
|
||||
" " MPLOCKED " " \
|
||||
" cmpxchg %3,%1 ; " \
|
||||
" sete %0 ; " \
|
||||
"# atomic_cmpset_" #TYPE " " \
|
||||
: "=q" (res), /* 0 */ \
|
||||
"+m" (*dst), /* 1 */ \
|
||||
"+a" (expect) /* 2 */ \
|
||||
: "r" (src) /* 3 */ \
|
||||
: "memory", "cc"); \
|
||||
return (res); \
|
||||
} \
|
||||
\
|
||||
static __inline int \
|
||||
atomic_fcmpset_##TYPE(volatile u_##TYPE *dst, u_##TYPE *expect, u_##TYPE src) \
|
||||
{ \
|
||||
u_char res; \
|
||||
\
|
||||
__asm __volatile( \
|
||||
" " MPLOCKED " " \
|
||||
" cmpxchg %3,%1 ; " \
|
||||
" sete %0 ; " \
|
||||
"# atomic_fcmpset_" #TYPE " " \
|
||||
: "=q" (res), /* 0 */ \
|
||||
"+m" (*dst), /* 1 */ \
|
||||
"+a" (*expect) /* 2 */ \
|
||||
: "r" (src) /* 3 */ \
|
||||
: "memory", "cc"); \
|
||||
return (res); \
|
||||
}
|
||||
|
||||
static __inline int
|
||||
atomic_fcmpset_int(volatile u_int *dst, u_int *expect, u_int src)
|
||||
{
|
||||
u_char res;
|
||||
|
||||
__asm __volatile(
|
||||
" " MPLOCKED " "
|
||||
" cmpxchgl %3,%1 ; "
|
||||
" sete %0 ; "
|
||||
"# atomic_cmpset_int"
|
||||
: "=q" (res), /* 0 */
|
||||
"+m" (*dst), /* 1 */
|
||||
"+a" (*expect) /* 2 */
|
||||
: "r" (src) /* 3 */
|
||||
: "memory", "cc");
|
||||
return (res);
|
||||
}
|
||||
ATOMIC_CMPSET(char);
|
||||
ATOMIC_CMPSET(short);
|
||||
ATOMIC_CMPSET(int);
|
||||
|
||||
/*
|
||||
* Atomically add the value of v to the integer pointed to by p and return
|
||||
@ -654,6 +671,10 @@ u_long atomic_swap_long(volatile u_long *p, u_long v);
|
||||
#define atomic_add_rel_char atomic_add_barr_char
|
||||
#define atomic_subtract_acq_char atomic_subtract_barr_char
|
||||
#define atomic_subtract_rel_char atomic_subtract_barr_char
|
||||
#define atomic_cmpset_acq_char atomic_cmpset_char
|
||||
#define atomic_cmpset_rel_char atomic_cmpset_char
|
||||
#define atomic_fcmpset_acq_char atomic_fcmpset_char
|
||||
#define atomic_fcmpset_rel_char atomic_fcmpset_char
|
||||
|
||||
#define atomic_set_acq_short atomic_set_barr_short
|
||||
#define atomic_set_rel_short atomic_set_barr_short
|
||||
@ -663,6 +684,10 @@ u_long atomic_swap_long(volatile u_long *p, u_long v);
|
||||
#define atomic_add_rel_short atomic_add_barr_short
|
||||
#define atomic_subtract_acq_short atomic_subtract_barr_short
|
||||
#define atomic_subtract_rel_short atomic_subtract_barr_short
|
||||
#define atomic_cmpset_acq_short atomic_cmpset_short
|
||||
#define atomic_cmpset_rel_short atomic_cmpset_short
|
||||
#define atomic_fcmpset_acq_short atomic_fcmpset_short
|
||||
#define atomic_fcmpset_rel_short atomic_fcmpset_short
|
||||
|
||||
#define atomic_set_acq_int atomic_set_barr_int
|
||||
#define atomic_set_rel_int atomic_set_barr_int
|
||||
@ -708,6 +733,12 @@ u_long atomic_swap_long(volatile u_long *p, u_long v);
|
||||
#define atomic_subtract_rel_8 atomic_subtract_rel_char
|
||||
#define atomic_load_acq_8 atomic_load_acq_char
|
||||
#define atomic_store_rel_8 atomic_store_rel_char
|
||||
#define atomic_cmpset_8 atomic_cmpset_char
|
||||
#define atomic_cmpset_acq_8 atomic_cmpset_acq_char
|
||||
#define atomic_cmpset_rel_8 atomic_cmpset_rel_char
|
||||
#define atomic_fcmpset_8 atomic_fcmpset_char
|
||||
#define atomic_fcmpset_acq_8 atomic_fcmpset_acq_char
|
||||
#define atomic_fcmpset_rel_8 atomic_fcmpset_rel_char
|
||||
|
||||
/* Operations on 16-bit words. */
|
||||
#define atomic_set_16 atomic_set_short
|
||||
@ -724,6 +755,12 @@ u_long atomic_swap_long(volatile u_long *p, u_long v);
|
||||
#define atomic_subtract_rel_16 atomic_subtract_rel_short
|
||||
#define atomic_load_acq_16 atomic_load_acq_short
|
||||
#define atomic_store_rel_16 atomic_store_rel_short
|
||||
#define atomic_cmpset_16 atomic_cmpset_short
|
||||
#define atomic_cmpset_acq_16 atomic_cmpset_acq_short
|
||||
#define atomic_cmpset_rel_16 atomic_cmpset_rel_short
|
||||
#define atomic_fcmpset_16 atomic_fcmpset_short
|
||||
#define atomic_fcmpset_acq_16 atomic_fcmpset_acq_short
|
||||
#define atomic_fcmpset_rel_16 atomic_fcmpset_rel_short
|
||||
|
||||
/* Operations on 32-bit double words. */
|
||||
#define atomic_set_32 atomic_set_int
|
||||
|
Loading…
Reference in New Issue
Block a user