@@ -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 */
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(-)