diff options
Diffstat (limited to 'lib/proportions.c')
-rw-r--r-- | lib/proportions.c | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/lib/proportions.c b/lib/proportions.c index 9508d9a7af3e..4f387a643d72 100644 --- a/lib/proportions.c +++ b/lib/proportions.c | |||
@@ -73,12 +73,6 @@ | |||
73 | #include <linux/proportions.h> | 73 | #include <linux/proportions.h> |
74 | #include <linux/rcupdate.h> | 74 | #include <linux/rcupdate.h> |
75 | 75 | ||
76 | /* | ||
77 | * Limit the time part in order to ensure there are some bits left for the | ||
78 | * cycle counter. | ||
79 | */ | ||
80 | #define PROP_MAX_SHIFT (3*BITS_PER_LONG/4) | ||
81 | |||
82 | int prop_descriptor_init(struct prop_descriptor *pd, int shift) | 76 | int prop_descriptor_init(struct prop_descriptor *pd, int shift) |
83 | { | 77 | { |
84 | int err; | 78 | int err; |
@@ -268,6 +262,38 @@ void __prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl) | |||
268 | } | 262 | } |
269 | 263 | ||
270 | /* | 264 | /* |
265 | * identical to __prop_inc_percpu, except that it limits this pl's fraction to | ||
266 | * @frac/PROP_FRAC_BASE by ignoring events when this limit has been exceeded. | ||
267 | */ | ||
268 | void __prop_inc_percpu_max(struct prop_descriptor *pd, | ||
269 | struct prop_local_percpu *pl, long frac) | ||
270 | { | ||
271 | struct prop_global *pg = prop_get_global(pd); | ||
272 | |||
273 | prop_norm_percpu(pg, pl); | ||
274 | |||
275 | if (unlikely(frac != PROP_FRAC_BASE)) { | ||
276 | unsigned long period_2 = 1UL << (pg->shift - 1); | ||
277 | unsigned long counter_mask = period_2 - 1; | ||
278 | unsigned long global_count; | ||
279 | long numerator, denominator; | ||
280 | |||
281 | numerator = percpu_counter_read_positive(&pl->events); | ||
282 | global_count = percpu_counter_read(&pg->events); | ||
283 | denominator = period_2 + (global_count & counter_mask); | ||
284 | |||
285 | if (numerator > ((denominator * frac) >> PROP_FRAC_SHIFT)) | ||
286 | goto out_put; | ||
287 | } | ||
288 | |||
289 | percpu_counter_add(&pl->events, 1); | ||
290 | percpu_counter_add(&pg->events, 1); | ||
291 | |||
292 | out_put: | ||
293 | prop_put_global(pd, pg); | ||
294 | } | ||
295 | |||
296 | /* | ||
271 | * Obtain a fraction of this proportion | 297 | * Obtain a fraction of this proportion |
272 | * | 298 | * |
273 | * p_{j} = x_{j} / (period/2 + t % period/2) | 299 | * p_{j} = x_{j} / (period/2 + t % period/2) |