diff mbox series

[RFC] average: rewrite for clearity

Message ID 20230421130022.191045-1-benjamin.beichler@uni-rostock.de (mailing list archive)
State RFC
Delegated to: Johannes Berg
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(-)

Comments

Benjamin Beichler April 21, 2023, 1:06 p.m. UTC | #1
Sorry for the crappy formatting of line endings, I have some tab/space 
issues with my editor, I will fix this ...

Am 21.04.2023 um 15:00 schrieb Benjamin Beichler:
> 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 --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 */
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 */