]> Git Repo - linux.git/blob - include/linux/average.h
x86/paravirt: Set up the virt_spin_lock_key after static keys get initialized
[linux.git] / include / linux / average.h
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 */
This page took 0.040831 seconds and 4 git commands to generate.