Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 12efa1fa authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

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: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e01b16a7
Loading
Loading
Loading
Loading
+16 −9
Original line number Diff line number Diff line
@@ -78,8 +78,7 @@

#define EST_MAX_INTERVAL	5

struct gen_estimator
{
struct gen_estimator {
	struct list_head	list;
	struct gnet_stats_basic_packed	*bstats;
	struct gnet_stats_rate_est64	*rate_est;
@@ -96,8 +95,8 @@ struct gen_estimator
	struct rcu_head		head;
};

struct gen_estimator_head
{
struct gen_estimator_head {
	unsigned long		next_jiffies;
	struct timer_list	timer;
	struct list_head	list;
};
@@ -146,8 +145,15 @@ static void est_timer(unsigned long arg)
			spin_unlock(e->stats_lock);
	}

	if (!list_empty(&elist[idx].list))
		mod_timer(&elist[idx].timer, jiffies + ((HZ/4) << idx));
	if (!list_empty(&elist[idx].list)) {
		elist[idx].next_jiffies += ((HZ/4) << idx);

		if (unlikely(time_after_eq(jiffies, elist[idx].next_jiffies))) {
			/* Ouch... timer was delayed. */
			elist[idx].next_jiffies = jiffies + 1;
		}
		mod_timer(&elist[idx].timer, elist[idx].next_jiffies);
	}
	rcu_read_unlock();
}

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

	if (list_empty(&elist[idx].list))
		mod_timer(&elist[idx].timer, jiffies + ((HZ/4) << idx));

	if (list_empty(&elist[idx].list)) {
		elist[idx].next_jiffies = jiffies + ((HZ/4) << idx);
		mod_timer(&elist[idx].timer, elist[idx].next_jiffies);
	}
	list_add_rcu(&est->list, &elist[idx].list);
	gen_add_node(est);
	spin_unlock_bh(&est_tree_lock);