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 | /* |