Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/include/atomic.h
Show First 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | |||||
* atomic_set_long(P, V) (*(u_long *)(P) |= (V)) | * atomic_set_long(P, V) (*(u_long *)(P) |= (V)) | ||||
* atomic_clear_long(P, V) (*(u_long *)(P) &= ~(V)) | * atomic_clear_long(P, V) (*(u_long *)(P) &= ~(V)) | ||||
* atomic_add_long(P, V) (*(u_long *)(P) += (V)) | * atomic_add_long(P, V) (*(u_long *)(P) += (V)) | ||||
* atomic_subtract_long(P, V) (*(u_long *)(P) -= (V)) | * atomic_subtract_long(P, V) (*(u_long *)(P) -= (V)) | ||||
* atomic_swap_long(P, V) (return (*(u_long *)(P)); *(u_long *)(P) = (V);) | * atomic_swap_long(P, V) (return (*(u_long *)(P)); *(u_long *)(P) = (V);) | ||||
* atomic_readandclear_long(P) (return (*(u_long *)(P)); *(u_long *)(P) = 0;) | * atomic_readandclear_long(P) (return (*(u_long *)(P)); *(u_long *)(P) = 0;) | ||||
*/ | */ | ||||
#if !defined(__GNUCLIKE_ASM) | |||||
#define ATOMIC_ASM(NAME, TYPE, OP, CONS, V) \ | |||||
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); | |||||
u_long atomic_fetchadd_long(volatile u_long *p, u_long v); | |||||
int atomic_testandset_int(volatile u_int *p, u_int v); | |||||
int atomic_testandset_long(volatile u_long *p, u_int v); | |||||
int atomic_testandclear_int(volatile u_int *p, u_int v); | |||||
int atomic_testandclear_long(volatile u_long *p, u_int v); | |||||
void atomic_thread_fence_acq(void); | |||||
void atomic_thread_fence_acq_rel(void); | |||||
void atomic_thread_fence_rel(void); | |||||
void atomic_thread_fence_seq_cst(void); | |||||
#define ATOMIC_LOAD(TYPE) \ | |||||
u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p) | |||||
#define ATOMIC_STORE(TYPE) \ | |||||
void atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v) | |||||
#else /* !__GNUCLIKE_ASM */ | |||||
/* | /* | ||||
* Always use lock prefixes. The result is slighly less optimal for | * Always use lock prefixes. The result is slighly less optimal for | ||||
* UP systems, but it matters less now, and sometimes UP is emulated | * UP systems, but it matters less now, and sometimes UP is emulated | ||||
* over SMP. | * over SMP. | ||||
* | * | ||||
* The assembly is volatilized to avoid code chunk removal by the compiler. | * The assembly is volatilized to avoid code chunk removal by the compiler. | ||||
* GCC aggressively reorders operations and memory clobbering is necessary | * GCC aggressively reorders operations and memory clobbering is necessary | ||||
* in order to avoid that for memory barriers. | * in order to avoid that for memory barriers. | ||||
▲ Show 20 Lines • Show All 235 Lines • ▼ Show 20 Lines | |||||
static __inline void | static __inline void | ||||
atomic_thread_fence_seq_cst(void) | atomic_thread_fence_seq_cst(void) | ||||
{ | { | ||||
__storeload_barrier(); | __storeload_barrier(); | ||||
} | } | ||||
#endif /* !__GNUCLIKE_ASM */ | |||||
ATOMIC_ASM(set, char, "orb %b1,%0", "iq", v); | ATOMIC_ASM(set, char, "orb %b1,%0", "iq", v); | ||||
ATOMIC_ASM(clear, char, "andb %b1,%0", "iq", ~v); | ATOMIC_ASM(clear, char, "andb %b1,%0", "iq", ~v); | ||||
ATOMIC_ASM(add, char, "addb %b1,%0", "iq", v); | ATOMIC_ASM(add, char, "addb %b1,%0", "iq", v); | ||||
ATOMIC_ASM(subtract, char, "subb %b1,%0", "iq", v); | ATOMIC_ASM(subtract, char, "subb %b1,%0", "iq", v); | ||||
ATOMIC_ASM(set, short, "orw %w1,%0", "ir", v); | ATOMIC_ASM(set, short, "orw %w1,%0", "ir", v); | ||||
ATOMIC_ASM(clear, short, "andw %w1,%0", "ir", ~v); | ATOMIC_ASM(clear, short, "andw %w1,%0", "ir", ~v); | ||||
ATOMIC_ASM(add, short, "addw %w1,%0", "ir", v); | ATOMIC_ASM(add, short, "addw %w1,%0", "ir", v); | ||||
Show All 20 Lines | |||||
#undef ATOMIC_ASM | #undef ATOMIC_ASM | ||||
#undef ATOMIC_LOAD | #undef ATOMIC_LOAD | ||||
#undef ATOMIC_STORE | #undef ATOMIC_STORE | ||||
#undef ATOMIC_LOADSTORE | #undef ATOMIC_LOADSTORE | ||||
#ifndef WANT_FUNCTIONS | #ifndef WANT_FUNCTIONS | ||||
/* Read the current value and store a new value in the destination. */ | /* Read the current value and store a new value in the destination. */ | ||||
#ifdef __GNUCLIKE_ASM | |||||
static __inline u_int | static __inline u_int | ||||
atomic_swap_int(volatile u_int *p, u_int v) | atomic_swap_int(volatile u_int *p, u_int v) | ||||
{ | { | ||||
__asm __volatile( | __asm __volatile( | ||||
" xchgl %1,%0 ; " | " xchgl %1,%0 ; " | ||||
"# atomic_swap_int" | "# atomic_swap_int" | ||||
: "+r" (v), /* 0 */ | : "+r" (v), /* 0 */ | ||||
"+m" (*p)); /* 1 */ | "+m" (*p)); /* 1 */ | ||||
return (v); | return (v); | ||||
} | } | ||||
static __inline u_long | static __inline u_long | ||||
atomic_swap_long(volatile u_long *p, u_long v) | atomic_swap_long(volatile u_long *p, u_long v) | ||||
{ | { | ||||
__asm __volatile( | __asm __volatile( | ||||
" xchgq %1,%0 ; " | " xchgq %1,%0 ; " | ||||
"# atomic_swap_long" | "# atomic_swap_long" | ||||
: "+r" (v), /* 0 */ | : "+r" (v), /* 0 */ | ||||
"+m" (*p)); /* 1 */ | "+m" (*p)); /* 1 */ | ||||
return (v); | return (v); | ||||
} | } | ||||
#else /* !__GNUCLIKE_ASM */ | |||||
u_int atomic_swap_int(volatile u_int *p, u_int v); | |||||
u_long atomic_swap_long(volatile u_long *p, u_long v); | |||||
#endif /* __GNUCLIKE_ASM */ | |||||
#define atomic_set_acq_char atomic_set_barr_char | #define atomic_set_acq_char atomic_set_barr_char | ||||
#define atomic_set_rel_char atomic_set_barr_char | #define atomic_set_rel_char atomic_set_barr_char | ||||
#define atomic_clear_acq_char atomic_clear_barr_char | #define atomic_clear_acq_char atomic_clear_barr_char | ||||
#define atomic_clear_rel_char atomic_clear_barr_char | #define atomic_clear_rel_char atomic_clear_barr_char | ||||
#define atomic_add_acq_char atomic_add_barr_char | #define atomic_add_acq_char atomic_add_barr_char | ||||
#define atomic_add_rel_char atomic_add_barr_char | #define atomic_add_rel_char atomic_add_barr_char | ||||
#define atomic_subtract_acq_char atomic_subtract_barr_char | #define atomic_subtract_acq_char atomic_subtract_barr_char | ||||
▲ Show 20 Lines • Show All 176 Lines • Show Last 20 Lines |