diff mbox series

[RFC] average: rewrite for clearity

Message ID 20230421130022.191045-1-benjamin.beichler@uni-rostock.de
State New
Headers show
Series [RFC] average: rewrite for clearity | expand

Commit Message

Benjamin Beichler April 21, 2023, 1 p.m. UTC
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, altough 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.

Also fix some formatting issues.

Signed-off-by: Benjamin Beichler <benjamin.beichler@uni-rostock.de>
---
 include/linux/average.h | 98 ++++++++++++++++++++++++-----------------
 1 file changed, 57 insertions(+), 41 deletions(-)
diff mbox series

Patch

diff --git a/include/linux/average.h b/include/linux/average.h
index a1a8f09631ce..2e70224b84a8 100644
--- a/include/linux/average.h
+++ b/include/linux/average.h
@@ -25,47 +25,63 @@ 
  * 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)	\
-	{								\
-		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));				\
+#define EWMA_BUILD_TIME_CHECKS(_precision, _weight_rcp)                        \
+		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);		
+
+
+#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 */