aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2008-04-29 04:02:46 -0400
committerIngo Molnar <mingo@elte.hu>2008-05-05 17:56:18 -0400
commitb328ca182f01c2a04b85e0ee8a410720b104fbcc (patch)
treed04ba3472a8f57788fb7e6e614e8e6b3c5a79b55
parent104f64549c961a797ff5f7c59946a7caa335c5b0 (diff)
sched: fix hrtick_start_fair and CPU-Hotplug
Gautham R Shenoy reported: > While running the usual CPU-Hotplug stress tests on linux-2.6.25, > I noticed the following in the console logs. > > This is a wee bit difficult to reproduce. In the past 10 runs I hit this > only once. > > ------------[ cut here ]------------ > > WARNING: at kernel/sched.c:962 hrtick+0x2e/0x65() > > Just wondering if we are doing a good job at handling the cancellation > of any per-cpu scheduler timers during CPU-Hotplug. This looks like its indeed not cancelled at all and migrates the it to another cpu. Fix it via a proper hotplug notifier mechanism. Reported-by: Gautham R Shenoy <ego@in.ibm.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: stable@kernel.org Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--kernel/sched.c66
1 files changed, 65 insertions, 1 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index d941ddc9ec1d..bee9cbe13c15 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -1191,6 +1191,7 @@ static inline void resched_rq(struct rq *rq)
1191enum { 1191enum {
1192 HRTICK_SET, /* re-programm hrtick_timer */ 1192 HRTICK_SET, /* re-programm hrtick_timer */
1193 HRTICK_RESET, /* not a new slice */ 1193 HRTICK_RESET, /* not a new slice */
1194 HRTICK_BLOCK, /* stop hrtick operations */
1194}; 1195};
1195 1196
1196/* 1197/*
@@ -1202,6 +1203,8 @@ static inline int hrtick_enabled(struct rq *rq)
1202{ 1203{
1203 if (!sched_feat(HRTICK)) 1204 if (!sched_feat(HRTICK))
1204 return 0; 1205 return 0;
1206 if (unlikely(test_bit(HRTICK_BLOCK, &rq->hrtick_flags)))
1207 return 0;
1205 return hrtimer_is_hres_active(&rq->hrtick_timer); 1208 return hrtimer_is_hres_active(&rq->hrtick_timer);
1206} 1209}
1207 1210
@@ -1284,7 +1287,63 @@ static enum hrtimer_restart hrtick(struct hrtimer *timer)
1284 return HRTIMER_NORESTART; 1287 return HRTIMER_NORESTART;
1285} 1288}
1286 1289
1287static inline void init_rq_hrtick(struct rq *rq) 1290static void hotplug_hrtick_disable(int cpu)
1291{
1292 struct rq *rq = cpu_rq(cpu);
1293 unsigned long flags;
1294
1295 spin_lock_irqsave(&rq->lock, flags);
1296 rq->hrtick_flags = 0;
1297 __set_bit(HRTICK_BLOCK, &rq->hrtick_flags);
1298 spin_unlock_irqrestore(&rq->lock, flags);
1299
1300 hrtick_clear(rq);
1301}
1302
1303static void hotplug_hrtick_enable(int cpu)
1304{
1305 struct rq *rq = cpu_rq(cpu);
1306 unsigned long flags;
1307
1308 spin_lock_irqsave(&rq->lock, flags);
1309 __clear_bit(HRTICK_BLOCK, &rq->hrtick_flags);
1310 spin_unlock_irqrestore(&rq->lock, flags);
1311}
1312
1313static int
1314hotplug_hrtick(struct notifier_block *nfb, unsigned long action, void *hcpu)
1315{
1316 int cpu = (int)(long)hcpu;
1317
1318 switch (action) {
1319 case CPU_UP_CANCELED:
1320 case CPU_UP_CANCELED_FROZEN:
1321 case CPU_DOWN_PREPARE:
1322 case CPU_DOWN_PREPARE_FROZEN:
1323 case CPU_DEAD:
1324 case CPU_DEAD_FROZEN:
1325 hotplug_hrtick_disable(cpu);
1326 return NOTIFY_OK;
1327
1328 case CPU_UP_PREPARE:
1329 case CPU_UP_PREPARE_FROZEN:
1330 case CPU_DOWN_FAILED:
1331 case CPU_DOWN_FAILED_FROZEN:
1332 case CPU_ONLINE:
1333 case CPU_ONLINE_FROZEN:
1334 hotplug_hrtick_enable(cpu);
1335 return NOTIFY_OK;
1336 }
1337
1338 return NOTIFY_DONE;
1339}
1340
1341static void init_hrtick(void)
1342{
1343 hotcpu_notifier(hotplug_hrtick, 0);
1344}
1345
1346static void init_rq_hrtick(struct rq *rq)
1288{ 1347{
1289 rq->hrtick_flags = 0; 1348 rq->hrtick_flags = 0;
1290 hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 1349 hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
@@ -1321,6 +1380,10 @@ static inline void init_rq_hrtick(struct rq *rq)
1321void hrtick_resched(void) 1380void hrtick_resched(void)
1322{ 1381{
1323} 1382}
1383
1384static inline void init_hrtick(void)
1385{
1386}
1324#endif 1387#endif
1325 1388
1326/* 1389/*
@@ -7943,6 +8006,7 @@ void __init sched_init_smp(void)
7943 put_online_cpus(); 8006 put_online_cpus();
7944 /* XXX: Theoretical race here - CPU may be hotplugged now */ 8007 /* XXX: Theoretical race here - CPU may be hotplugged now */
7945 hotcpu_notifier(update_sched_domains, 0); 8008 hotcpu_notifier(update_sched_domains, 0);
8009 init_hrtick();
7946 8010
7947 /* Move init over to a non-isolated CPU */ 8011 /* Move init over to a non-isolated CPU */
7948 if (set_cpus_allowed_ptr(current, &non_isolated_cpus) < 0) 8012 if (set_cpus_allowed_ptr(current, &non_isolated_cpus) < 0)