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