[patch] hwpmc [1/13]

Aggelos Economopoulos aoiko at cc.ece.ntua.gr
Sat Nov 24 13:17:45 PST 2007


Bring in some atomic primitives. Required for hwpmc.

Obtained-from: FreeBSD

Index: cpu/i386/include/atomic.h
===================================================================
retrieving revision 1.23
diff -u -p -r1.23 atomic.h
--- cpu/i386/include/atomic.h
+++ cpu/i386/include/atomic.h
@@ -70,6 +70,9 @@
 #define ATOMIC_ASM(NAME, TYPE, OP, V)			\
 	extern void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v); \
 	extern void atomic_##NAME##_##TYPE##_nonlocked(volatile u_##TYPE *p, u_##TYPE v);
+#define	ATOMIC_STORE_LOAD(TYPE, LOP, SOP)			\
+u_##TYPE	atomic_load_acq_##TYPE(volatile u_##TYPE *p);	\
+void		atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)
 #else /* !KLD_MODULE */
 #if defined(SMP) || !defined(_KERNEL)
 #define MPLOCKED	"lock ; "
@@ -107,6 +110,61 @@ atomic_##NAME##_##TYPE##_nonlocked(volat
 			 : "iq" (V)); 			\
 }
 
+#if defined(_KERNEL) && !defined(SMP)
+
+/*
+ * We assume that a = b will do atomic loads and stores.  However, on a
+ * PentiumPro or higher, reads may pass writes, so for that case we have
+ * to use a serializing instruction (i.e. with LOCK) to do the load in
+ * SMP kernels.  For UP kernels, however, the cache of the single processor
+ * is always consistent, so we don't need any memory barriers.
+ */
+#define	ATOMIC_STORE_LOAD(TYPE, LOP, SOP)		\
+static __inline u_##TYPE				\
+atomic_load_acq_##TYPE(volatile u_##TYPE *p)		\
+{							\
+	return (*p);					\
+}							\
+							\
+static __inline void					\
+atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
+{							\
+	*p = v;						\
+}							\
+struct __hack
+
+#else /* !(_KERNEL && !SMP) */
+
+#define	ATOMIC_STORE_LOAD(TYPE, LOP, SOP)		\
+static __inline u_##TYPE				\
+atomic_load_acq_##TYPE(volatile u_##TYPE *p)		\
+{							\
+	u_##TYPE res;					\
+							\
+	__asm __volatile(MPLOCKED LOP			\
+	: "=a" (res),			/* 0 */		\
+	  "=m" (*p)			/* 1 */		\
+	: "m" (*p)			/* 2 */		\
+	: "memory");					\
+							\
+	return (res);					\
+}							\
+							\
+/*							\
+ * The XCHG instruction asserts LOCK automagically.	\
+ */							\
+static __inline void					\
+atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
+{							\
+	__asm __volatile(SOP				\
+	: "=m" (*p),			/* 0 */		\
+	  "+r" (v)			/* 1 */		\
+	: "m" (*p));			/* 2 */		\
+}							\
+struct __hack
+
+#endif /* _KERNEL && !SMP */
+
 #endif /* KLD_MODULE */
 
 /* egcs 1.1.2+ version */
@@ -130,6 +188,14 @@ ATOMIC_ASM(clear,    long,  "andl %1,%0"
 ATOMIC_ASM(add,	     long,  "addl %1,%0",  v)
 ATOMIC_ASM(subtract, long,  "subl %1,%0",  v)
 
+ATOMIC_STORE_LOAD(char,	"cmpxchgb %b0,%1", "xchgb %b1,%0");
+ATOMIC_STORE_LOAD(short,"cmpxchgw %w0,%1", "xchgw %w1,%0");
+ATOMIC_STORE_LOAD(int,	"cmpxchgl %0,%1",  "xchgl %1,%0");
+ATOMIC_STORE_LOAD(long,	"cmpxchgl %0,%1",  "xchgl %1,%0");
+
+#undef ATOMIC_ASM
+#undef ATOMIC_STORE_LOAD
+
 /*
  * atomic_poll_acquire_int(P)	Returns non-zero on success, 0 if the lock
  *				has already been acquired.
@@ -367,4 +433,138 @@ atomic_cmpset_int(volatile u_int *_dst, 
 }
 #endif	/* KLD_MODULE */
 
+/* Acquire and release variants are identical to the normal ones. */
+#define	atomic_set_acq_char		atomic_set_char
+#define	atomic_set_rel_char		atomic_set_char
+#define	atomic_clear_acq_char		atomic_clear_char
+#define	atomic_clear_rel_char		atomic_clear_char
+#define	atomic_add_acq_char		atomic_add_char
+#define	atomic_add_rel_char		atomic_add_char
+#define	atomic_subtract_acq_char	atomic_subtract_char
+#define	atomic_subtract_rel_char	atomic_subtract_char
+
+#define	atomic_set_acq_short		atomic_set_short
+#define	atomic_set_rel_short		atomic_set_short
+#define	atomic_clear_acq_short		atomic_clear_short
+#define	atomic_clear_rel_short		atomic_clear_short
+#define	atomic_add_acq_short		atomic_add_short
+#define	atomic_add_rel_short		atomic_add_short
+#define	atomic_subtract_acq_short	atomic_subtract_short
+#define	atomic_subtract_rel_short	atomic_subtract_short
+
+#define	atomic_set_acq_int		atomic_set_int
+#define	atomic_set_rel_int		atomic_set_int
+#define	atomic_clear_acq_int		atomic_clear_int
+#define	atomic_clear_rel_int		atomic_clear_int
+#define	atomic_add_acq_int		atomic_add_int
+#define	atomic_add_rel_int		atomic_add_int
+#define	atomic_subtract_acq_int		atomic_subtract_int
+#define	atomic_subtract_rel_int		atomic_subtract_int
+#define	atomic_cmpset_acq_int		atomic_cmpset_int
+#define	atomic_cmpset_rel_int		atomic_cmpset_int
+
+#define	atomic_set_acq_long		atomic_set_long
+#define	atomic_set_rel_long		atomic_set_long
+#define	atomic_clear_acq_long		atomic_clear_long
+#define	atomic_clear_rel_long		atomic_clear_long
+#define	atomic_add_acq_long		atomic_add_long
+#define	atomic_add_rel_long		atomic_add_long
+#define	atomic_subtract_acq_long	atomic_subtract_long
+#define	atomic_subtract_rel_long	atomic_subtract_long
+#define	atomic_cmpset_acq_long		atomic_cmpset_long
+#define	atomic_cmpset_rel_long		atomic_cmpset_long
+
+/* Operations on 8-bit bytes. */
+#define	atomic_set_8		atomic_set_char
+#define	atomic_set_acq_8	atomic_set_acq_char
+#define	atomic_set_rel_8	atomic_set_rel_char
+#define	atomic_clear_8		atomic_clear_char
+#define	atomic_clear_acq_8	atomic_clear_acq_char
+#define	atomic_clear_rel_8	atomic_clear_rel_char
+#define	atomic_add_8		atomic_add_char
+#define	atomic_add_acq_8	atomic_add_acq_char
+#define	atomic_add_rel_8	atomic_add_rel_char
+#define	atomic_subtract_8	atomic_subtract_char
+#define	atomic_subtract_acq_8	atomic_subtract_acq_char
+#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
+
+/* Operations on 16-bit words. */
+#define	atomic_set_16		atomic_set_short
+#define	atomic_set_acq_16	atomic_set_acq_short
+#define	atomic_set_rel_16	atomic_set_rel_short
+#define	atomic_clear_16		atomic_clear_short
+#define	atomic_clear_acq_16	atomic_clear_acq_short
+#define	atomic_clear_rel_16	atomic_clear_rel_short
+#define	atomic_add_16		atomic_add_short
+#define	atomic_add_acq_16	atomic_add_acq_short
+#define	atomic_add_rel_16	atomic_add_rel_short
+#define	atomic_subtract_16	atomic_subtract_short
+#define	atomic_subtract_acq_16	atomic_subtract_acq_short
+#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
+
+/* Operations on 32-bit double words. */
+#define	atomic_set_32		atomic_set_int
+#define	atomic_set_acq_32	atomic_set_acq_int
+#define	atomic_set_rel_32	atomic_set_rel_int
+#define	atomic_clear_32		atomic_clear_int
+#define	atomic_clear_acq_32	atomic_clear_acq_int
+#define	atomic_clear_rel_32	atomic_clear_rel_int
+#define	atomic_add_32		atomic_add_int
+#define	atomic_add_acq_32	atomic_add_acq_int
+#define	atomic_add_rel_32	atomic_add_rel_int
+#define	atomic_subtract_32	atomic_subtract_int
+#define	atomic_subtract_acq_32	atomic_subtract_acq_int
+#define	atomic_subtract_rel_32	atomic_subtract_rel_int
+#define	atomic_load_acq_32	atomic_load_acq_int
+#define	atomic_store_rel_32	atomic_store_rel_int
+#define	atomic_cmpset_32	atomic_cmpset_int
+#define	atomic_cmpset_acq_32	atomic_cmpset_acq_int
+#define	atomic_cmpset_rel_32	atomic_cmpset_rel_int
+#define	atomic_readandclear_32	atomic_readandclear_int
+#define	atomic_fetchadd_32	atomic_fetchadd_int
+
+/* Operations on pointers. */
+#define	atomic_set_ptr(p, v) \
+	atomic_set_int((volatile u_int *)(p), (u_int)(v))
+#define	atomic_set_acq_ptr(p, v) \
+	atomic_set_acq_int((volatile u_int *)(p), (u_int)(v))
+#define	atomic_set_rel_ptr(p, v) \
+	atomic_set_rel_int((volatile u_int *)(p), (u_int)(v))
+#define	atomic_clear_ptr(p, v) \
+	atomic_clear_int((volatile u_int *)(p), (u_int)(v))
+#define	atomic_clear_acq_ptr(p, v) \
+	atomic_clear_acq_int((volatile u_int *)(p), (u_int)(v))
+#define	atomic_clear_rel_ptr(p, v) \
+	atomic_clear_rel_int((volatile u_int *)(p), (u_int)(v))
+#define	atomic_add_ptr(p, v) \
+	atomic_add_int((volatile u_int *)(p), (u_int)(v))
+#define	atomic_add_acq_ptr(p, v) \
+	atomic_add_acq_int((volatile u_int *)(p), (u_int)(v))
+#define	atomic_add_rel_ptr(p, v) \
+	atomic_add_rel_int((volatile u_int *)(p), (u_int)(v))
+#define	atomic_subtract_ptr(p, v) \
+	atomic_subtract_int((volatile u_int *)(p), (u_int)(v))
+#define	atomic_subtract_acq_ptr(p, v) \
+	atomic_subtract_acq_int((volatile u_int *)(p), (u_int)(v))
+#define	atomic_subtract_rel_ptr(p, v) \
+	atomic_subtract_rel_int((volatile u_int *)(p), (u_int)(v))
+#define	atomic_load_acq_ptr(p) \
+	atomic_load_acq_int((volatile u_int *)(p))
+#define	atomic_store_rel_ptr(p, v) \
+	atomic_store_rel_int((volatile u_int *)(p), (v))
+#define	atomic_cmpset_ptr(dst, old, new) \
+	atomic_cmpset_int((volatile u_int *)(dst), (u_int)(old), (u_int)(new))
+#define	atomic_cmpset_acq_ptr(dst, old, new) \
+	atomic_cmpset_acq_int((volatile u_int *)(dst), (u_int)(old), \
+	    (u_int)(new))
+#define	atomic_cmpset_rel_ptr(dst, old, new) \
+	atomic_cmpset_rel_int((volatile u_int *)(dst), (u_int)(old), \
+	    (u_int)(new))
+#define	atomic_readandclear_ptr(p) \
+	atomic_readandclear_int((volatile u_int *)(p))
+
 #endif /* ! _CPU_ATOMIC_H_ */





More information about the Submit mailing list