1 #ifndef _LINUX_AVERAGE_H 2 #define _LINUX_AVERAGE_H 3 4 #include <linux/bug.h> 5 #include <linux/compiler.h> 6 #include <linux/log2.h> 7 8 /* 9 * Exponentially weighted moving average (EWMA) 10 * 11 * This implements a fixed-precision EWMA algorithm, with both the 12 * precision and fall-off coefficient determined at compile-time 13 * and built into the generated helper funtions. 14 * 15 * The first argument to the macro is the name that will be used 16 * for the struct and helper functions. 17 * 18 * The second argument, the precision, expresses how many bits are 19 * used for the fractional part of the fixed-precision values. 20 * 21 * The third argument, the weight reciprocal, determines how the 22 * new values will be weighed vs. the old state, new values will 23 * get weight 1/weight_rcp and old values 1-1/weight_rcp. Note 24 * that this parameter must be a power of two for efficiency. 25 */ 26 27 #define DECLARE_EWMA(name, _precision, _weight_rcp) \ 28 struct ewma_##name { \ 29 unsigned long internal; \ 30 }; \ 31 static inline void ewma_##name##_init(struct ewma_##name *e) \ 32 { \ 33 BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ 34 BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ 35 /* \ 36 * Even if you want to feed it just 0/1 you should have \ 37 * some bits for the non-fractional part... \ 38 */ \ 39 BUILD_BUG_ON((_precision) > 30); \ 40 BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ 41 e->internal = 0; \ 42 } \ 43 static inline unsigned long \ 44 ewma_##name##_read(struct ewma_##name *e) \ 45 { \ 46 BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ 47 BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ 48 BUILD_BUG_ON((_precision) > 30); \ 49 BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ 50 return e->internal >> (_precision); \ 51 } \ 52 static inline void ewma_##name##_add(struct ewma_##name *e, \ 53 unsigned long val) \ 54 { \ 55 unsigned long internal = READ_ONCE(e->internal); \ 56 unsigned long weight_rcp = ilog2(_weight_rcp); \ 57 unsigned long precision = _precision; \ 58 \ 59 BUILD_BUG_ON(!__builtin_constant_p(_precision)); \ 60 BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \ 61 BUILD_BUG_ON((_precision) > 30); \ 62 BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \ 63 \ 64 WRITE_ONCE(e->internal, internal ? \ 65 (((internal << weight_rcp) - internal) + \ 66 (val << precision)) >> weight_rcp : \ 67 (val << precision)); \ 68 } 69 70 #endif /* _LINUX_AVERAGE_H */ 71