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

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

 



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 ==
+			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);
+		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

[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