ef4d9af62f
For several reasons, it is desirable to use {READ,WRITE}_ONCE() in preference to ACCESS_ONCE(), and new code is expected to use one of the former. So far, there's been no reason to change most existing uses of ACCESS_ONCE(), as these aren't currently harmful. However, for some features it is necessary to instrument reads and writes separately, which is not possible with ACCESS_ONCE(). This distinction is critical to correct operation. It's possible to transform the bulk of kernel code using the Coccinelle script below. However, this doesn't pick up some uses, including those in <linux/average.h>. As a preparatory step, this patch converts the file to use {READ,WRITE}_ONCE() consistently. At the same time, this patch addds missing includes necessary for {READ,WRITE}_ONCE(), *BUG_ON*(), and ilog2(). ---- virtual patch @ depends on patch @ expression E1, E2; @@ - ACCESS_ONCE(E1) = E2 + WRITE_ONCE(E1, E2) @ depends on patch @ expression E; @@ - ACCESS_ONCE(E) + READ_ONCE(E) ---- Signed-off-by: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reviewed-by: Johannes Berg <johannes@sipsolutions.net> Cc: David S. Miller <davem@davemloft.net> Cc: Johannes Berg <johannes.berg@intel.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-arch@vger.kernel.org Cc: mpe@ellerman.id.au Cc: shuah@kernel.org Cc: snitzer@redhat.com Cc: thor.thayer@linux.intel.com Cc: tj@kernel.org Cc: viro@zeniv.linux.org.uk Cc: will.deacon@arm.com Link: http://lkml.kernel.org/r/1508792849-3115-9-git-send-email-paulmck@linux.vnet.ibm.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
71 lines
2.4 KiB
C
71 lines
2.4 KiB
C
#ifndef _LINUX_AVERAGE_H
|
|
#define _LINUX_AVERAGE_H
|
|
|
|
#include <linux/bug.h>
|
|
#include <linux/compiler.h>
|
|
#include <linux/log2.h>
|
|
|
|
/*
|
|
* Exponentially weighted moving average (EWMA)
|
|
*
|
|
* This implements a fixed-precision EWMA algorithm, with both the
|
|
* precision and fall-off coefficient determined at compile-time
|
|
* and built into the generated helper funtions.
|
|
*
|
|
* The first argument to the macro is the name that will be used
|
|
* for the struct and helper functions.
|
|
*
|
|
* The second argument, the precision, expresses how many bits are
|
|
* used for the fractional part of the fixed-precision values.
|
|
*
|
|
* The third argument, the weight reciprocal, determines how the
|
|
* new values will be weighed vs. the old state, new values will
|
|
* get weight 1/weight_rcp and old values 1-1/weight_rcp. Note
|
|
* that this parameter must be a power of two for efficiency.
|
|
*/
|
|
|
|
#define DECLARE_EWMA(name, _precision, _weight_rcp) \
|
|
struct ewma_##name { \
|
|
unsigned long internal; \
|
|
}; \
|
|
static inline void ewma_##name##_init(struct ewma_##name *e) \
|
|
{ \
|
|
BUILD_BUG_ON(!__builtin_constant_p(_precision)); \
|
|
BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \
|
|
/* \
|
|
* Even if you want to feed it just 0/1 you should have \
|
|
* some bits for the non-fractional part... \
|
|
*/ \
|
|
BUILD_BUG_ON((_precision) > 30); \
|
|
BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \
|
|
e->internal = 0; \
|
|
} \
|
|
static inline unsigned long \
|
|
ewma_##name##_read(struct ewma_##name *e) \
|
|
{ \
|
|
BUILD_BUG_ON(!__builtin_constant_p(_precision)); \
|
|
BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \
|
|
BUILD_BUG_ON((_precision) > 30); \
|
|
BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \
|
|
return e->internal >> (_precision); \
|
|
} \
|
|
static inline void ewma_##name##_add(struct ewma_##name *e, \
|
|
unsigned long val) \
|
|
{ \
|
|
unsigned long internal = READ_ONCE(e->internal); \
|
|
unsigned long weight_rcp = ilog2(_weight_rcp); \
|
|
unsigned long precision = _precision; \
|
|
\
|
|
BUILD_BUG_ON(!__builtin_constant_p(_precision)); \
|
|
BUILD_BUG_ON(!__builtin_constant_p(_weight_rcp)); \
|
|
BUILD_BUG_ON((_precision) > 30); \
|
|
BUILD_BUG_ON_NOT_POWER_OF_2(_weight_rcp); \
|
|
\
|
|
WRITE_ONCE(e->internal, internal ? \
|
|
(((internal << weight_rcp) - internal) + \
|
|
(val << precision)) >> weight_rcp : \
|
|
(val << precision)); \
|
|
}
|
|
|
|
#endif /* _LINUX_AVERAGE_H */
|