at v3.3 3.2 kB view raw
1/* 2 * FLoating proportions 3 * 4 * Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> 5 * 6 * This file contains the public data structure and API definitions. 7 */ 8 9#ifndef _LINUX_PROPORTIONS_H 10#define _LINUX_PROPORTIONS_H 11 12#include <linux/percpu_counter.h> 13#include <linux/spinlock.h> 14#include <linux/mutex.h> 15 16struct prop_global { 17 /* 18 * The period over which we differentiate 19 * 20 * period = 2^shift 21 */ 22 int shift; 23 /* 24 * The total event counter aka 'time'. 25 * 26 * Treated as an unsigned long; the lower 'shift - 1' bits are the 27 * counter bits, the remaining upper bits the period counter. 28 */ 29 struct percpu_counter events; 30}; 31 32/* 33 * global proportion descriptor 34 * 35 * this is needed to consitently flip prop_global structures. 36 */ 37struct prop_descriptor { 38 int index; 39 struct prop_global pg[2]; 40 struct mutex mutex; /* serialize the prop_global switch */ 41}; 42 43int prop_descriptor_init(struct prop_descriptor *pd, int shift); 44void prop_change_shift(struct prop_descriptor *pd, int new_shift); 45 46/* 47 * ----- PERCPU ------ 48 */ 49 50struct prop_local_percpu { 51 /* 52 * the local events counter 53 */ 54 struct percpu_counter events; 55 56 /* 57 * snapshot of the last seen global state 58 */ 59 int shift; 60 unsigned long period; 61 raw_spinlock_t lock; /* protect the snapshot state */ 62}; 63 64int prop_local_init_percpu(struct prop_local_percpu *pl); 65void prop_local_destroy_percpu(struct prop_local_percpu *pl); 66void __prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl); 67void prop_fraction_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl, 68 long *numerator, long *denominator); 69 70static inline 71void prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl) 72{ 73 unsigned long flags; 74 75 local_irq_save(flags); 76 __prop_inc_percpu(pd, pl); 77 local_irq_restore(flags); 78} 79 80/* 81 * Limit the time part in order to ensure there are some bits left for the 82 * cycle counter and fraction multiply. 83 */ 84#if BITS_PER_LONG == 32 85#define PROP_MAX_SHIFT (3*BITS_PER_LONG/4) 86#else 87#define PROP_MAX_SHIFT (BITS_PER_LONG/2) 88#endif 89 90#define PROP_FRAC_SHIFT (BITS_PER_LONG - PROP_MAX_SHIFT - 1) 91#define PROP_FRAC_BASE (1UL << PROP_FRAC_SHIFT) 92 93void __prop_inc_percpu_max(struct prop_descriptor *pd, 94 struct prop_local_percpu *pl, long frac); 95 96 97/* 98 * ----- SINGLE ------ 99 */ 100 101struct prop_local_single { 102 /* 103 * the local events counter 104 */ 105 unsigned long events; 106 107 /* 108 * snapshot of the last seen global state 109 * and a lock protecting this state 110 */ 111 unsigned long period; 112 int shift; 113 raw_spinlock_t lock; /* protect the snapshot state */ 114}; 115 116#define INIT_PROP_LOCAL_SINGLE(name) \ 117{ .lock = __RAW_SPIN_LOCK_UNLOCKED(name.lock), \ 118} 119 120int prop_local_init_single(struct prop_local_single *pl); 121void prop_local_destroy_single(struct prop_local_single *pl); 122void __prop_inc_single(struct prop_descriptor *pd, struct prop_local_single *pl); 123void prop_fraction_single(struct prop_descriptor *pd, struct prop_local_single *pl, 124 long *numerator, long *denominator); 125 126static inline 127void prop_inc_single(struct prop_descriptor *pd, struct prop_local_single *pl) 128{ 129 unsigned long flags; 130 131 local_irq_save(flags); 132 __prop_inc_single(pd, pl); 133 local_irq_restore(flags); 134} 135 136#endif /* _LINUX_PROPORTIONS_H */