Pull scheduler fixes from Ingo Molnar: "Two smaller fixes - plus a context tracking tracing fix that is a bit bigger" * 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: tracing/context-tracking: Add preempt_schedule_context() for tracing sched: Fix clear NOHZ_BALANCE_KICK sched/x86: Construct all sibling maps if smt
Unified · Split
| @@ -372,15 +372,15 @@ static bool __cpuinit match_mc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) · 371 unmodified lines | ||
| 372 | 372 | |
| 373 | 373 | void __cpuinit set_cpu_sibling_map(int cpu) |
| 374 | 374 | { |
| 375 | − bool has_mc = boot_cpu_data.x86_max_cores > 1; | |
| 376 | 375 | bool has_smt = smp_num_siblings > 1; |
| 376 | + bool has_mp = has_smt || boot_cpu_data.x86_max_cores > 1; | |
| 377 | 377 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
| 378 | 378 | struct cpuinfo_x86 *o; |
| 379 | 379 | int i; |
| 380 | 380 | |
| 381 | 381 | cpumask_set_cpu(cpu, cpu_sibling_setup_mask); |
| 382 | 382 | |
| 383 | − if (!has_smt && !has_mc) { | |
| 383 | + if (!has_mp) { | |
| 384 | 384 | cpumask_set_cpu(cpu, cpu_sibling_mask(cpu)); |
| 385 | 385 | cpumask_set_cpu(cpu, cpu_llc_shared_mask(cpu)); |
| 386 | 386 | cpumask_set_cpu(cpu, cpu_core_mask(cpu)); |
| @@ -394,7 +394,7 @@ void __cpuinit set_cpu_sibling_map(int cpu) · 7 unmodified lines | ||
| 394 | 394 | if ((i == cpu) || (has_smt && match_smt(c, o))) |
| 395 | 395 | link_mask(sibling, cpu, i); |
| 396 | 396 | |
| 397 | − if ((i == cpu) || (has_mc && match_llc(c, o))) | |
| 397 | + if ((i == cpu) || (has_mp && match_llc(c, o))) | |
| 398 | 398 | link_mask(llc_shared, cpu, i); |
| 399 | 399 | |
| 400 | 400 | } |
| @@ -406,7 +406,7 @@ void __cpuinit set_cpu_sibling_map(int cpu) · 5 unmodified lines | ||
| 406 | 406 | for_each_cpu(i, cpu_sibling_setup_mask) { |
| 407 | 407 | o = &cpu_data(i); |
| 408 | 408 | |
| 409 | − if ((i == cpu) || (has_mc && match_mc(c, o))) { | |
| 409 | + if ((i == cpu) || (has_mp && match_mc(c, o))) { | |
| 410 | 410 | link_mask(core, cpu, i); |
| 411 | 411 | |
| 412 | 412 | /* |
| @@ -33,9 +33,25 @@ do { \ · 32 unmodified lines | ||
| 33 | 33 | preempt_schedule(); \ |
| 34 | 34 | } while (0) |
| 35 | 35 | |
| 36 | +#ifdef CONFIG_CONTEXT_TRACKING | |
| 37 | + | |
| 38 | +void preempt_schedule_context(void); | |
| 39 | + | |
| 40 | +#define preempt_check_resched_context() \ | |
| 41 | +do { \ | |
| 42 | + if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \ | |
| 43 | + preempt_schedule_context(); \ | |
| 44 | +} while (0) | |
| 45 | +#else | |
| 46 | + | |
| 47 | +#define preempt_check_resched_context() preempt_check_resched() | |
| 48 | + | |
| 49 | +#endif /* CONFIG_CONTEXT_TRACKING */ | |
| 50 | + | |
| 36 | 51 | #else /* !CONFIG_PREEMPT */ |
| 37 | 52 | |
| 38 | 53 | #define preempt_check_resched() do { } while (0) |
| 54 | +#define preempt_check_resched_context() do { } while (0) | |
| 39 | 55 | |
| 40 | 56 | #endif /* CONFIG_PREEMPT */ |
| 41 | 57 | |
| @@ -88,7 +104,7 @@ do { \ · 46 unmodified lines | ||
| 88 | 104 | do { \ |
| 89 | 105 | preempt_enable_no_resched_notrace(); \ |
| 90 | 106 | barrier(); \ |
| 91 | − preempt_check_resched(); \ | |
| 107 | + preempt_check_resched_context(); \ | |
| 92 | 108 | } while (0) |
| 93 | 109 | |
| 94 | 110 | #else /* !CONFIG_PREEMPT_COUNT */ |
| @@ -70,6 +70,46 @@ void user_enter(void) · 69 unmodified lines | ||
| 70 | 70 | local_irq_restore(flags); |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | +#ifdef CONFIG_PREEMPT | |
| 74 | +/** | |
| 75 | + * preempt_schedule_context - preempt_schedule called by tracing | |
| 76 | + * | |
| 77 | + * The tracing infrastructure uses preempt_enable_notrace to prevent | |
| 78 | + * recursion and tracing preempt enabling caused by the tracing | |
| 79 | + * infrastructure itself. But as tracing can happen in areas coming | |
| 80 | + * from userspace or just about to enter userspace, a preempt enable | |
| 81 | + * can occur before user_exit() is called. This will cause the scheduler | |
| 82 | + * to be called when the system is still in usermode. | |
| 83 | + * | |
| 84 | + * To prevent this, the preempt_enable_notrace will use this function | |
| 85 | + * instead of preempt_schedule() to exit user context if needed before | |
| 86 | + * calling the scheduler. | |
| 87 | + */ | |
| 88 | +void __sched notrace preempt_schedule_context(void) | |
| 89 | +{ | |
| 90 | + struct thread_info *ti = current_thread_info(); | |
| 91 | + enum ctx_state prev_ctx; | |
| 92 | + | |
| 93 | + if (likely(ti->preempt_count || irqs_disabled())) | |
| 94 | + return; | |
| 95 | + | |
| 96 | + /* | |
| 97 | + * Need to disable preemption in case user_exit() is traced | |
| 98 | + * and the tracer calls preempt_enable_notrace() causing | |
| 99 | + * an infinite recursion. | |
| 100 | + */ | |
| 101 | + preempt_disable_notrace(); | |
| 102 | + prev_ctx = exception_enter(); | |
| 103 | + preempt_enable_no_resched_notrace(); | |
| 104 | + | |
| 105 | + preempt_schedule(); | |
| 106 | + | |
| 107 | + preempt_disable_notrace(); | |
| 108 | + exception_exit(prev_ctx); | |
| 109 | + preempt_enable_notrace(); | |
| 110 | +} | |
| 111 | +EXPORT_SYMBOL_GPL(preempt_schedule_context); | |
| 112 | +#endif /* CONFIG_PREEMPT */ | |
| 73 | 113 | |
| 74 | 114 | /** |
| 75 | 115 | * user_exit - Inform the context tracking that the CPU is |
| @@ -633,7 +633,19 @@ void wake_up_nohz_cpu(int cpu) · 632 unmodified lines | ||
| 633 | 633 | static inline bool got_nohz_idle_kick(void) |
| 634 | 634 | { |
| 635 | 635 | int cpu = smp_processor_id(); |
| 636 | − return idle_cpu(cpu) && test_bit(NOHZ_BALANCE_KICK, nohz_flags(cpu)); | |
| 636 | + | |
| 637 | + if (!test_bit(NOHZ_BALANCE_KICK, nohz_flags(cpu))) | |
| 638 | + return false; | |
| 639 | + | |
| 640 | + if (idle_cpu(cpu) && !need_resched()) | |
| 641 | + return true; | |
| 642 | + | |
| 643 | + /* | |
| 644 | + * We can't run Idle Load Balance on this CPU for this time so we | |
| 645 | + * cancel it and clear NOHZ_BALANCE_KICK | |
| 646 | + */ | |
| 647 | + clear_bit(NOHZ_BALANCE_KICK, nohz_flags(cpu)); | |
| 648 | + return false; | |
| 637 | 649 | } |
| 638 | 650 | |
| 639 | 651 | #else /* CONFIG_NO_HZ_COMMON */ |
| @@ -1393,8 +1405,9 @@ static void sched_ttwu_pending(void) · 753 unmodified lines | ||
| 1393 | 1405 | |
| 1394 | 1406 | void scheduler_ipi(void) |
| 1395 | 1407 | { |
| 1396 | − if (llist_empty(&this_rq()->wake_list) && !got_nohz_idle_kick() | |
| 1397 | − && !tick_nohz_full_cpu(smp_processor_id())) | |
| 1408 | + if (llist_empty(&this_rq()->wake_list) | |
| 1409 | + && !tick_nohz_full_cpu(smp_processor_id()) | |
| 1410 | + && !got_nohz_idle_kick()) | |
| 1398 | 1411 | return; |
| 1399 | 1412 | |
| 1400 | 1413 | /* |
| @@ -1417,7 +1430,7 @@ void scheduler_ipi(void) · 16 unmodified lines | ||
| 1417 | 1430 | /* |
| 1418 | 1431 | * Check if someone kicked us for doing the nohz idle load balance. |
| 1419 | 1432 | */ |
| 1420 | − if (unlikely(got_nohz_idle_kick() && !need_resched())) { | |
| 1433 | + if (unlikely(got_nohz_idle_kick())) { | |
| 1421 | 1434 | this_rq()->idle_balance = 1; |
| 1422 | 1435 | raise_softirq_irqoff(SCHED_SOFTIRQ); |
| 1423 | 1436 | } |