Skip to content

Commit 12efa1f

Browse files
edumazetdavem330
authored andcommitted
net_sched: gen_estimator: account for timer drifts
Under heavy stress, timer used in estimators tend to slowly be delayed by a few jiffies, leading to inaccuracies. Lets remember what was the last scheduled jiffies so that we get more precise estimations, without having to add a multiply/divide in the loop to account for the drifts. Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e01b16a commit 12efa1f

File tree

1 file changed

+16
-9
lines changed

1 file changed

+16
-9
lines changed

net/core/gen_estimator.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@
7878

7979
#define EST_MAX_INTERVAL 5
8080

81-
struct gen_estimator
82-
{
81+
struct gen_estimator {
8382
struct list_head list;
8483
struct gnet_stats_basic_packed *bstats;
8584
struct gnet_stats_rate_est64 *rate_est;
@@ -96,8 +95,8 @@ struct gen_estimator
9695
struct rcu_head head;
9796
};
9897

99-
struct gen_estimator_head
100-
{
98+
struct gen_estimator_head {
99+
unsigned long next_jiffies;
101100
struct timer_list timer;
102101
struct list_head list;
103102
};
@@ -146,8 +145,15 @@ static void est_timer(unsigned long arg)
146145
spin_unlock(e->stats_lock);
147146
}
148147

149-
if (!list_empty(&elist[idx].list))
150-
mod_timer(&elist[idx].timer, jiffies + ((HZ/4) << idx));
148+
if (!list_empty(&elist[idx].list)) {
149+
elist[idx].next_jiffies += ((HZ/4) << idx);
150+
151+
if (unlikely(time_after_eq(jiffies, elist[idx].next_jiffies))) {
152+
/* Ouch... timer was delayed. */
153+
elist[idx].next_jiffies = jiffies + 1;
154+
}
155+
mod_timer(&elist[idx].timer, elist[idx].next_jiffies);
156+
}
151157
rcu_read_unlock();
152158
}
153159

@@ -251,9 +257,10 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
251257
setup_timer(&elist[idx].timer, est_timer, idx);
252258
}
253259

254-
if (list_empty(&elist[idx].list))
255-
mod_timer(&elist[idx].timer, jiffies + ((HZ/4) << idx));
256-
260+
if (list_empty(&elist[idx].list)) {
261+
elist[idx].next_jiffies = jiffies + ((HZ/4) << idx);
262+
mod_timer(&elist[idx].timer, elist[idx].next_jiffies);
263+
}
257264
list_add_rcu(&est->list, &elist[idx].list);
258265
gen_add_node(est);
259266
spin_unlock_bh(&est_tree_lock);

0 commit comments

Comments
 (0)