diff options
author | phk <phk@FreeBSD.org> | 2000-09-06 11:21:14 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2000-09-06 11:21:14 +0000 |
commit | 6c07bccbf798848cb394146e35ef94c64121accd (patch) | |
tree | bb9380dc43e99fb9dd5abf7fdae1d22ac81d97c1 /sys/amd64/include/atomic.h | |
parent | 75d7416f31678a75fbee4c150d761d197d6809da (diff) | |
download | FreeBSD-src-6c07bccbf798848cb394146e35ef94c64121accd.zip FreeBSD-src-6c07bccbf798848cb394146e35ef94c64121accd.tar.gz |
Introduce atomic_cmpset_int() and atomic_cmpset_long() from SMPng a
few hours earlier than the rest.
The next DEVFS commit needs these functions.
Alpha versions by: dfr
i386 versions by: jakeb
Approved by: SMPng
Diffstat (limited to 'sys/amd64/include/atomic.h')
-rw-r--r-- | sys/amd64/include/atomic.h | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/sys/amd64/include/atomic.h b/sys/amd64/include/atomic.h index e6af303..35a710e 100644 --- a/sys/amd64/include/atomic.h +++ b/sys/amd64/include/atomic.h @@ -65,9 +65,15 @@ #define ATOMIC_ASM(NAME, TYPE, OP, V) \ extern void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v); +extern int atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src); + #else /* !KLD_MODULE */ #if defined(SMP) +#if defined(LOCORE) +#define MPLOCKED lock ; +#else #define MPLOCKED "lock ; " +#endif #else #define MPLOCKED #endif @@ -87,6 +93,62 @@ atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\ : "0" (*p), "ir" (V)); \ } +/* + * Atomic compare and set, used by the mutex functions + * + * if (*dst == exp) *dst = src (all 32 bit words) + * + * Returns 0 on failure, non-zero on success + */ + +#if defined(I386_CPU) +static __inline int +atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src) +{ + int res = exp; + + __asm __volatile( + " pushfl ; " + " cli ; " + " cmpl %1,%3 ; " + " jne 1f ; " + " movl %2,%3 ; " + "1: " + " sete %%al; " + " movzbl %%al,%0 ; " + " popfl ; " + "# atomic_cmpset_int" + : "=a" (res) /* 0 (result) */ + : "0" (exp), /* 1 */ + "r" (src), /* 2 */ + "m" (*(dst)) /* 3 */ + : "memory"); + + return (res); +} +#else /* defined(I386_CPU) */ +static __inline int +atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src) +{ + int res = exp; + + __asm __volatile ( + " " MPLOCKED " " + " cmpxchgl %2,%3 ; " + " setz %%al ; " + " movzbl %%al,%0 ; " + "1: " + "# atomic_cmpset_int" + : "=a" (res) /* 0 (result) */ + : "0" (exp), /* 1 */ + "r" (src), /* 2 */ + "m" (*(dst)) /* 3 */ + : "memory"); + + return (res); +} +#endif /* defined(I386_CPU) */ + #else /* gcc <= 2.8 version */ #define ATOMIC_ASM(NAME, TYPE, OP, V) \ @@ -148,4 +210,14 @@ ATOMIC_ASM(subtract, long, "subl %1,%0", v) #endif +#ifndef WANT_FUNCTIONS +static __inline int +atomic_cmpset_ptr(volatile void *dst, void *exp, void *src) +{ + + return ( + atomic_cmpset_int((volatile u_int *)dst, (u_int)exp, (u_int)src)); +} +#endif + #endif /* ! _MACHINE_ATOMIC_H_ */ |