diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-21 15:55:43 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-21 15:55:43 -0400 |
commit | bc4016f48161454a9a8e5eb209b0693c6cde9f62 (patch) | |
tree | f470f5d711e975b152eec90282f5dd30a1d5dba5 /kernel/sched.c | |
parent | 5d70f79b5ef6ea2de4f72a37b2d96e2601e40a22 (diff) | |
parent | b7dadc38797584f6203386da1947ed5edf516646 (diff) |
Merge branch 'sched-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'sched-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (29 commits)
sched: Export account_system_vtime()
sched: Call tick_check_idle before __irq_enter
sched: Remove irq time from available CPU power
sched: Do not account irq time to current task
x86: Add IRQ_TIME_ACCOUNTING
sched: Add IRQ_TIME_ACCOUNTING, finer accounting of irq time
sched: Add a PF flag for ksoftirqd identification
sched: Consolidate account_system_vtime extern declaration
sched: Fix softirq time accounting
sched: Drop group_capacity to 1 only if local group has extra capacity
sched: Force balancing on newidle balance if local group has capacity
sched: Set group_imb only a task can be pulled from the busiest cpu
sched: Do not consider SCHED_IDLE tasks to be cache hot
sched: Drop all load weight manipulation for RT tasks
sched: Create special class for stop/migrate work
sched: Unindent labels
sched: Comment updates: fix default latency and granularity numbers
tracing/sched: Add sched_pi_setprio tracepoint
sched: Give CPU bound RT tasks preference
sched: Try not to migrate higher priority RT tasks
...
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 291 |
1 files changed, 246 insertions, 45 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 5a5cc33e4999..d42992bccdfa 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -426,9 +426,7 @@ struct root_domain { | |||
426 | */ | 426 | */ |
427 | cpumask_var_t rto_mask; | 427 | cpumask_var_t rto_mask; |
428 | atomic_t rto_count; | 428 | atomic_t rto_count; |
429 | #ifdef CONFIG_SMP | ||
430 | struct cpupri cpupri; | 429 | struct cpupri cpupri; |
431 | #endif | ||
432 | }; | 430 | }; |
433 | 431 | ||
434 | /* | 432 | /* |
@@ -437,7 +435,7 @@ struct root_domain { | |||
437 | */ | 435 | */ |
438 | static struct root_domain def_root_domain; | 436 | static struct root_domain def_root_domain; |
439 | 437 | ||
440 | #endif | 438 | #endif /* CONFIG_SMP */ |
441 | 439 | ||
442 | /* | 440 | /* |
443 | * This is the main, per-CPU runqueue data structure. | 441 | * This is the main, per-CPU runqueue data structure. |
@@ -488,11 +486,12 @@ struct rq { | |||
488 | */ | 486 | */ |
489 | unsigned long nr_uninterruptible; | 487 | unsigned long nr_uninterruptible; |
490 | 488 | ||
491 | struct task_struct *curr, *idle; | 489 | struct task_struct *curr, *idle, *stop; |
492 | unsigned long next_balance; | 490 | unsigned long next_balance; |
493 | struct mm_struct *prev_mm; | 491 | struct mm_struct *prev_mm; |
494 | 492 | ||
495 | u64 clock; | 493 | u64 clock; |
494 | u64 clock_task; | ||
496 | 495 | ||
497 | atomic_t nr_iowait; | 496 | atomic_t nr_iowait; |
498 | 497 | ||
@@ -520,6 +519,10 @@ struct rq { | |||
520 | u64 avg_idle; | 519 | u64 avg_idle; |
521 | #endif | 520 | #endif |
522 | 521 | ||
522 | #ifdef CONFIG_IRQ_TIME_ACCOUNTING | ||
523 | u64 prev_irq_time; | ||
524 | #endif | ||
525 | |||
523 | /* calc_load related fields */ | 526 | /* calc_load related fields */ |
524 | unsigned long calc_load_update; | 527 | unsigned long calc_load_update; |
525 | long calc_load_active; | 528 | long calc_load_active; |
@@ -643,10 +646,22 @@ static inline struct task_group *task_group(struct task_struct *p) | |||
643 | 646 | ||
644 | #endif /* CONFIG_CGROUP_SCHED */ | 647 | #endif /* CONFIG_CGROUP_SCHED */ |
645 | 648 | ||
649 | static u64 irq_time_cpu(int cpu); | ||
650 | static void sched_irq_time_avg_update(struct rq *rq, u64 irq_time); | ||
651 | |||
646 | inline void update_rq_clock(struct rq *rq) | 652 | inline void update_rq_clock(struct rq *rq) |
647 | { | 653 | { |
648 | if (!rq->skip_clock_update) | 654 | if (!rq->skip_clock_update) { |
649 | rq->clock = sched_clock_cpu(cpu_of(rq)); | 655 | int cpu = cpu_of(rq); |
656 | u64 irq_time; | ||
657 | |||
658 | rq->clock = sched_clock_cpu(cpu); | ||
659 | irq_time = irq_time_cpu(cpu); | ||
660 | if (rq->clock - irq_time > rq->clock_task) | ||
661 | rq->clock_task = rq->clock - irq_time; | ||
662 | |||
663 | sched_irq_time_avg_update(rq, irq_time); | ||
664 | } | ||
650 | } | 665 | } |
651 | 666 | ||
652 | /* | 667 | /* |
@@ -723,7 +738,7 @@ sched_feat_write(struct file *filp, const char __user *ubuf, | |||
723 | size_t cnt, loff_t *ppos) | 738 | size_t cnt, loff_t *ppos) |
724 | { | 739 | { |
725 | char buf[64]; | 740 | char buf[64]; |
726 | char *cmp = buf; | 741 | char *cmp; |
727 | int neg = 0; | 742 | int neg = 0; |
728 | int i; | 743 | int i; |
729 | 744 | ||
@@ -734,6 +749,7 @@ sched_feat_write(struct file *filp, const char __user *ubuf, | |||
734 | return -EFAULT; | 749 | return -EFAULT; |
735 | 750 | ||
736 | buf[cnt] = 0; | 751 | buf[cnt] = 0; |
752 | cmp = strstrip(buf); | ||
737 | 753 | ||
738 | if (strncmp(buf, "NO_", 3) == 0) { | 754 | if (strncmp(buf, "NO_", 3) == 0) { |
739 | neg = 1; | 755 | neg = 1; |
@@ -741,9 +757,7 @@ sched_feat_write(struct file *filp, const char __user *ubuf, | |||
741 | } | 757 | } |
742 | 758 | ||
743 | for (i = 0; sched_feat_names[i]; i++) { | 759 | for (i = 0; sched_feat_names[i]; i++) { |
744 | int len = strlen(sched_feat_names[i]); | 760 | if (strcmp(cmp, sched_feat_names[i]) == 0) { |
745 | |||
746 | if (strncmp(cmp, sched_feat_names[i], len) == 0) { | ||
747 | if (neg) | 761 | if (neg) |
748 | sysctl_sched_features &= ~(1UL << i); | 762 | sysctl_sched_features &= ~(1UL << i); |
749 | else | 763 | else |
@@ -1840,7 +1854,7 @@ static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu) | |||
1840 | 1854 | ||
1841 | static const struct sched_class rt_sched_class; | 1855 | static const struct sched_class rt_sched_class; |
1842 | 1856 | ||
1843 | #define sched_class_highest (&rt_sched_class) | 1857 | #define sched_class_highest (&stop_sched_class) |
1844 | #define for_each_class(class) \ | 1858 | #define for_each_class(class) \ |
1845 | for (class = sched_class_highest; class; class = class->next) | 1859 | for (class = sched_class_highest; class; class = class->next) |
1846 | 1860 | ||
@@ -1858,12 +1872,6 @@ static void dec_nr_running(struct rq *rq) | |||
1858 | 1872 | ||
1859 | static void set_load_weight(struct task_struct *p) | 1873 | static void set_load_weight(struct task_struct *p) |
1860 | { | 1874 | { |
1861 | if (task_has_rt_policy(p)) { | ||
1862 | p->se.load.weight = 0; | ||
1863 | p->se.load.inv_weight = WMULT_CONST; | ||
1864 | return; | ||
1865 | } | ||
1866 | |||
1867 | /* | 1875 | /* |
1868 | * SCHED_IDLE tasks get minimal weight: | 1876 | * SCHED_IDLE tasks get minimal weight: |
1869 | */ | 1877 | */ |
@@ -1917,13 +1925,132 @@ static void deactivate_task(struct rq *rq, struct task_struct *p, int flags) | |||
1917 | dec_nr_running(rq); | 1925 | dec_nr_running(rq); |
1918 | } | 1926 | } |
1919 | 1927 | ||
1928 | #ifdef CONFIG_IRQ_TIME_ACCOUNTING | ||
1929 | |||
1930 | /* | ||
1931 | * There are no locks covering percpu hardirq/softirq time. | ||
1932 | * They are only modified in account_system_vtime, on corresponding CPU | ||
1933 | * with interrupts disabled. So, writes are safe. | ||
1934 | * They are read and saved off onto struct rq in update_rq_clock(). | ||
1935 | * This may result in other CPU reading this CPU's irq time and can | ||
1936 | * race with irq/account_system_vtime on this CPU. We would either get old | ||
1937 | * or new value (or semi updated value on 32 bit) with a side effect of | ||
1938 | * accounting a slice of irq time to wrong task when irq is in progress | ||
1939 | * while we read rq->clock. That is a worthy compromise in place of having | ||
1940 | * locks on each irq in account_system_time. | ||
1941 | */ | ||
1942 | static DEFINE_PER_CPU(u64, cpu_hardirq_time); | ||
1943 | static DEFINE_PER_CPU(u64, cpu_softirq_time); | ||
1944 | |||
1945 | static DEFINE_PER_CPU(u64, irq_start_time); | ||
1946 | static int sched_clock_irqtime; | ||
1947 | |||
1948 | void enable_sched_clock_irqtime(void) | ||
1949 | { | ||
1950 | sched_clock_irqtime = 1; | ||
1951 | } | ||
1952 | |||
1953 | void disable_sched_clock_irqtime(void) | ||
1954 | { | ||
1955 | sched_clock_irqtime = 0; | ||
1956 | } | ||
1957 | |||
1958 | static u64 irq_time_cpu(int cpu) | ||
1959 | { | ||
1960 | if (!sched_clock_irqtime) | ||
1961 | return 0; | ||
1962 | |||
1963 | return per_cpu(cpu_softirq_time, cpu) + per_cpu(cpu_hardirq_time, cpu); | ||
1964 | } | ||
1965 | |||
1966 | void account_system_vtime(struct task_struct *curr) | ||
1967 | { | ||
1968 | unsigned long flags; | ||
1969 | int cpu; | ||
1970 | u64 now, delta; | ||
1971 | |||
1972 | if (!sched_clock_irqtime) | ||
1973 | return; | ||
1974 | |||
1975 | local_irq_save(flags); | ||
1976 | |||
1977 | cpu = smp_processor_id(); | ||
1978 | now = sched_clock_cpu(cpu); | ||
1979 | delta = now - per_cpu(irq_start_time, cpu); | ||
1980 | per_cpu(irq_start_time, cpu) = now; | ||
1981 | /* | ||
1982 | * We do not account for softirq time from ksoftirqd here. | ||
1983 | * We want to continue accounting softirq time to ksoftirqd thread | ||
1984 | * in that case, so as not to confuse scheduler with a special task | ||
1985 | * that do not consume any time, but still wants to run. | ||
1986 | */ | ||
1987 | if (hardirq_count()) | ||
1988 | per_cpu(cpu_hardirq_time, cpu) += delta; | ||
1989 | else if (in_serving_softirq() && !(curr->flags & PF_KSOFTIRQD)) | ||
1990 | per_cpu(cpu_softirq_time, cpu) += delta; | ||
1991 | |||
1992 | local_irq_restore(flags); | ||
1993 | } | ||
1994 | EXPORT_SYMBOL_GPL(account_system_vtime); | ||
1995 | |||
1996 | static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time) | ||
1997 | { | ||
1998 | if (sched_clock_irqtime && sched_feat(NONIRQ_POWER)) { | ||
1999 | u64 delta_irq = curr_irq_time - rq->prev_irq_time; | ||
2000 | rq->prev_irq_time = curr_irq_time; | ||
2001 | sched_rt_avg_update(rq, delta_irq); | ||
2002 | } | ||
2003 | } | ||
2004 | |||
2005 | #else | ||
2006 | |||
2007 | static u64 irq_time_cpu(int cpu) | ||
2008 | { | ||
2009 | return 0; | ||
2010 | } | ||
2011 | |||
2012 | static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time) { } | ||
2013 | |||
2014 | #endif | ||
2015 | |||
1920 | #include "sched_idletask.c" | 2016 | #include "sched_idletask.c" |
1921 | #include "sched_fair.c" | 2017 | #include "sched_fair.c" |
1922 | #include "sched_rt.c" | 2018 | #include "sched_rt.c" |
2019 | #include "sched_stoptask.c" | ||
1923 | #ifdef CONFIG_SCHED_DEBUG | 2020 | #ifdef CONFIG_SCHED_DEBUG |
1924 | # include "sched_debug.c" | 2021 | # include "sched_debug.c" |
1925 | #endif | 2022 | #endif |
1926 | 2023 | ||
2024 | void sched_set_stop_task(int cpu, struct task_struct *stop) | ||
2025 | { | ||
2026 | struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 }; | ||
2027 | struct task_struct *old_stop = cpu_rq(cpu)->stop; | ||
2028 | |||
2029 | if (stop) { | ||
2030 | /* | ||
2031 | * Make it appear like a SCHED_FIFO task, its something | ||
2032 | * userspace knows about and won't get confused about. | ||
2033 | * | ||
2034 | * Also, it will make PI more or less work without too | ||
2035 | * much confusion -- but then, stop work should not | ||
2036 | * rely on PI working anyway. | ||
2037 | */ | ||
2038 | sched_setscheduler_nocheck(stop, SCHED_FIFO, ¶m); | ||
2039 | |||
2040 | stop->sched_class = &stop_sched_class; | ||
2041 | } | ||
2042 | |||
2043 | cpu_rq(cpu)->stop = stop; | ||
2044 | |||
2045 | if (old_stop) { | ||
2046 | /* | ||
2047 | * Reset it back to a normal scheduling class so that | ||
2048 | * it can die in pieces. | ||
2049 | */ | ||
2050 | old_stop->sched_class = &rt_sched_class; | ||
2051 | } | ||
2052 | } | ||
2053 | |||
1927 | /* | 2054 | /* |
1928 | * __normal_prio - return the priority that is based on the static prio | 2055 | * __normal_prio - return the priority that is based on the static prio |
1929 | */ | 2056 | */ |
@@ -2003,6 +2130,9 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd) | |||
2003 | if (p->sched_class != &fair_sched_class) | 2130 | if (p->sched_class != &fair_sched_class) |
2004 | return 0; | 2131 | return 0; |
2005 | 2132 | ||
2133 | if (unlikely(p->policy == SCHED_IDLE)) | ||
2134 | return 0; | ||
2135 | |||
2006 | /* | 2136 | /* |
2007 | * Buddy candidates are cache hot: | 2137 | * Buddy candidates are cache hot: |
2008 | */ | 2138 | */ |
@@ -2852,14 +2982,14 @@ context_switch(struct rq *rq, struct task_struct *prev, | |||
2852 | */ | 2982 | */ |
2853 | arch_start_context_switch(prev); | 2983 | arch_start_context_switch(prev); |
2854 | 2984 | ||
2855 | if (likely(!mm)) { | 2985 | if (!mm) { |
2856 | next->active_mm = oldmm; | 2986 | next->active_mm = oldmm; |
2857 | atomic_inc(&oldmm->mm_count); | 2987 | atomic_inc(&oldmm->mm_count); |
2858 | enter_lazy_tlb(oldmm, next); | 2988 | enter_lazy_tlb(oldmm, next); |
2859 | } else | 2989 | } else |
2860 | switch_mm(oldmm, mm, next); | 2990 | switch_mm(oldmm, mm, next); |
2861 | 2991 | ||
2862 | if (likely(!prev->mm)) { | 2992 | if (!prev->mm) { |
2863 | prev->active_mm = NULL; | 2993 | prev->active_mm = NULL; |
2864 | rq->prev_mm = oldmm; | 2994 | rq->prev_mm = oldmm; |
2865 | } | 2995 | } |
@@ -3248,7 +3378,7 @@ static u64 do_task_delta_exec(struct task_struct *p, struct rq *rq) | |||
3248 | 3378 | ||
3249 | if (task_current(rq, p)) { | 3379 | if (task_current(rq, p)) { |
3250 | update_rq_clock(rq); | 3380 | update_rq_clock(rq); |
3251 | ns = rq->clock - p->se.exec_start; | 3381 | ns = rq->clock_task - p->se.exec_start; |
3252 | if ((s64)ns < 0) | 3382 | if ((s64)ns < 0) |
3253 | ns = 0; | 3383 | ns = 0; |
3254 | } | 3384 | } |
@@ -3397,7 +3527,7 @@ void account_system_time(struct task_struct *p, int hardirq_offset, | |||
3397 | tmp = cputime_to_cputime64(cputime); | 3527 | tmp = cputime_to_cputime64(cputime); |
3398 | if (hardirq_count() - hardirq_offset) | 3528 | if (hardirq_count() - hardirq_offset) |
3399 | cpustat->irq = cputime64_add(cpustat->irq, tmp); | 3529 | cpustat->irq = cputime64_add(cpustat->irq, tmp); |
3400 | else if (softirq_count()) | 3530 | else if (in_serving_softirq()) |
3401 | cpustat->softirq = cputime64_add(cpustat->softirq, tmp); | 3531 | cpustat->softirq = cputime64_add(cpustat->softirq, tmp); |
3402 | else | 3532 | else |
3403 | cpustat->system = cputime64_add(cpustat->system, tmp); | 3533 | cpustat->system = cputime64_add(cpustat->system, tmp); |
@@ -3723,17 +3853,13 @@ pick_next_task(struct rq *rq) | |||
3723 | return p; | 3853 | return p; |
3724 | } | 3854 | } |
3725 | 3855 | ||
3726 | class = sched_class_highest; | 3856 | for_each_class(class) { |
3727 | for ( ; ; ) { | ||
3728 | p = class->pick_next_task(rq); | 3857 | p = class->pick_next_task(rq); |
3729 | if (p) | 3858 | if (p) |
3730 | return p; | 3859 | return p; |
3731 | /* | ||
3732 | * Will never be NULL as the idle class always | ||
3733 | * returns a non-NULL p: | ||
3734 | */ | ||
3735 | class = class->next; | ||
3736 | } | 3860 | } |
3861 | |||
3862 | BUG(); /* the idle class will always have a runnable task */ | ||
3737 | } | 3863 | } |
3738 | 3864 | ||
3739 | /* | 3865 | /* |
@@ -4358,6 +4484,7 @@ void rt_mutex_setprio(struct task_struct *p, int prio) | |||
4358 | 4484 | ||
4359 | rq = task_rq_lock(p, &flags); | 4485 | rq = task_rq_lock(p, &flags); |
4360 | 4486 | ||
4487 | trace_sched_pi_setprio(p, prio); | ||
4361 | oldprio = p->prio; | 4488 | oldprio = p->prio; |
4362 | prev_class = p->sched_class; | 4489 | prev_class = p->sched_class; |
4363 | on_rq = p->se.on_rq; | 4490 | on_rq = p->se.on_rq; |
@@ -4661,6 +4788,15 @@ recheck: | |||
4661 | */ | 4788 | */ |
4662 | rq = __task_rq_lock(p); | 4789 | rq = __task_rq_lock(p); |
4663 | 4790 | ||
4791 | /* | ||
4792 | * Changing the policy of the stop threads its a very bad idea | ||
4793 | */ | ||
4794 | if (p == rq->stop) { | ||
4795 | __task_rq_unlock(rq); | ||
4796 | raw_spin_unlock_irqrestore(&p->pi_lock, flags); | ||
4797 | return -EINVAL; | ||
4798 | } | ||
4799 | |||
4664 | #ifdef CONFIG_RT_GROUP_SCHED | 4800 | #ifdef CONFIG_RT_GROUP_SCHED |
4665 | if (user) { | 4801 | if (user) { |
4666 | /* | 4802 | /* |
@@ -4893,7 +5029,7 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask) | |||
4893 | 5029 | ||
4894 | cpuset_cpus_allowed(p, cpus_allowed); | 5030 | cpuset_cpus_allowed(p, cpus_allowed); |
4895 | cpumask_and(new_mask, in_mask, cpus_allowed); | 5031 | cpumask_and(new_mask, in_mask, cpus_allowed); |
4896 | again: | 5032 | again: |
4897 | retval = set_cpus_allowed_ptr(p, new_mask); | 5033 | retval = set_cpus_allowed_ptr(p, new_mask); |
4898 | 5034 | ||
4899 | if (!retval) { | 5035 | if (!retval) { |
@@ -6526,6 +6662,7 @@ struct s_data { | |||
6526 | cpumask_var_t nodemask; | 6662 | cpumask_var_t nodemask; |
6527 | cpumask_var_t this_sibling_map; | 6663 | cpumask_var_t this_sibling_map; |
6528 | cpumask_var_t this_core_map; | 6664 | cpumask_var_t this_core_map; |
6665 | cpumask_var_t this_book_map; | ||
6529 | cpumask_var_t send_covered; | 6666 | cpumask_var_t send_covered; |
6530 | cpumask_var_t tmpmask; | 6667 | cpumask_var_t tmpmask; |
6531 | struct sched_group **sched_group_nodes; | 6668 | struct sched_group **sched_group_nodes; |
@@ -6537,6 +6674,7 @@ enum s_alloc { | |||
6537 | sa_rootdomain, | 6674 | sa_rootdomain, |
6538 | sa_tmpmask, | 6675 | sa_tmpmask, |
6539 | sa_send_covered, | 6676 | sa_send_covered, |
6677 | sa_this_book_map, | ||
6540 | sa_this_core_map, | 6678 | sa_this_core_map, |
6541 | sa_this_sibling_map, | 6679 | sa_this_sibling_map, |
6542 | sa_nodemask, | 6680 | sa_nodemask, |
@@ -6572,31 +6710,48 @@ cpu_to_cpu_group(int cpu, const struct cpumask *cpu_map, | |||
6572 | #ifdef CONFIG_SCHED_MC | 6710 | #ifdef CONFIG_SCHED_MC |
6573 | static DEFINE_PER_CPU(struct static_sched_domain, core_domains); | 6711 | static DEFINE_PER_CPU(struct static_sched_domain, core_domains); |
6574 | static DEFINE_PER_CPU(struct static_sched_group, sched_group_core); | 6712 | static DEFINE_PER_CPU(struct static_sched_group, sched_group_core); |
6575 | #endif /* CONFIG_SCHED_MC */ | ||
6576 | 6713 | ||
6577 | #if defined(CONFIG_SCHED_MC) && defined(CONFIG_SCHED_SMT) | ||
6578 | static int | 6714 | static int |
6579 | cpu_to_core_group(int cpu, const struct cpumask *cpu_map, | 6715 | cpu_to_core_group(int cpu, const struct cpumask *cpu_map, |
6580 | struct sched_group **sg, struct cpumask *mask) | 6716 | struct sched_group **sg, struct cpumask *mask) |
6581 | { | 6717 | { |
6582 | int group; | 6718 | int group; |
6583 | 6719 | #ifdef CONFIG_SCHED_SMT | |
6584 | cpumask_and(mask, topology_thread_cpumask(cpu), cpu_map); | 6720 | cpumask_and(mask, topology_thread_cpumask(cpu), cpu_map); |
6585 | group = cpumask_first(mask); | 6721 | group = cpumask_first(mask); |
6722 | #else | ||
6723 | group = cpu; | ||
6724 | #endif | ||
6586 | if (sg) | 6725 | if (sg) |
6587 | *sg = &per_cpu(sched_group_core, group).sg; | 6726 | *sg = &per_cpu(sched_group_core, group).sg; |
6588 | return group; | 6727 | return group; |
6589 | } | 6728 | } |
6590 | #elif defined(CONFIG_SCHED_MC) | 6729 | #endif /* CONFIG_SCHED_MC */ |
6730 | |||
6731 | /* | ||
6732 | * book sched-domains: | ||
6733 | */ | ||
6734 | #ifdef CONFIG_SCHED_BOOK | ||
6735 | static DEFINE_PER_CPU(struct static_sched_domain, book_domains); | ||
6736 | static DEFINE_PER_CPU(struct static_sched_group, sched_group_book); | ||
6737 | |||
6591 | static int | 6738 | static int |
6592 | cpu_to_core_group(int cpu, const struct cpumask *cpu_map, | 6739 | cpu_to_book_group(int cpu, const struct cpumask *cpu_map, |
6593 | struct sched_group **sg, struct cpumask *unused) | 6740 | struct sched_group **sg, struct cpumask *mask) |
6594 | { | 6741 | { |
6742 | int group = cpu; | ||
6743 | #ifdef CONFIG_SCHED_MC | ||
6744 | cpumask_and(mask, cpu_coregroup_mask(cpu), cpu_map); | ||
6745 | group = cpumask_first(mask); | ||
6746 | #elif defined(CONFIG_SCHED_SMT) | ||
6747 | cpumask_and(mask, topology_thread_cpumask(cpu), cpu_map); | ||
6748 | group = cpumask_first(mask); | ||
6749 | #endif | ||
6595 | if (sg) | 6750 | if (sg) |
6596 | *sg = &per_cpu(sched_group_core, cpu).sg; | 6751 | *sg = &per_cpu(sched_group_book, group).sg; |
6597 | return cpu; | 6752 | return group; |
6598 | } | 6753 | } |
6599 | #endif | 6754 | #endif /* CONFIG_SCHED_BOOK */ |
6600 | 6755 | ||
6601 | static DEFINE_PER_CPU(struct static_sched_domain, phys_domains); | 6756 | static DEFINE_PER_CPU(struct static_sched_domain, phys_domains); |
6602 | static DEFINE_PER_CPU(struct static_sched_group, sched_group_phys); | 6757 | static DEFINE_PER_CPU(struct static_sched_group, sched_group_phys); |
@@ -6606,7 +6761,10 @@ cpu_to_phys_group(int cpu, const struct cpumask *cpu_map, | |||
6606 | struct sched_group **sg, struct cpumask *mask) | 6761 | struct sched_group **sg, struct cpumask *mask) |
6607 | { | 6762 | { |
6608 | int group; | 6763 | int group; |
6609 | #ifdef CONFIG_SCHED_MC | 6764 | #ifdef CONFIG_SCHED_BOOK |
6765 | cpumask_and(mask, cpu_book_mask(cpu), cpu_map); | ||
6766 | group = cpumask_first(mask); | ||
6767 | #elif defined(CONFIG_SCHED_MC) | ||
6610 | cpumask_and(mask, cpu_coregroup_mask(cpu), cpu_map); | 6768 | cpumask_and(mask, cpu_coregroup_mask(cpu), cpu_map); |
6611 | group = cpumask_first(mask); | 6769 | group = cpumask_first(mask); |
6612 | #elif defined(CONFIG_SCHED_SMT) | 6770 | #elif defined(CONFIG_SCHED_SMT) |
@@ -6867,6 +7025,9 @@ SD_INIT_FUNC(CPU) | |||
6867 | #ifdef CONFIG_SCHED_MC | 7025 | #ifdef CONFIG_SCHED_MC |
6868 | SD_INIT_FUNC(MC) | 7026 | SD_INIT_FUNC(MC) |
6869 | #endif | 7027 | #endif |
7028 | #ifdef CONFIG_SCHED_BOOK | ||
7029 | SD_INIT_FUNC(BOOK) | ||
7030 | #endif | ||
6870 | 7031 | ||
6871 | static int default_relax_domain_level = -1; | 7032 | static int default_relax_domain_level = -1; |
6872 | 7033 | ||
@@ -6916,6 +7077,8 @@ static void __free_domain_allocs(struct s_data *d, enum s_alloc what, | |||
6916 | free_cpumask_var(d->tmpmask); /* fall through */ | 7077 | free_cpumask_var(d->tmpmask); /* fall through */ |
6917 | case sa_send_covered: | 7078 | case sa_send_covered: |
6918 | free_cpumask_var(d->send_covered); /* fall through */ | 7079 | free_cpumask_var(d->send_covered); /* fall through */ |
7080 | case sa_this_book_map: | ||
7081 | free_cpumask_var(d->this_book_map); /* fall through */ | ||
6919 | case sa_this_core_map: | 7082 | case sa_this_core_map: |
6920 | free_cpumask_var(d->this_core_map); /* fall through */ | 7083 | free_cpumask_var(d->this_core_map); /* fall through */ |
6921 | case sa_this_sibling_map: | 7084 | case sa_this_sibling_map: |
@@ -6962,8 +7125,10 @@ static enum s_alloc __visit_domain_allocation_hell(struct s_data *d, | |||
6962 | return sa_nodemask; | 7125 | return sa_nodemask; |
6963 | if (!alloc_cpumask_var(&d->this_core_map, GFP_KERNEL)) | 7126 | if (!alloc_cpumask_var(&d->this_core_map, GFP_KERNEL)) |
6964 | return sa_this_sibling_map; | 7127 | return sa_this_sibling_map; |
6965 | if (!alloc_cpumask_var(&d->send_covered, GFP_KERNEL)) | 7128 | if (!alloc_cpumask_var(&d->this_book_map, GFP_KERNEL)) |
6966 | return sa_this_core_map; | 7129 | return sa_this_core_map; |
7130 | if (!alloc_cpumask_var(&d->send_covered, GFP_KERNEL)) | ||
7131 | return sa_this_book_map; | ||
6967 | if (!alloc_cpumask_var(&d->tmpmask, GFP_KERNEL)) | 7132 | if (!alloc_cpumask_var(&d->tmpmask, GFP_KERNEL)) |
6968 | return sa_send_covered; | 7133 | return sa_send_covered; |
6969 | d->rd = alloc_rootdomain(); | 7134 | d->rd = alloc_rootdomain(); |
@@ -7021,6 +7186,23 @@ static struct sched_domain *__build_cpu_sched_domain(struct s_data *d, | |||
7021 | return sd; | 7186 | return sd; |
7022 | } | 7187 | } |
7023 | 7188 | ||
7189 | static struct sched_domain *__build_book_sched_domain(struct s_data *d, | ||
7190 | const struct cpumask *cpu_map, struct sched_domain_attr *attr, | ||
7191 | struct sched_domain *parent, int i) | ||
7192 | { | ||
7193 | struct sched_domain *sd = parent; | ||
7194 | #ifdef CONFIG_SCHED_BOOK | ||
7195 | sd = &per_cpu(book_domains, i).sd; | ||
7196 | SD_INIT(sd, BOOK); | ||
7197 | set_domain_attribute(sd, attr); | ||
7198 | cpumask_and(sched_domain_span(sd), cpu_map, cpu_book_mask(i)); | ||
7199 | sd->parent = parent; | ||
7200 | parent->child = sd; | ||
7201 | cpu_to_book_group(i, cpu_map, &sd->groups, d->tmpmask); | ||
7202 | #endif | ||
7203 | return sd; | ||
7204 | } | ||
7205 | |||
7024 | static struct sched_domain *__build_mc_sched_domain(struct s_data *d, | 7206 | static struct sched_domain *__build_mc_sched_domain(struct s_data *d, |
7025 | const struct cpumask *cpu_map, struct sched_domain_attr *attr, | 7207 | const struct cpumask *cpu_map, struct sched_domain_attr *attr, |
7026 | struct sched_domain *parent, int i) | 7208 | struct sched_domain *parent, int i) |
@@ -7078,6 +7260,15 @@ static void build_sched_groups(struct s_data *d, enum sched_domain_level l, | |||
7078 | d->send_covered, d->tmpmask); | 7260 | d->send_covered, d->tmpmask); |
7079 | break; | 7261 | break; |
7080 | #endif | 7262 | #endif |
7263 | #ifdef CONFIG_SCHED_BOOK | ||
7264 | case SD_LV_BOOK: /* set up book groups */ | ||
7265 | cpumask_and(d->this_book_map, cpu_map, cpu_book_mask(cpu)); | ||
7266 | if (cpu == cpumask_first(d->this_book_map)) | ||
7267 | init_sched_build_groups(d->this_book_map, cpu_map, | ||
7268 | &cpu_to_book_group, | ||
7269 | d->send_covered, d->tmpmask); | ||
7270 | break; | ||
7271 | #endif | ||
7081 | case SD_LV_CPU: /* set up physical groups */ | 7272 | case SD_LV_CPU: /* set up physical groups */ |
7082 | cpumask_and(d->nodemask, cpumask_of_node(cpu), cpu_map); | 7273 | cpumask_and(d->nodemask, cpumask_of_node(cpu), cpu_map); |
7083 | if (!cpumask_empty(d->nodemask)) | 7274 | if (!cpumask_empty(d->nodemask)) |
@@ -7125,12 +7316,14 @@ static int __build_sched_domains(const struct cpumask *cpu_map, | |||
7125 | 7316 | ||
7126 | sd = __build_numa_sched_domains(&d, cpu_map, attr, i); | 7317 | sd = __build_numa_sched_domains(&d, cpu_map, attr, i); |
7127 | sd = __build_cpu_sched_domain(&d, cpu_map, attr, sd, i); | 7318 | sd = __build_cpu_sched_domain(&d, cpu_map, attr, sd, i); |
7319 | sd = __build_book_sched_domain(&d, cpu_map, attr, sd, i); | ||
7128 | sd = __build_mc_sched_domain(&d, cpu_map, attr, sd, i); | 7320 | sd = __build_mc_sched_domain(&d, cpu_map, attr, sd, i); |
7129 | sd = __build_smt_sched_domain(&d, cpu_map, attr, sd, i); | 7321 | sd = __build_smt_sched_domain(&d, cpu_map, attr, sd, i); |
7130 | } | 7322 | } |
7131 | 7323 | ||
7132 | for_each_cpu(i, cpu_map) { | 7324 | for_each_cpu(i, cpu_map) { |
7133 | build_sched_groups(&d, SD_LV_SIBLING, cpu_map, i); | 7325 | build_sched_groups(&d, SD_LV_SIBLING, cpu_map, i); |
7326 | build_sched_groups(&d, SD_LV_BOOK, cpu_map, i); | ||
7134 | build_sched_groups(&d, SD_LV_MC, cpu_map, i); | 7327 | build_sched_groups(&d, SD_LV_MC, cpu_map, i); |
7135 | } | 7328 | } |
7136 | 7329 | ||
@@ -7161,6 +7354,12 @@ static int __build_sched_domains(const struct cpumask *cpu_map, | |||
7161 | init_sched_groups_power(i, sd); | 7354 | init_sched_groups_power(i, sd); |
7162 | } | 7355 | } |
7163 | #endif | 7356 | #endif |
7357 | #ifdef CONFIG_SCHED_BOOK | ||
7358 | for_each_cpu(i, cpu_map) { | ||
7359 | sd = &per_cpu(book_domains, i).sd; | ||
7360 | init_sched_groups_power(i, sd); | ||
7361 | } | ||
7362 | #endif | ||
7164 | 7363 | ||
7165 | for_each_cpu(i, cpu_map) { | 7364 | for_each_cpu(i, cpu_map) { |
7166 | sd = &per_cpu(phys_domains, i).sd; | 7365 | sd = &per_cpu(phys_domains, i).sd; |
@@ -7186,6 +7385,8 @@ static int __build_sched_domains(const struct cpumask *cpu_map, | |||
7186 | sd = &per_cpu(cpu_domains, i).sd; | 7385 | sd = &per_cpu(cpu_domains, i).sd; |
7187 | #elif defined(CONFIG_SCHED_MC) | 7386 | #elif defined(CONFIG_SCHED_MC) |
7188 | sd = &per_cpu(core_domains, i).sd; | 7387 | sd = &per_cpu(core_domains, i).sd; |
7388 | #elif defined(CONFIG_SCHED_BOOK) | ||
7389 | sd = &per_cpu(book_domains, i).sd; | ||
7189 | #else | 7390 | #else |
7190 | sd = &per_cpu(phys_domains, i).sd; | 7391 | sd = &per_cpu(phys_domains, i).sd; |
7191 | #endif | 7392 | #endif |
@@ -8090,9 +8291,9 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent) | |||
8090 | 8291 | ||
8091 | return 1; | 8292 | return 1; |
8092 | 8293 | ||
8093 | err_free_rq: | 8294 | err_free_rq: |
8094 | kfree(cfs_rq); | 8295 | kfree(cfs_rq); |
8095 | err: | 8296 | err: |
8096 | return 0; | 8297 | return 0; |
8097 | } | 8298 | } |
8098 | 8299 | ||
@@ -8180,9 +8381,9 @@ int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent) | |||
8180 | 8381 | ||
8181 | return 1; | 8382 | return 1; |
8182 | 8383 | ||
8183 | err_free_rq: | 8384 | err_free_rq: |
8184 | kfree(rt_rq); | 8385 | kfree(rt_rq); |
8185 | err: | 8386 | err: |
8186 | return 0; | 8387 | return 0; |
8187 | } | 8388 | } |
8188 | 8389 | ||
@@ -8540,7 +8741,7 @@ static int tg_set_bandwidth(struct task_group *tg, | |||
8540 | raw_spin_unlock(&rt_rq->rt_runtime_lock); | 8741 | raw_spin_unlock(&rt_rq->rt_runtime_lock); |
8541 | } | 8742 | } |
8542 | raw_spin_unlock_irq(&tg->rt_bandwidth.rt_runtime_lock); | 8743 | raw_spin_unlock_irq(&tg->rt_bandwidth.rt_runtime_lock); |
8543 | unlock: | 8744 | unlock: |
8544 | read_unlock(&tasklist_lock); | 8745 | read_unlock(&tasklist_lock); |
8545 | mutex_unlock(&rt_constraints_mutex); | 8746 | mutex_unlock(&rt_constraints_mutex); |
8546 | 8747 | ||