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/