aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sched.c')
-rw-r--r--kernel/sched.c54
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
1838static const struct sched_class rt_sched_class; 1838static 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
1925void 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, &param);
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 /*