Message ID | 20170820144553.2ab2727b@ppc64le (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
From: Nicholas Piggin <npiggin@gmail.com> Date: Sun, 20 Aug 2017 14:45:53 +1000 > [PATCH] timers: Fix excessive granularity of new timers after a nohz idle I just booted into this on my sparc64 box, let's see if it does the trick :-)
On Sun, Aug 20, 2017 at 02:45:53PM +1000, Nicholas Piggin wrote: > On Wed, 16 Aug 2017 09:27:31 -0700 > "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> wrote: > > On Wed, Aug 16, 2017 at 05:56:17AM -0700, Paul E. McKenney wrote: > > > > Thomas, John, am I misinterpreting the timer trace event messages? > > So I did some digging, and what you find is that rcu_sched seems to do a > simple scheudle_timeout(1) and just goes out to lunch for many seconds. > The process_timeout timer never fires (when it finally does wake after > one of these events, it usually removes the timer with del_timer_sync). > > So this patch seems to fix it. Testing, comments welcome. Fired up some tests, which should complete in about 12 hours. Here is hoping! ;-) Thanx, Paul
diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 8f5d1bf18854..8f69b3105b8f 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -859,10 +859,10 @@ static inline void forward_timer_base(struct timer_base *base) unsigned long jnow = READ_ONCE(jiffies); /* - * We only forward the base when it's idle and we have a delta between - * base clock and jiffies. + * We only forward the base when we have a delta between base clock + * and jiffies. In the common case, run_timers will take care of it. */ - if (!base->is_idle || (long) (jnow - base->clk) < 2) + if ((long) (jnow - base->clk) < 2) return; /* @@ -938,6 +938,13 @@ __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only) * same array bucket then just return: */ if (timer_pending(timer)) { + /* + * The downside of this optimization is that it can result in + * larger granularity than you would get from adding a new + * timer with this expiry. Would a timer flag for networking + * be appropriate, then we can try to keep expiry of general + * timers within ~1/8th of their interval? + */ if (timer->expires == expires) return 1;