]> Git Repo - qemu.git/blob - include/qemu/ratelimit.h
ppc/pnv: fix PnvChip redefinition in <hw/ppc/pnv_xscom.h>
[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     uint64_t 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. Calculate the next time slice we may start
59      * sending data again. */
60     delay_slices = (limit->dispatched + limit->slice_quota - 1) /
61         limit->slice_quota;
62     limit->slice_end_time = limit->slice_start_time +
63         delay_slices * limit->slice_ns;
64     return limit->slice_end_time - now;
65 }
66
67 static inline void ratelimit_set_speed(RateLimit *limit, uint64_t speed,
68                                        uint64_t slice_ns)
69 {
70     limit->slice_ns = slice_ns;
71     limit->slice_quota = MAX(((double)speed * slice_ns) / 1000000000ULL, 1);
72 }
73
74 #endif
This page took 0.028139 seconds and 4 git commands to generate.