Search Linux Wireless

[RFC v2] average: rewrite for clearity

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Move the former *_add function with its implicit initialization into a
separate function, when the user explicitly wants to init with the first
added value, although this creates issues, when 0 is a expected value for
the internal value.

Add a separate init function with value parameter to allow init with
distinct value, which was formerly done by the implicit init of old
*_add function.

Move the compile time checks into a separate macro, as they are used
multiple times and noise up the functions.

Signed-off-by: Benjamin Beichler <benjamin.beichler@xxxxxxxxxxxxxx>
---
 include/linux/average.h | 86 ++++++++++++++++++++++++-----------------
 1 file changed, 50 insertions(+), 36 deletions(-)

diff --git a/include/linux/average.h b/include/linux/average.h
index a1a8f09631ce..7149a9ee555a 100644
--- a/include/linux/average.h
+++ b/include/linux/average.h
@@ -25,47 +25,61 @@
  * that this parameter must be a power of two for efficiency.
  */
 
-#define DECLARE_EWMA(name, _precision, _weight_rcp)			\
-	struct ewma_##name {						\
-		unsigned long internal;					\
-	};								\
-	static inline void ewma_##name##_init(struct ewma_##name *e)	\
-	{								\
+#define EWMA_BUILD_TIME_CHECKS(_precision, _weight_rcp)			\
+	do {								\
 		BUILD_BUG_ON(!__builtin_constant_p(_precision));	\
 		BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp));	\
-		/*							\
-		 * Even if you want to feed it just 0/1 you should have	\
-		 * some bits for the non-fractional part...		\
-		 */							\
-		BUILD_BUG_ON((_precision) > 30);			\
-		BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp);		\
-		e->internal = 0;					\
-	}								\
-	static inline unsigned long					\
-	ewma_##name##_read(struct ewma_##name *e)			\
-	{								\
-		BUILD_BUG_ON(!__builtin_constant_p(_precision));	\
-		BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp));	\
-		BUILD_BUG_ON((_precision) > 30);			\
-		BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp);		\
-		return e->internal >> (_precision);			\
-	}								\
-	static inline void ewma_##name##_add(struct ewma_##name *e,	\
-					     unsigned long val)		\
-	{								\
-		unsigned long internal = READ_ONCE(e->internal);	\
-		unsigned long weight_rcp = ilog2(_weight_rcp);		\
-		unsigned long precision = _precision;			\
 									\
-		BUILD_BUG_ON(!__builtin_constant_p(_precision));	\
-		BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp));	\
 		BUILD_BUG_ON((_precision) > 30);			\
 		BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp);		\
-									\
-		WRITE_ONCE(e->internal, internal ?			\
-			(((internal << weight_rcp) - internal) +	\
-				(val << precision)) >> weight_rcp :	\
-			(val << precision));				\
+	} while (0)
+
+#define DECLARE_EWMA(name, _precision, _weight_rcp)				\
+	struct ewma_##name {							\
+		unsigned long internal;						\
+	};									\
+	static inline void ewma_##name##_init_val(struct ewma_##name *e,	\
+						  unsigned long init)		\
+	{									\
+		EWMA_BUILD_TIME_CHECKS(_precision, _weight_rcp)			\
+		e->internal = init << _precision;				\
+	}									\
+	static inline void ewma_##name##_init(struct ewma_##name *e)		\
+	{									\
+			ewma_##name##_init_val(e, 0);				\
+	}									\
+	static inline unsigned long						\
+	ewma_##name##_read(struct ewma_##name *e)				\
+	{									\
+		EWMA_BUILD_TIME_CHECKS(_precision, _weight_rcp)			\
+		return e->internal >> (_precision);				\
+	}									\
+	static inline void ewma_##name##_add(struct ewma_##name *e,		\
+					     unsigned long val)			\
+	{									\
+		unsigned long internal = READ_ONCE(e->internal);		\
+		unsigned long weight_rcp = ilog2(_weight_rcp);			\
+		unsigned long precision = _precision;				\
+										\
+		EWMA_BUILD_TIME_CHECKS(_precision, _weight_rcp)			\
+										\
+		WRITE_ONCE(e->internal,						\
+			(((internal << weight_rcp) - internal) +		\
+				(val << precision)) >> weight_rcp);		\
+	}									\
+	static inline void ewma_##name##_add_or_init(struct ewma_##name *e,	\
+					     unsigned long val)			\
+	{									\
+		unsigned long internal = READ_ONCE(e->internal);		\
+		unsigned long weight_rcp = ilog2(_weight_rcp);			\
+		unsigned long precision = _precision;				\
+										\
+		EWMA_BUILD_TIME_CHECKS(_precision, _weight_rcp)			\
+										\
+		WRITE_ONCE(e->internal, internal ?				\
+			(((internal << weight_rcp) - internal) +		\
+				(val << precision)) >> weight_rcp :		\
+			(val << precision));					\
 	}
 
 #endif /* _LINUX_AVERAGE_H */
-- 
2.25.1



[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux