]> Git Repo - qemu.git/blob - include/qemu/ratelimit.h
block: Eliminate the S_1KiB, S_2KiB, ... macros
[qemu.git] / include / qemu / ratelimit.h
1 /*
2  * Ratelimiting calculations
3  *
4  * Copyright IBM, Corp. 2011
5  *
6  * Authors:
7  *  Stefan Hajnoczi   <[email protected]>
8  *
9  * This work is licensed under the terms of the GNU LGPL, version 2 or later.
10  * See the COPYING.LIB file in the top-level directory.
11  *
12  */
13
14 #ifndef QEMU_RATELIMIT_H
15 #define QEMU_RATELIMIT_H
16
17 typedef struct {
18     int64_t slice_start_time;
19     int64_t slice_end_time;
20     uint64_t slice_quota;
21     uint64_t slice_ns;
22     uint64_t dispatched;
23 } RateLimit;
24
25 /** Calculate and return delay for next request in ns
26  *
27  * Record that we sent @n data units (where @n matches the scale chosen
28  * during ratelimit_set_speed). If we may send more data units
29  * in the current time slice, return 0 (i.e. no delay). Otherwise
30  * return the amount of time (in ns) until the start of the next time
31  * slice that will permit sending the next chunk of data.
32  *
33  * Recording sent data units even after exceeding the quota is
34  * permitted; the time slice will be extended accordingly.
35  */
36 static inline int64_t ratelimit_calculate_delay(RateLimit *limit, uint64_t n)
37 {
38     int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
39     double delay_slices;
40
41     assert(limit->slice_quota && limit->slice_ns);
42
43     if (limit->slice_end_time < now) {
44         /* Previous, possibly extended, time slice finished; reset the
45          * accounting. */
46         limit->slice_start_time = now;
47         limit->slice_end_time = now + limit->slice_ns;
48         limit->dispatched = 0;
49     }
50
51     limit->dispatched += n;
52     if (limit->dispatched < limit->slice_quota) {
53         /* We may send further data within the current time slice, no
54          * need to delay the next request. */
55         return 0;
56     }
57
58     /* Quota exceeded. Wait based on the excess amount and then start a new
59      * slice. */
60     delay_slices = (double)limit->dispatched / limit->slice_quota;
61     limit->slice_end_time = limit->slice_start_time +
62         (uint64_t)(delay_slices * limit->slice_ns);
63     return limit->slice_end_time - now;
64 }
65
66 static inline void ratelimit_set_speed(RateLimit *limit, uint64_t speed,
67                                        uint64_t slice_ns)
68 {
69     limit->slice_ns = slice_ns;
70     limit->slice_quota = MAX(((double)speed * slice_ns) / 1000000000ULL, 1);
71 }
72
73 #endif
This page took 0.027754 seconds and 4 git commands to generate.