diff options
Diffstat (limited to 'kernel/sched.c')
| -rw-r--r-- | kernel/sched.c | 54 |
1 files changed, 45 insertions, 9 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 7f522832250c..5f64fed56a44 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
| @@ -486,7 +486,7 @@ struct rq { | |||
| 486 | */ | 486 | */ |
| 487 | unsigned long nr_uninterruptible; | 487 | unsigned long nr_uninterruptible; |
| 488 | 488 | ||
| 489 | struct task_struct *curr, *idle; | 489 | struct task_struct *curr, *idle, *stop; |
| 490 | unsigned long next_balance; | 490 | unsigned long next_balance; |
| 491 | struct mm_struct *prev_mm; | 491 | struct mm_struct *prev_mm; |
| 492 | 492 | ||
| @@ -1837,7 +1837,7 @@ static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu) | |||
| 1837 | 1837 | ||
| 1838 | static const struct sched_class rt_sched_class; | 1838 | static const struct sched_class rt_sched_class; |
| 1839 | 1839 | ||
| 1840 | #define sched_class_highest (&rt_sched_class) | 1840 | #define sched_class_highest (&stop_sched_class) |
| 1841 | #define for_each_class(class) \ | 1841 | #define for_each_class(class) \ |
| 1842 | for (class = sched_class_highest; class; class = class->next) | 1842 | for (class = sched_class_highest; class; class = class->next) |
| 1843 | 1843 | ||
| @@ -1917,10 +1917,41 @@ static void deactivate_task(struct rq *rq, struct task_struct *p, int flags) | |||
| 1917 | #include "sched_idletask.c" | 1917 | #include "sched_idletask.c" |
| 1918 | #include "sched_fair.c" | 1918 | #include "sched_fair.c" |
| 1919 | #include "sched_rt.c" | 1919 | #include "sched_rt.c" |
| 1920 | #include "sched_stoptask.c" | ||
| 1920 | #ifdef CONFIG_SCHED_DEBUG | 1921 | #ifdef CONFIG_SCHED_DEBUG |
| 1921 | # include "sched_debug.c" | 1922 | # include "sched_debug.c" |
| 1922 | #endif | 1923 | #endif |
| 1923 | 1924 | ||
| 1925 | void sched_set_stop_task(int cpu, struct task_struct *stop) | ||
| 1926 | { | ||
| 1927 | struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 }; | ||
| 1928 | struct task_struct *old_stop = cpu_rq(cpu)->stop; | ||
| 1929 | |||
| 1930 | if (stop) { | ||
| 1931 | /* | ||
| 1932 | * Make it appear like a SCHED_FIFO task, its something | ||
| 1933 | * userspace knows about and won't get confused about. | ||
| 1934 | * | ||
| 1935 | * Also, it will make PI more or less work without too | ||
| 1936 | * much confusion -- but then, stop work should not | ||
| 1937 | * rely on PI working anyway. | ||
| 1938 | */ | ||
| 1939 | sched_setscheduler_nocheck(stop, SCHED_FIFO, ¶m); | ||
| 1940 | |||
| 1941 | stop->sched_class = &stop_sched_class; | ||
| 1942 | } | ||
| 1943 | |||
| 1944 | cpu_rq(cpu)->stop = stop; | ||
| 1945 | |||
| 1946 | if (old_stop) { | ||
| 1947 | /* | ||
| 1948 | * Reset it back to a normal scheduling class so that | ||
| 1949 | * it can die in pieces. | ||
| 1950 | */ | ||
| 1951 | old_stop->sched_class = &rt_sched_class; | ||
| 1952 | } | ||
| 1953 | } | ||
| 1954 | |||
| 1924 | /* | 1955 | /* |
| 1925 | * __normal_prio - return the priority that is based on the static prio | 1956 | * __normal_prio - return the priority that is based on the static prio |
| 1926 | */ | 1957 | */ |
| @@ -3720,17 +3751,13 @@ pick_next_task(struct rq *rq) | |||
| 3720 | return p; | 3751 | return p; |
| 3721 | } | 3752 | } |
| 3722 | 3753 | ||
| 3723 | class = sched_class_highest; | 3754 | for_each_class(class) { |
| 3724 | for ( ; ; ) { | ||
| 3725 | p = class->pick_next_task(rq); | 3755 | p = class->pick_next_task(rq); |
| 3726 | if (p) | 3756 | if (p) |
| 3727 | return p; | 3757 | return p; |
| 3728 | /* | ||
| 3729 | * Will never be NULL as the idle class always | ||
| 3730 | * returns a non-NULL p: | ||
| 3731 | */ | ||
| 3732 | class = class->next; | ||
| 3733 | } | 3758 | } |
| 3759 | |||
| 3760 | BUG(); /* the idle class will always have a runnable task */ | ||
| 3734 | } | 3761 | } |
| 3735 | 3762 | ||
| 3736 | /* | 3763 | /* |
| @@ -4659,6 +4686,15 @@ recheck: | |||
| 4659 | */ | 4686 | */ |
| 4660 | rq = __task_rq_lock(p); | 4687 | rq = __task_rq_lock(p); |
| 4661 | 4688 | ||
| 4689 | /* | ||
| 4690 | * Changing the policy of the stop threads its a very bad idea | ||
| 4691 | */ | ||
| 4692 | if (p == rq->stop) { | ||
| 4693 | __task_rq_unlock(rq); | ||
| 4694 | raw_spin_unlock_irqrestore(&p->pi_lock, flags); | ||
| 4695 | return -EINVAL; | ||
| 4696 | } | ||
| 4697 | |||
| 4662 | #ifdef CONFIG_RT_GROUP_SCHED | 4698 | #ifdef CONFIG_RT_GROUP_SCHED |
| 4663 | if (user) { | 4699 | if (user) { |
| 4664 | /* | 4700 | /* |
