Add the "timers: do not raise softirq unconditionally" temporarily 26/1226/7
authorYunhong Jiang <yunhong.jiang@intel.com>
Tue, 18 Aug 2015 18:07:48 +0000 (11:07 -0700)
committerYunhong Jiang <yunhong.jiang@linux.intel.com>
Fri, 22 Jul 2016 00:48:26 +0000 (17:48 -0700)
This patch enable the nohz_full and is important for RT. Bring it back
temporarily, while waiting for more work on RT community.

Please refer to https://lkml.org/lkml/2015/3/17/783 for more information
of the revert.

A little rebase needed because it's reverted on old code base.

Please notice that we change the rt_mutex_trylock() so that we can get
the tvec_base lock there. This is sure to be wrong, and should be fixed
cleanly. And that's the major reason the original patch are reverted on the
upstream RT linux. Will discuss with upstream on how to achieve the
solution.

Upstream status: pending

Change-Id: I2747e087faf4145b69b800a60b8d9414bc71e206
Signed-off-by: Yunhong Jiang <yunhong.jiang@linux.intel.com>
kernel/kernel/locking/rtmutex.c
kernel/kernel/time/timer.c

index 6697100..30777e8 100644 (file)
@@ -2058,13 +2058,6 @@ EXPORT_SYMBOL_GPL(rt_mutex_timed_lock);
  */
 int __sched rt_mutex_trylock(struct rt_mutex *lock)
 {
-#ifdef CONFIG_PREEMPT_RT_FULL
-       if (WARN_ON(in_irq() || in_nmi()))
-#else
-       if (WARN_ON(in_irq() || in_nmi() || in_serving_softirq()))
-#endif
-               return 0;
-
        return rt_mutex_fasttrylock(lock, rt_mutex_slowtrylock);
 }
 EXPORT_SYMBOL_GPL(rt_mutex_trylock);
index fee8682..76a301b 100644 (file)
@@ -1509,8 +1509,36 @@ static void run_timer_softirq(struct softirq_action *h)
  */
 void run_local_timers(void)
 {
+       struct tvec_base *base = this_cpu_ptr(&tvec_bases);
+
        hrtimer_run_queues();
-       raise_softirq(TIMER_SOFTIRQ);
+       /*
+        * We can access this lockless as we are in the timer
+        * interrupt. If there are no timers queued, nothing to do in
+        * the timer softirq.
+        */
+#ifdef CONFIG_PREEMPT_RT_FULL
+       if (irq_work_needs_cpu()) {
+               raise_softirq(TIMER_SOFTIRQ);
+               return;
+       }
+       if (!spin_do_trylock(&base->lock)) {
+               raise_softirq(TIMER_SOFTIRQ);
+               return;
+       }
+#endif
+       if (!base->active_timers)
+               goto out;
+
+       /* Check whether the next pending timer has expired */
+       if (time_before_eq(base->next_timer, jiffies))
+               raise_softirq(TIMER_SOFTIRQ);
+out:
+#ifdef CONFIG_PREEMPT_RT_FULL
+       rt_spin_unlock(&base->lock);
+#endif
+       /* The ; ensures that gcc won't complain in the !RT case */
+       ;
 }
 
 #ifdef __ARCH_WANT_SYS_ALARM