Search Linux Wireless

Re: [RFC] average: rewrite for clearity

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

 



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@xxxxxxxxxxxxxx>
---
  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 */


--
M.Sc. Benjamin Beichler

Universität Rostock, Fakultät für Informatik und Elektrotechnik
Institut für Angewandte Mikroelektronik und Datentechnik

University of Rostock, Department of CS and EE
Institute of Applied Microelectronics and CE

Albert-Einstein-Str. 26
18059 Rostock
Deutschland/Germany

phone: +49 (0) 381 498 - 7278
email: Benjamin.Beichler@xxxxxxxxxxxxxx
www: http://www.imd.uni-rostock.de/




[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