aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched.c
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2010-09-22 07:53:15 -0400
committerIngo Molnar <mingo@elte.hu>2010-10-18 12:41:58 -0400
commit34f971f6f7988be4d014eec3e3526bee6d007ffa (patch)
treea662e0701f81f019418b55aa1354f833277b9c40 /kernel/sched.c
parent4924627423d5e286136ad2520f5be536345ae590 (diff)
sched: Create special class for stop/migrate work
In order to separate the stop/migrate work thread from the SCHED_FIFO implementation, create a special class for it that is of higher priority than SCHED_FIFO itself. This currently solves a problem where cpu-hotplug consumes so much cpu-time that the SCHED_FIFO class gets throttled, but has the bandwidth replenishment timer pending on the now dead cpu. It is also required for when we add the planned deadline scheduling class above SCHED_FIFO, as the stop/migrate thread still needs to transcent those tasks. Tested-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <1285165776.2275.1022.camel@laptop> Signed-off-by: Ingo Molnar <mingo@elte.hu>
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 /*