summaryrefslogtreecommitdiffstats
path: root/sys/amd64/include/atomic.h
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2000-09-06 11:21:14 +0000
committerphk <phk@FreeBSD.org>2000-09-06 11:21:14 +0000
commit6c07bccbf798848cb394146e35ef94c64121accd (patch)
treebb9380dc43e99fb9dd5abf7fdae1d22ac81d97c1 /sys/amd64/include/atomic.h
parent75d7416f31678a75fbee4c150d761d197d6809da (diff)
downloadFreeBSD-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.h72
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_ */
OpenPOWER on IntegriCloud