1145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra/*
2145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra * FLoating proportions
3145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra *
4145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
5145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra *
6145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra * This file contains the public data structure and API definitions.
7145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra */
8145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
9145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra#ifndef _LINUX_PROPORTIONS_H
10145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra#define _LINUX_PROPORTIONS_H
11145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
12145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra#include <linux/percpu_counter.h>
13145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra#include <linux/spinlock.h>
14145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra#include <linux/mutex.h>
15145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
16145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstrastruct prop_global {
17145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	/*
18145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 * The period over which we differentiate
19145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 *
20145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 *   period = 2^shift
21145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 */
22145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	int shift;
23145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	/*
24145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 * The total event counter aka 'time'.
25145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 *
26145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 * Treated as an unsigned long; the lower 'shift - 1' bits are the
27145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 * counter bits, the remaining upper bits the period counter.
28145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 */
29145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	struct percpu_counter events;
30145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra};
31145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
32145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra/*
33145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra * global proportion descriptor
34145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra *
35145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra * this is needed to consitently flip prop_global structures.
36145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra */
37145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstrastruct prop_descriptor {
38145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	int index;
39145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	struct prop_global pg[2];
40145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	struct mutex mutex;		/* serialize the prop_global switch */
41145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra};
42145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
43145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstraint prop_descriptor_init(struct prop_descriptor *pd, int shift);
44145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstravoid prop_change_shift(struct prop_descriptor *pd, int new_shift);
45145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
46145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra/*
47145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra * ----- PERCPU ------
48145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra */
49145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
50145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstrastruct prop_local_percpu {
51145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	/*
52145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 * the local events counter
53145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 */
54145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	struct percpu_counter events;
55145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
56145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	/*
57145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 * snapshot of the last seen global state
58145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 */
59145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	int shift;
60145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	unsigned long period;
61740969f91e950b64a18fdd0a25164cdee042abf0Thomas Gleixner	raw_spinlock_t lock;		/* protect the snapshot state */
62145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra};
63145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
64145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstraint prop_local_init_percpu(struct prop_local_percpu *pl);
65145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstravoid prop_local_destroy_percpu(struct prop_local_percpu *pl);
66145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstravoid __prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl);
67145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstravoid prop_fraction_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl,
68145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra		long *numerator, long *denominator);
69145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
70145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstrastatic inline
71145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstravoid prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl)
72145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra{
73145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	unsigned long flags;
74145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
75145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	local_irq_save(flags);
76145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	__prop_inc_percpu(pd, pl);
77145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	local_irq_restore(flags);
78145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra}
79145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
80145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra/*
81a42dde04152750426cc620fd277e80fffae2f65aPeter Zijlstra * Limit the time part in order to ensure there are some bits left for the
82a42dde04152750426cc620fd277e80fffae2f65aPeter Zijlstra * cycle counter and fraction multiply.
83a42dde04152750426cc620fd277e80fffae2f65aPeter Zijlstra */
843310225dfc71a35a2cc9340c15c0e08b14b3c754Wu Fengguang#if BITS_PER_LONG == 32
85a42dde04152750426cc620fd277e80fffae2f65aPeter Zijlstra#define PROP_MAX_SHIFT (3*BITS_PER_LONG/4)
863310225dfc71a35a2cc9340c15c0e08b14b3c754Wu Fengguang#else
873310225dfc71a35a2cc9340c15c0e08b14b3c754Wu Fengguang#define PROP_MAX_SHIFT (BITS_PER_LONG/2)
883310225dfc71a35a2cc9340c15c0e08b14b3c754Wu Fengguang#endif
89a42dde04152750426cc620fd277e80fffae2f65aPeter Zijlstra
90a42dde04152750426cc620fd277e80fffae2f65aPeter Zijlstra#define PROP_FRAC_SHIFT		(BITS_PER_LONG - PROP_MAX_SHIFT - 1)
91a42dde04152750426cc620fd277e80fffae2f65aPeter Zijlstra#define PROP_FRAC_BASE		(1UL << PROP_FRAC_SHIFT)
92a42dde04152750426cc620fd277e80fffae2f65aPeter Zijlstra
93a42dde04152750426cc620fd277e80fffae2f65aPeter Zijlstravoid __prop_inc_percpu_max(struct prop_descriptor *pd,
94a42dde04152750426cc620fd277e80fffae2f65aPeter Zijlstra			   struct prop_local_percpu *pl, long frac);
95a42dde04152750426cc620fd277e80fffae2f65aPeter Zijlstra
96a42dde04152750426cc620fd277e80fffae2f65aPeter Zijlstra
97a42dde04152750426cc620fd277e80fffae2f65aPeter Zijlstra/*
98145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra * ----- SINGLE ------
99145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra */
100145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
101145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstrastruct prop_local_single {
102145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	/*
103145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 * the local events counter
104145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 */
105145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	unsigned long events;
106145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
107145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	/*
108145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 * snapshot of the last seen global state
109145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 * and a lock protecting this state
110145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	 */
111145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	unsigned long period;
1123fb669dd6ec11e14819c0114a0e68a9ddcec65e1Richard Kennedy	int shift;
113740969f91e950b64a18fdd0a25164cdee042abf0Thomas Gleixner	raw_spinlock_t lock;		/* protect the snapshot state */
114145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra};
115145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
116145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra#define INIT_PROP_LOCAL_SINGLE(name)			\
117740969f91e950b64a18fdd0a25164cdee042abf0Thomas Gleixner{	.lock = __RAW_SPIN_LOCK_UNLOCKED(name.lock),	\
118145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra}
119145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
120145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstraint prop_local_init_single(struct prop_local_single *pl);
121145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstravoid prop_local_destroy_single(struct prop_local_single *pl);
122145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstravoid __prop_inc_single(struct prop_descriptor *pd, struct prop_local_single *pl);
123145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstravoid prop_fraction_single(struct prop_descriptor *pd, struct prop_local_single *pl,
124145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra		long *numerator, long *denominator);
125145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
126145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstrastatic inline
127145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstravoid prop_inc_single(struct prop_descriptor *pd, struct prop_local_single *pl)
128145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra{
129145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	unsigned long flags;
130145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
131145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	local_irq_save(flags);
132145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	__prop_inc_single(pd, pl);
133145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra	local_irq_restore(flags);
134145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra}
135145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra
136145ca25eb2fbd20d4faf1bad4628c7650332058fPeter Zijlstra#endif /* _LINUX_PROPORTIONS_H */
137