aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2008-06-05 08:49:58 -0400
committerIngo Molnar <mingo@elte.hu>2008-06-10 06:17:28 -0400
commit7def2be1dc679984f4c4fb3ef19a8a081b2454ec (patch)
tree5be15957919d095cdbbc9ed3217d9dec939b234b /kernel
parente958b3600484533ff801920290468adc8135f89d (diff)
sched: fix hotplug cpus on ia64
Cliff Wickman wrote: > I built an ia64 kernel from Andrew's tree (2.6.26-rc2-mm1) > and get a very predictable hotplug cpu problem. > billberry1:/tmp/cpw # ./dis > disabled cpu 17 > enabled cpu 17 > billberry1:/tmp/cpw # ./dis > disabled cpu 17 > enabled cpu 17 > billberry1:/tmp/cpw # ./dis > > The script that disables the cpu always hangs (unkillable) > on the 3rd attempt. > > And a bit further: > The kstopmachine thread always sits on the run queue (real time) for about > 30 minutes before running. this fix solves some (but not all) issues between CPU hotplug and RT bandwidth throttling. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched.c15
-rw-r--r--kernel/sched_rt.c109
2 files changed, 115 insertions, 9 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index 727bdef76161..e9c24a128655 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -7513,21 +7513,28 @@ int sched_create_sysfs_power_savings_entries(struct sysdev_class *cls)
7513static int update_sched_domains(struct notifier_block *nfb, 7513static int update_sched_domains(struct notifier_block *nfb,
7514 unsigned long action, void *hcpu) 7514 unsigned long action, void *hcpu)
7515{ 7515{
7516 int cpu = (int)(long)hcpu;
7517
7516 switch (action) { 7518 switch (action) {
7517 case CPU_UP_PREPARE:
7518 case CPU_UP_PREPARE_FROZEN:
7519 case CPU_DOWN_PREPARE: 7519 case CPU_DOWN_PREPARE:
7520 case CPU_DOWN_PREPARE_FROZEN: 7520 case CPU_DOWN_PREPARE_FROZEN:
7521 disable_runtime(cpu_rq(cpu));
7522 /* fall-through */
7523 case CPU_UP_PREPARE:
7524 case CPU_UP_PREPARE_FROZEN:
7521 detach_destroy_domains(&cpu_online_map); 7525 detach_destroy_domains(&cpu_online_map);
7522 free_sched_domains(); 7526 free_sched_domains();
7523 return NOTIFY_OK; 7527 return NOTIFY_OK;
7524 7528
7525 case CPU_UP_CANCELED: 7529
7526 case CPU_UP_CANCELED_FROZEN:
7527 case CPU_DOWN_FAILED: 7530 case CPU_DOWN_FAILED:
7528 case CPU_DOWN_FAILED_FROZEN: 7531 case CPU_DOWN_FAILED_FROZEN:
7529 case CPU_ONLINE: 7532 case CPU_ONLINE:
7530 case CPU_ONLINE_FROZEN: 7533 case CPU_ONLINE_FROZEN:
7534 enable_runtime(cpu_rq(cpu));
7535 /* fall-through */
7536 case CPU_UP_CANCELED:
7537 case CPU_UP_CANCELED_FROZEN:
7531 case CPU_DEAD: 7538 case CPU_DEAD:
7532 case CPU_DEAD_FROZEN: 7539 case CPU_DEAD_FROZEN:
7533 /* 7540 /*
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index eaa606071d51..8ae3416e0bb4 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -286,6 +286,9 @@ static int balance_runtime(struct rt_rq *rt_rq)
286 continue; 286 continue;
287 287
288 spin_lock(&iter->rt_runtime_lock); 288 spin_lock(&iter->rt_runtime_lock);
289 if (iter->rt_runtime == RUNTIME_INF)
290 goto next;
291
289 diff = iter->rt_runtime - iter->rt_time; 292 diff = iter->rt_runtime - iter->rt_time;
290 if (diff > 0) { 293 if (diff > 0) {
291 do_div(diff, weight); 294 do_div(diff, weight);
@@ -299,12 +302,105 @@ static int balance_runtime(struct rt_rq *rt_rq)
299 break; 302 break;
300 } 303 }
301 } 304 }
305next:
302 spin_unlock(&iter->rt_runtime_lock); 306 spin_unlock(&iter->rt_runtime_lock);
303 } 307 }
304 spin_unlock(&rt_b->rt_runtime_lock); 308 spin_unlock(&rt_b->rt_runtime_lock);
305 309
306 return more; 310 return more;
307} 311}
312
313static void __disable_runtime(struct rq *rq)
314{
315 struct root_domain *rd = rq->rd;
316 struct rt_rq *rt_rq;
317
318 if (unlikely(!scheduler_running))
319 return;
320
321 for_each_leaf_rt_rq(rt_rq, rq) {
322 struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq);
323 s64 want;
324 int i;
325
326 spin_lock(&rt_b->rt_runtime_lock);
327 spin_lock(&rt_rq->rt_runtime_lock);
328 if (rt_rq->rt_runtime == RUNTIME_INF ||
329 rt_rq->rt_runtime == rt_b->rt_runtime)
330 goto balanced;
331 spin_unlock(&rt_rq->rt_runtime_lock);
332
333 want = rt_b->rt_runtime - rt_rq->rt_runtime;
334
335 for_each_cpu_mask(i, rd->span) {
336 struct rt_rq *iter = sched_rt_period_rt_rq(rt_b, i);
337 s64 diff;
338
339 if (iter == rt_rq)
340 continue;
341
342 spin_lock(&iter->rt_runtime_lock);
343 if (want > 0) {
344 diff = min_t(s64, iter->rt_runtime, want);
345 iter->rt_runtime -= diff;
346 want -= diff;
347 } else {
348 iter->rt_runtime -= want;
349 want -= want;
350 }
351 spin_unlock(&iter->rt_runtime_lock);
352
353 if (!want)
354 break;
355 }
356
357 spin_lock(&rt_rq->rt_runtime_lock);
358 BUG_ON(want);
359balanced:
360 rt_rq->rt_runtime = RUNTIME_INF;
361 spin_unlock(&rt_rq->rt_runtime_lock);
362 spin_unlock(&rt_b->rt_runtime_lock);
363 }
364}
365
366static void disable_runtime(struct rq *rq)
367{
368 unsigned long flags;
369
370 spin_lock_irqsave(&rq->lock, flags);
371 __disable_runtime(rq);
372 spin_unlock_irqrestore(&rq->lock, flags);
373}
374
375static void __enable_runtime(struct rq *rq)
376{
377 struct root_domain *rd = rq->rd;
378 struct rt_rq *rt_rq;
379
380 if (unlikely(!scheduler_running))
381 return;
382
383 for_each_leaf_rt_rq(rt_rq, rq) {
384 struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq);
385
386 spin_lock(&rt_b->rt_runtime_lock);
387 spin_lock(&rt_rq->rt_runtime_lock);
388 rt_rq->rt_runtime = rt_b->rt_runtime;
389 rt_rq->rt_time = 0;
390 spin_unlock(&rt_rq->rt_runtime_lock);
391 spin_unlock(&rt_b->rt_runtime_lock);
392 }
393}
394
395static void enable_runtime(struct rq *rq)
396{
397 unsigned long flags;
398
399 spin_lock_irqsave(&rq->lock, flags);
400 __enable_runtime(rq);
401 spin_unlock_irqrestore(&rq->lock, flags);
402}
403
308#endif 404#endif
309 405
310static inline int rt_se_prio(struct sched_rt_entity *rt_se) 406static inline int rt_se_prio(struct sched_rt_entity *rt_se)
@@ -334,14 +430,13 @@ static int sched_rt_runtime_exceeded(struct rt_rq *rt_rq)
334 430
335#ifdef CONFIG_SMP 431#ifdef CONFIG_SMP
336 if (rt_rq->rt_time > runtime) { 432 if (rt_rq->rt_time > runtime) {
337 int more;
338
339 spin_unlock(&rt_rq->rt_runtime_lock); 433 spin_unlock(&rt_rq->rt_runtime_lock);
340 more = balance_runtime(rt_rq); 434 balance_runtime(rt_rq);
341 spin_lock(&rt_rq->rt_runtime_lock); 435 spin_lock(&rt_rq->rt_runtime_lock);
342 436
343 if (more) 437 runtime = sched_rt_runtime(rt_rq);
344 runtime = sched_rt_runtime(rt_rq); 438 if (runtime == RUNTIME_INF)
439 return 0;
345 } 440 }
346#endif 441#endif
347 442
@@ -1174,6 +1269,8 @@ static void rq_online_rt(struct rq *rq)
1174 if (rq->rt.overloaded) 1269 if (rq->rt.overloaded)
1175 rt_set_overload(rq); 1270 rt_set_overload(rq);
1176 1271
1272 __enable_runtime(rq);
1273
1177 cpupri_set(&rq->rd->cpupri, rq->cpu, rq->rt.highest_prio); 1274 cpupri_set(&rq->rd->cpupri, rq->cpu, rq->rt.highest_prio);
1178} 1275}
1179 1276
@@ -1183,6 +1280,8 @@ static void rq_offline_rt(struct rq *rq)
1183 if (rq->rt.overloaded) 1280 if (rq->rt.overloaded)
1184 rt_clear_overload(rq); 1281 rt_clear_overload(rq);
1185 1282
1283 __disable_runtime(rq);
1284
1186 cpupri_set(&rq->rd->cpupri, rq->cpu, CPUPRI_INVALID); 1285 cpupri_set(&rq->rd->cpupri, rq->cpu, CPUPRI_INVALID);
1187} 1286}
1188 1287