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