]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - include/linux/average.h
Merge remote-tracking branch 'parisc-hd/for-next'
[karo-tx-linux.git] / include / linux / average.h
1 #ifndef _LINUX_AVERAGE_H
2 #define _LINUX_AVERAGE_H
3
4 /* Exponentially weighted moving average (EWMA) */
5
6 #define DECLARE_EWMA(name, _factor, _weight)                            \
7         struct ewma_##name {                                            \
8                 unsigned long internal;                                 \
9         };                                                              \
10         static inline void ewma_##name##_init(struct ewma_##name *e)    \
11         {                                                               \
12                 BUILD_BUG_ON(!__builtin_constant_p(_factor));           \
13                 BUILD_BUG_ON(!__builtin_constant_p(_weight));           \
14                 BUILD_BUG_ON_NOT_POWER_OF_2(_factor);                   \
15                 BUILD_BUG_ON_NOT_POWER_OF_2(_weight);                   \
16                 e->internal = 0;                                        \
17         }                                                               \
18         static inline unsigned long                                     \
19         ewma_##name##_read(struct ewma_##name *e)                       \
20         {                                                               \
21                 BUILD_BUG_ON(!__builtin_constant_p(_factor));           \
22                 BUILD_BUG_ON(!__builtin_constant_p(_weight));           \
23                 BUILD_BUG_ON_NOT_POWER_OF_2(_factor);                   \
24                 BUILD_BUG_ON_NOT_POWER_OF_2(_weight);                   \
25                 return e->internal >> ilog2(_factor);                   \
26         }                                                               \
27         static inline void ewma_##name##_add(struct ewma_##name *e,     \
28                                              unsigned long val)         \
29         {                                                               \
30                 unsigned long internal = ACCESS_ONCE(e->internal);      \
31                 unsigned long weight = ilog2(_weight);                  \
32                 unsigned long factor = ilog2(_factor);                  \
33                                                                         \
34                 BUILD_BUG_ON(!__builtin_constant_p(_factor));           \
35                 BUILD_BUG_ON(!__builtin_constant_p(_weight));           \
36                 BUILD_BUG_ON_NOT_POWER_OF_2(_factor);                   \
37                 BUILD_BUG_ON_NOT_POWER_OF_2(_weight);                   \
38                                                                         \
39                 ACCESS_ONCE(e->internal) = internal ?                   \
40                         (((internal << weight) - internal) +            \
41                                 (val << factor)) >> weight :            \
42                         (val << factor);                                \
43         }
44
45 #endif /* _LINUX_AVERAGE_H */