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