linux/include/linux/average.h
<<
>>
Prefs
   1#ifndef _LINUX_AVERAGE_H
   2#define _LINUX_AVERAGE_H
   3
   4/* Exponentially weighted moving average (EWMA) */
   5
   6/* For more documentation see lib/average.c */
   7
   8struct ewma {
   9        unsigned long internal;
  10        unsigned long factor;
  11        unsigned long weight;
  12};
  13
  14extern void ewma_init(struct ewma *avg, unsigned long factor,
  15                      unsigned long weight);
  16
  17extern struct ewma *ewma_add(struct ewma *avg, unsigned long val);
  18
  19/**
  20 * ewma_read() - Get average value
  21 * @avg: Average structure
  22 *
  23 * Returns the average value held in @avg.
  24 */
  25static inline unsigned long ewma_read(const struct ewma *avg)
  26{
  27        return avg->internal >> avg->factor;
  28}
  29
  30#define DECLARE_EWMA(name, _factor, _weight)                            \
  31        struct ewma_##name {                                            \
  32                unsigned long internal;                                 \
  33        };                                                              \
  34        static inline void ewma_##name##_init(struct ewma_##name *e)    \
  35        {                                                               \
  36                BUILD_BUG_ON(!__builtin_constant_p(_factor));           \
  37                BUILD_BUG_ON(!__builtin_constant_p(_weight));           \
  38                BUILD_BUG_ON_NOT_POWER_OF_2(_factor);                   \
  39                BUILD_BUG_ON_NOT_POWER_OF_2(_weight);                   \
  40                e->internal = 0;                                        \
  41        }                                                               \
  42        static inline unsigned long                                     \
  43        ewma_##name##_read(struct ewma_##name *e)                       \
  44        {                                                               \
  45                BUILD_BUG_ON(!__builtin_constant_p(_factor));           \
  46                BUILD_BUG_ON(!__builtin_constant_p(_weight));           \
  47                BUILD_BUG_ON_NOT_POWER_OF_2(_factor);                   \
  48                BUILD_BUG_ON_NOT_POWER_OF_2(_weight);                   \
  49                return e->internal >> ilog2(_factor);                   \
  50        }                                                               \
  51        static inline void ewma_##name##_add(struct ewma_##name *e,     \
  52                                             unsigned long val)         \
  53        {                                                               \
  54                unsigned long internal = ACCESS_ONCE(e->internal);      \
  55                unsigned long weight = ilog2(_weight);                  \
  56                unsigned long factor = ilog2(_factor);                  \
  57                                                                        \
  58                BUILD_BUG_ON(!__builtin_constant_p(_factor));           \
  59                BUILD_BUG_ON(!__builtin_constant_p(_weight));           \
  60                BUILD_BUG_ON_NOT_POWER_OF_2(_factor);                   \
  61                BUILD_BUG_ON_NOT_POWER_OF_2(_weight);                   \
  62                                                                        \
  63                ACCESS_ONCE(e->internal) = internal ?                   \
  64                        (((internal << weight) - internal) +            \
  65                                (val << factor)) >> weight :            \
  66                        (val << factor);                                \
  67        }
  68
  69#endif /* _LINUX_AVERAGE_H */
  70