diff options
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 | ||
