1  /* SPDX-License-Identifier: GPL-2.0 */
2  /*
3   * Floating proportions with flexible aging period
4   *
5   *  Copyright (C) 2011, SUSE, Jan Kara <jack@suse.cz>
6   */
7  
8  #ifndef _LINUX_FLEX_PROPORTIONS_H
9  #define _LINUX_FLEX_PROPORTIONS_H
10  
11  #include <linux/percpu_counter.h>
12  #include <linux/spinlock.h>
13  #include <linux/seqlock.h>
14  #include <linux/gfp.h>
15  
16  /*
17   * When maximum proportion of some event type is specified, this is the
18   * precision with which we allow limitting. Note that this creates an upper
19   * bound on the number of events per period like
20   *   ULLONG_MAX >> FPROP_FRAC_SHIFT.
21   */
22  #define FPROP_FRAC_SHIFT 10
23  #define FPROP_FRAC_BASE (1UL << FPROP_FRAC_SHIFT)
24  
25  /*
26   * ---- Global proportion definitions ----
27   */
28  struct fprop_global {
29  	/* Number of events in the current period */
30  	struct percpu_counter events;
31  	/* Current period */
32  	unsigned int period;
33  	/* Synchronization with period transitions */
34  	seqcount_t sequence;
35  };
36  
37  int fprop_global_init(struct fprop_global *p, gfp_t gfp);
38  void fprop_global_destroy(struct fprop_global *p);
39  bool fprop_new_period(struct fprop_global *p, int periods);
40  
41  /*
42   * ---- PERCPU ----
43   */
44  struct fprop_local_percpu {
45  	/* the local events counter */
46  	struct percpu_counter events;
47  	/* Period in which we last updated events */
48  	unsigned int period;
49  	raw_spinlock_t lock;	/* Protect period and numerator */
50  };
51  
52  int fprop_local_init_percpu(struct fprop_local_percpu *pl, gfp_t gfp);
53  void fprop_local_destroy_percpu(struct fprop_local_percpu *pl);
54  void __fprop_add_percpu(struct fprop_global *p, struct fprop_local_percpu *pl,
55  		long nr);
56  void __fprop_add_percpu_max(struct fprop_global *p,
57  		struct fprop_local_percpu *pl, int max_frac, long nr);
58  void fprop_fraction_percpu(struct fprop_global *p,
59  	struct fprop_local_percpu *pl, unsigned long *numerator,
60  	unsigned long *denominator);
61  
62  static inline
fprop_inc_percpu(struct fprop_global * p,struct fprop_local_percpu * pl)63  void fprop_inc_percpu(struct fprop_global *p, struct fprop_local_percpu *pl)
64  {
65  	unsigned long flags;
66  
67  	local_irq_save(flags);
68  	__fprop_add_percpu(p, pl, 1);
69  	local_irq_restore(flags);
70  }
71  
72  #endif
73