scheduler changes for v3.12
Subsystems (3)
Linus,
Please pull the latest sched-core-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git sched-core-for-linus
HEAD: 10866e62e8a6907d9072f10f9a0561db0c0cf50b sched/fair: Fix the sd_parent_degenerate() code
Various optimizations, cleanups and smaller fixes - no major changes in scheduler behavior.
Thanks,
Ingo
------------------>
Christoph Lameter (1):
sched/cputime: Use this_cpu_add() in task_group_account_field()
Joonsoo Kim (3):
sched: Remove one division operation in find_busiest_queue()
sched: Factor out code to should_we_balance()
sched: Clean-up struct sd_lb_stat
Kirill Tkhai (2):
sched/__wake_up_sync_key(): Fix nr_exclusive tasks which lead to WF_SYNC clearing sched/fair: Cleanup: remove duplicate variable declaration
Peter Zijlstra (6):
sched/fair: Shrink sg_lb_stats and play memset games sched/fair: Remove duplicate load_per_task computations sched/fair: Make group power more consistent sched/fair: Optimize find_busiest_queue() sched/fair: Rework and comment the group_imb code sched/fair: Fix the sd_parent_degenerate() code
Rik van Riel (1):
sched/x86: Optimize switch_mm() for multi-threaded workloads
Tom Rini (1):
numa: Mark __node_set() as __always_inline
Xiaotian Feng (1):
cpumask: Fix cpumask leak in partition_sched_domains()
Xie XiuQi (1):
generic-ipi: Kill unnecessary variable - csd_flags
arch/x86/include/asm/mmu_context.h | 20 +- include/linux/nodemask.h | 11 +- kernel/sched/core.c | 17 +- kernel/sched/cputime.c | 2 +- kernel/sched/fair.c | 511 +++++++++++++++++++++---------------- kernel/smp.c | 14 +- 6 files changed, 326 insertions(+), 249 deletions(-)
arch/x86/include/asm/mmu_context.h +13 -7
@@ -45,22 +45,28 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,/* Re-load page tables */ load_cr3 (next->pgd); -/* stop flush ipis for the previous mm */ +/* Stop flush ipis for the previous mm */ cpumask_clear_cpu (cpu,mm_cpumask (prev)); -/* -* load the LDT, if the LDT is different: -*/ +/* Load the LDT, if the LDT is different: */ if (unlikely (prev->context.ldt != next->context.ldt))load_LDT_nolock (&next->context); }#ifdef CONFIG_SMP - else { + else {this_cpu_write (cpu_tlbstate.state,TLBSTATE_OK );BUG_ON (this_cpu_read (cpu_tlbstate.active_mm) != next); -if (!cpumask_test_and_set_cpu (cpu,mm_cpumask (next))) { -/* We were in lazy tlb mode and leave_mm disabled +if (!cpumask_test_cpu (cpu,mm_cpumask (next))) { +/* +* On established mms, the mm_cpumask is only changed +* from irq context, from ptep_clear_flush() while in +* lazy tlb mode, and here. Irqs are blocked during +* schedule, protecting us from simultaneous changes. +*/ +cpumask_set_cpu (cpu,mm_cpumask (next)); +/* +* We were in lazy tlb mode and leave_mm disabled * tlb flush IPI delivery. We must reload CR3 * to make sure to use no freed page tables. */
include/linux/nodemask.h +10 -1
@@ -98,8 +98,17 @@ typedef struct { DECLARE_BITMAP(bits, MAX_NUMNODES); } nodemask_t;extern nodemask_t _unused_nodemask_arg_; +/* +* The inline keyword gives the compiler room to decide to inline, or +* not inline a function as it sees best. However, as these functions +* are called in both __init and non-__init functions, if they are not +* inlined we will end up with a section mis-match error (of the type of +* freeable items not being freed). So we must use __always_inline here +* to fix the problem. If other functions in the future also end up in +* this situation they will also need to be annotated as __always_inline +*/ #define node_set (node, dst) __node_set((node), &(dst)) -static inline void __node_set (int node,volatile nodemask_t *dstp) +static __always_inline void __node_set(int node, volatile nodemask_t *dstp) {set_bit (node, dstp->bits); }
kernel/sched/core.c +13 -4
@@ -2660,7 +2660,7 @@ void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode,if (unlikely (!q))return ; -if (unlikely (!nr_exclusive)) +if (unlikely (nr_exclusive !=1 )) wake_flags =0 ;spin_lock_irqsave (&q->lock, flags);
@@ -4914,7 +4914,8 @@ sd_parent_degenerate(struct sched_domain *sd, struct sched_domain *parent)SD_BALANCE_FORK |SD_BALANCE_EXEC |SD_SHARE_CPUPOWER | - SD_SHARE_PKG_RESOURCES); +SD_SHARE_PKG_RESOURCES | + SD_PREFER_SIBLING);if (nr_node_ids ==1 ) pflags &= ~SD_SERIALIZE ; }
@@ -5118,6 +5119,13 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu) tmp->parent = parent->parent;if (parent->parent) parent->parent->child = tmp; +/* +* Transfer SD_PREFER_SIBLING down in case of a +* degenerate parent; the spans match for this +* so the property transfers. +*/ +if (parent->flags &SD_PREFER_SIBLING ) + tmp->flags |=SD_PREFER_SIBLING ;destroy_sched_domain (parent, cpu); }else tmp = tmp->parent;
@@ -6184,8 +6192,9 @@ match1: ; } + n = ndoms_cur;if (doms_new ==NULL ) { - ndoms_cur =0 ; + n =0 ; doms_new = &fallback_doms;cpumask_andnot (doms_new[0 ], cpu_active_mask, cpu_isolated_map);WARN_ON_ONCE (dattr_new);
@@ -6193,7 +6202,7 @@ match1:/* Build new domains */ for (i =0 ; i < ndoms_new; i++) { -for (j =0 ; j < ndoms_cur && !new_topology; j++) { +for (j =0 ; j < n && !new_topology; j++) {if (cpumask_equal (doms_new[i], doms_cur[j]) &&dattrs_equal (dattr_new, i, dattr_cur, j)) goto match2;
kernel/sched/cputime.c +1 -1
@@ -121,7 +121,7 @@ static inline void task_group_account_field(struct task_struct *p, int index,* is the only cgroup, then nothing else should be necessary. * */ -__get_cpu_var (kernel_cpustat).cpustat[index] += tmp; +__this_cpu_add (kernel_cpustat.cpustat[index], tmp);cpuacct_account_field (p, index, tmp); }
kernel/sched/fair.c +288 -223
814 lines not on this page · raw message
kernel/smp.c +1 -13
@@ -186,25 +186,13 @@ void generic_smp_call_function_single_interrupt(void)while (!list_empty (&list)) {struct call_single_data *csd; -unsigned int csd_flags; csd = list_entry(list.next, struct call_single_data, list);list_del (&csd->list); -/* -* 'csd' can be invalid after this call if flags == 0 -* (when called through generic_exec_single()), -* so save them away before making the call: -*/ - csd_flags = csd->flags; - csd->func (csd->info); -/* -* Unlocked CSDs are valid through generic_exec_single(): -*/ -if (csd_flags &CSD_FLAG_LOCK ) -csd_unlock (csd); +csd_unlock (csd); } }