Re: [PATCH 1/2] [RT] hrtimers stuck in waitqueue

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




Le 21 août 08 à 15:16, John Kacur a écrit :

On Mon, Aug 18, 2008 at 4:42 PM, Gilles Carry <gilles.carry@xxxxxxxx> wrote:
This patch makes hrtimers initialized with hrtimer_init_sleeper
to use another mode and then not be stuck in waitqueues when
hrtimer_interrupt is very busy.

The new mode is HRTIMER_CB_IRQSAFE_NO_RESTART_NO_SOFIRQ.
The above-mentionned timers have been moved from
HRTIMER_CB_IRQSAFE_NO_SOFTIRQ to
HRTIMER_CB_IRQSAFE_NO_RESTART_NO_SOFIRQ.

HRTIMER_CB_IRQSAFE_NO_RESTART_NO_SOFIRQ timers use a slightly different state machine from HRTIMER_CB_IRQSAFE_NO_SOFTIRQ's as when removing the
timer, __run_hrtimer sets the status to INACTIVE _then_
wakes up the thread. This way, an awakened thread cannot enter
hrtimer_cancel before the timer's status has changed.

Signed-off-by: Gilles Carry <gilles.carry@xxxxxxxx>

---
include/linux/hrtimer.h |    4 ++++
kernel/hrtimer.c        |   26 +++++++++++++++++++++-----
2 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index f3867fd..53f4d44 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -49,12 +49,16 @@ enum hrtimer_restart {
*                                     does not restart the timer
* HRTIMER_CB_IRQSAFE_NO_SOFTIRQ: Callback must run in hardirq context * Special mode for tick emultation
+ *     HRTIMER_CB_IRQSAFE_NO_RESTART_NO_SOFTIRQ:
+ * Callback must run in hardirq context and
+ *                                     does not restart the timer
*/
enum hrtimer_cb_mode {
      HRTIMER_CB_SOFTIRQ,
      HRTIMER_CB_IRQSAFE,
      HRTIMER_CB_IRQSAFE_NO_RESTART,
      HRTIMER_CB_IRQSAFE_NO_SOFTIRQ,
+       HRTIMER_CB_IRQSAFE_NO_RESTART_NO_SOFTIRQ,
};

/*
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index fa63a24..778eb7e 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -668,6 +668,7 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
              /* Timer is expired, act upon the callback mode */
              switch(timer->cb_mode) {
              case HRTIMER_CB_IRQSAFE_NO_RESTART:
+               case HRTIMER_CB_IRQSAFE_NO_RESTART_NO_SOFTIRQ:
                      debug_hrtimer_deactivate(timer);
                      /*
* We can call the callback from here. No restart
@@ -1089,6 +1090,8 @@ int hrtimer_cancel(struct hrtimer *timer)

              if (ret >= 0)
                      return ret;
+               WARN_ON (timer->cb_mode ==

Minor point here, we may as well squash checkpatch.pl complaints now,
to reduce any clean-up later to push to mainline. if you run
checkpatch.pl
WARNING: space prohibited between function name and open parenthesis '('
#69: FILE: kernel/hrtimer.c:1093:
+               WARN_ON (timer->cb_mode ==

I will fix that soon.
I split the line because it was to long. I know some people don't like more than
80 chars a line. This is why I did this.




+                       HRTIMER_CB_IRQSAFE_NO_RESTART_NO_SOFTIRQ);
              hrtimer_wait_for_timer(timer);
      }
}
@@ -1298,11 +1301,18 @@ static void __run_hrtimer(struct hrtimer *timer)
      int restart;

      debug_hrtimer_deactivate(timer);
-       __remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0);
-       timer_stats_account_hrtimer(timer);

      fn = timer->function;
-       if (timer->cb_mode == HRTIMER_CB_IRQSAFE_NO_SOFTIRQ) {
+
+       switch (timer->cb_mode) {
+       case HRTIMER_CB_IRQSAFE_NO_RESTART_NO_SOFTIRQ:
+ __remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE, 0);

Correct me if I'm wrong but there is a lot of code reworking and code
expansion here, when really the above line is the only difference
between your new HRTIMER_CB_IRQSAFE_NO_RESTART_NO_SOFTIRQ
and HRTIMER_CB_IRQSAFE_NO_SOFTIRQ.
It is not even strictly necessary to return, since the rest of the
function should be safe. I have attached an alternate smaller patch, -
maybe you'll find it simpler?


You're right I did some reworking to have clear situation of what is to be done
depending on the timer's mode.
I'll check your patch as soon as I come back to my office (monday).
I just have an email client down here.

Thank-you for all your comments, John.


+               timer_stats_account_hrtimer(timer);
+               spin_unlock(&cpu_base->lock);
+               fn(timer);
+               spin_lock(&cpu_base->lock);
+               return;
+       case HRTIMER_CB_IRQSAFE_NO_SOFTIRQ:
              /*
               * Used for scheduler timers, avoid lock inversion with
               * rq->lock and tasklist_lock.
@@ -1310,11 +1320,17 @@ static void __run_hrtimer(struct hrtimer *timer) * These timers are required to deal with enqueue expiry
               * themselves and are not allowed to migrate.
               */
+ __remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0);
+               timer_stats_account_hrtimer(timer);
              spin_unlock(&cpu_base->lock);
              restart = fn(timer);
              spin_lock(&cpu_base->lock);
-       } else
+               break;
+       default:
+ __remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0);
+               timer_stats_account_hrtimer(timer);
              restart = fn(timer);
+       }

      /*
* Note: We clear the CALLBACK bit after enqueue_hrtimer to avoid @@ -1516,7 +1532,7 @@ void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task)
      sl->timer.function = hrtimer_wakeup;
      sl->task = task;
#ifdef CONFIG_HIGH_RES_TIMERS
-       sl->timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ;
+       sl->timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_RESTART_NO_SOFTIRQ;
#endif
}

--
1.5.2.2

--
To unsubscribe from this list: send the line "unsubscribe linux-rt- users" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

<hrtimers_stuck_in_waitq-jk.patch>

--
To unsubscribe from this list: send the line "unsubscribe linux-rt-users" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [RT Stable]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]

  Powered by Linux