Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

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

+78 -9
+4 -4
arch/x86/kernel/smpboot.c
··· 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 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 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 /*
+17 -1
include/linux/preempt.h
··· 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 ··· 104 88 do { \ 105 89 preempt_enable_no_resched_notrace(); \ 106 90 barrier(); \ 107 - preempt_check_resched(); \ 91 + preempt_check_resched_context(); \ 108 92 } while (0) 109 93 110 94 #else /* !CONFIG_PREEMPT_COUNT */
+40
kernel/context_tracking.c
··· 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
+17 -4
kernel/sched/core.c
··· 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 */ ··· 1405 1393 1406 1394 void scheduler_ipi(void) 1407 1395 { 1408 - if (llist_empty(&this_rq()->wake_list) && !got_nohz_idle_kick() 1409 - && !tick_nohz_full_cpu(smp_processor_id())) 1396 + if (llist_empty(&this_rq()->wake_list) 1397 + && !tick_nohz_full_cpu(smp_processor_id()) 1398 + && !got_nohz_idle_kick()) 1410 1399 return; 1411 1400 1412 1401 /* ··· 1430 1417 /* 1431 1418 * Check if someone kicked us for doing the nohz idle load balance. 1432 1419 */ 1433 - if (unlikely(got_nohz_idle_kick() && !need_resched())) { 1420 + if (unlikely(got_nohz_idle_kick())) { 1434 1421 this_rq()->idle_balance = 1; 1435 1422 raise_softirq_irqoff(SCHED_SOFTIRQ); 1436 1423 }