RT balance updates against sched-devel
Steven Rostedt
reviewerv2 cover RT balance updates against sched-devel
[Sorry if this is a repost, but I had a problem with quilt mail, and
I don't know if my original post made it out. Unfortunately, I didn't save the original "prolog" file, and so this has to be rewritten from scratch, and I don't even remember the original subject :-/ ]
This patch series goes against Ingo's sched-devel git tree.
The first patch addresses Ingo's concerns about having hooks in the main sched.c and replaces them with generic methods that any class may use. The methods are: pre_schedule, post_schedule and task_wake_up; which is called before the schedule, after a context switch and when a task wakes up respectively. The are surrounded by ifdef CONFIG_SMP since they are currently only used by sched_rt in SMP mode. But if this appears to be applicable to other sched_classes in UP, then I can rerun this series without the ifdefs.
The second patch addresses the concerns that Dmitry brought up showing that the current RT balancing neglected to handle changes in prio and classes from sched_setscheduler and rt_mutex_setprio. The added methods
are: switched_to, switched_from and prio_changed; these are called in the when a task is assigned a new sched_class, after it leaves a sched_class, and when it changes its prio respectively.
The last two patches are from Gregory Haskins where he cleaned up left over changes that were from previous versions of the balancing code.
-- Steve
Steven Rostedt
reviewerPATCH v2 1/4 Replace hooks with pre/post schedule and wakeup methods
To make the main sched.c code more agnostic to the schedule classes. Instead of having specific hooks in the schedule code for the RT class balancing. They are replaced with a pre_schedule, post_schedule and task_wake_up methods. These methods may be used by any of the classes but currently, only the sched_rt class implements them.
--- include/linux/sched.h | 3 +++ kernel/sched.c | 20 ++++++++++++++++---- kernel/sched_rt.c | 17 +++++++---------- 3 files changed, 26 insertions(+), 14 deletions(-)
include/linux/sched.h +3 -0
@@ -848,6 +848,9 @@ struct sched_class {int (*move_one_task) (struct rq *this_rq,int this_cpu,struct rq *busiest,struct sched_domain *sd,enum cpu_idle_type idle); +void (*pre_schedule) (struct rq *this_rq,struct task_struct *task); +void (*post_schedule) (struct rq *this_rq); +void (*task_wake_up) (struct rq *this_rq,struct task_struct *task);#endif void (*set_curr_task) (struct rq *rq);
kernel/sched.c +16 -4
@@ -1620,7 +1620,10 @@ out_activate: out_running: p->state =TASK_RUNNING ; -wakeup_balance_rt (rq, p); +#ifdef CONFIG_SMP +if (p->sched_class->task_wake_up) + p->sched_class->task_wake_up (rq, p); +#endif out:task_rq_unlock (rq, &flags);
@@ -1743,7 +1746,10 @@ void fastcall wake_up_new_task(struct tainc_nr_running (p, rq); }check_preempt_curr (rq, p); -wakeup_balance_rt (rq, p); +#ifdef CONFIG_SMP +if (p->sched_class->task_wake_up) + p->sched_class->task_wake_up (rq, p); +#endif task_rq_unlock (rq, &flags); }
@@ -1864,7 +1870,10 @@ static void finish_task_switch(struct rq prev_state = prev->state;finish_arch_switch (prev);finish_lock_switch (rq, prev); -schedule_tail_balance_rt (rq); +#ifdef CONFIG_SMP +if (current->sched_class->post_schedule) + current->sched_class->post_schedule (rq); +#endif fire_sched_in_preempt_notifiers (current);if (mm)
@@ -3633,7 +3642,10 @@ need_resched_nonpreemptible: switch_count = &prev->nvcsw; } -schedule_balance_rt (rq, prev); +#ifdef CONFIG_SMP +if (prev->sched_class->pre_schedule) + prev->sched_class->pre_schedule (rq, prev); +#endif if (unlikely (!rq->nr_running))idle_balance (cpu, rq);
kernel/sched_rt.c +7 -10
@@ -689,14 +689,14 @@ static int pull_rt_task(struct rq *this_return ret; } -static void schedule_balance_rt (struct rq *rq,struct task_struct *prev) +static void pre_schedule_rt (struct rq *rq,struct task_struct *prev) {/* Try to pull RT tasks here if we lower this rq's prio */ if (unlikely (rt_task (prev)) && rq->rt.highest_prio > prev->prio)pull_rt_task (rq); } -static void schedule_tail_balance_rt (struct rq *rq) +static void post_schedule_rt (struct rq *rq) {/* * If we have more than one rt_task queued, then
@@ -713,10 +713,9 @@ static void schedule_tail_balance_rt(str } -static void wakeup_balance_rt (struct rq *rq,struct task_struct *p) +static void task_wake_up_rt (struct rq *rq,struct task_struct *p) { -if (unlikely (rt_task (p)) && - !task_running (rq, p) && +if (!task_running (rq, p) && (p->prio >= rq->rt.highest_prio) && rq->rt.overloaded)push_rt_tasks (rq);
@@ -780,11 +779,6 @@ static void leave_domain_rt(struct rq *rif (rq->rt.overloaded) rt_clear_overload(rq); } - -#else /* CONFIG_SMP */ -# define schedule_tail_balance_rt (rq) do { } while (0) -# define schedule_balance_rt (rq, prev) do { } while (0) -# define wakeup_balance_rt (rq, p) do { } while (0)#endif /* CONFIG_SMP */ static void task_tick_rt (struct rq *rq,struct task_struct *p)
@@ -838,6 +832,9 @@ const struct sched_class rt_sched_class .set_cpus_allowed = set_cpus_allowed_rt, .join_domain = join_domain_rt, .leave_domain = leave_domain_rt, + .pre_schedule = pre_schedule_rt, + .post_schedule = post_schedule_rt, + .task_wake_up = task_wake_up_rt, #endif .set_curr_task = set_curr_task_rt,
Steven Rostedt
reviewerPATCH v2 2/4 added methods for sched_class changes
In reply to Steven RostedtDmitry Adamushko found that the current implementation of the RT balancing code left out changes to the sched_setscheduler and rt_mutex_setprio.
This patch addresses this issue by adding methods to the schedule classes to handle being switched out of (switched_from) and being switched into (switched_to) a sched_class. Also a method for changing of priorities is also added (prio_changed).
This patch also removes some duplicate logic between rt_mutex_setprio and sched_setscheduler.
--- include/linux/sched.h | 7 +++ kernel/sched.c | 42 ++++++++++------------ kernel/sched_fair.c | 39 +++++++++++++++++++++ kernel/sched_idletask.c | 31 ++++++++++++++++ kernel/sched_rt.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 186 insertions(+), 22 deletions(-)
include/linux/sched.h +7 -0
@@ -860,6 +860,13 @@ struct sched_class {void (*join_domain)(struct rq *rq);void (*leave_domain)(struct rq *rq); + +void (*switched_from) (struct rq *this_rq,struct task_struct *task, +int running); +void (*switched_to) (struct rq *this_rq,struct task_struct *task, +int running); +void (*prio_changed) (struct rq *this_rq,struct task_struct *task, +int oldprio,int running); };struct load_weight {
kernel/sched.c +20 -22
74 lines not on this page · raw message
kernel/sched_fair.c +39 -0
@@ -1280,6 +1280,42 @@ static void task_new_fair(struct rq *rq,resched_task (rq->curr); } +/* +* Priority of the task has changed. Check to see if we preempt +* the current task. +*/ +static void prio_changed_fair (struct rq *rq,struct task_struct *p, +int oldprio,int running) +{ +/* +* Reschedule if we are currently running on this runqueue and +* our priority decreased, or if we are not currently running on +* this runqueue and our priority is higher than the current's +*/ +if (running) { +if (p->prio > oldprio) +resched_task (rq->curr); + }else +check_preempt_curr (rq, p); +} + +/* +* We switched to the sched_fair class. +*/ +static void switched_to_fair (struct rq *rq,struct task_struct *p, +int running) +{ +/* +* We were most likely switched from sched_rt, so +* kick off the schedule if running, otherwise just see +* if we can still preempt the current task. +*/ +if (running) +resched_task (rq->curr); +else +check_preempt_curr (rq, p); +} +/* Account for a task changing its policy or group. * * This routine is mostly called to set cfs_rq->curr field when a task
@@ -1318,6 +1354,9 @@ static const struct sched_class fair_sch .set_curr_task = set_curr_task_fair, .task_tick = task_tick_fair, .task_new = task_new_fair, + + .prio_changed = prio_changed_fair, + .switched_to = switched_to_fair, };#ifdef CONFIG_SCHED_DEBUG
kernel/sched_idletask.c +31 -0
@@ -69,6 +69,33 @@ static void set_curr_task_idle(struct rq { } +static void switched_to_idle (struct rq *rq,struct task_struct *p, +int running) +{ +/* Can this actually happen?? */ +if (running) +resched_task (rq->curr); +else +check_preempt_curr (rq, p); +} + +static void prio_changed_idle (struct rq *rq,struct task_struct *p, +int oldprio,int running) +{ +/* This can happen for hot plug CPUS */ + +/* +* Reschedule if we are currently running on this runqueue and +* our priority decreased, or if we are not currently running on +* this runqueue and our priority is higher than the current's +*/ +if (running) { +if (p->prio > oldprio) +resched_task (rq->curr); + }else +check_preempt_curr (rq, p); +} +/* * Simple, special scheduling class for the per-CPU idle tasks: */
@@ -94,5 +121,9 @@ const struct sched_class idle_sched_clas .set_curr_task = set_curr_task_idle, .task_tick = task_tick_idle, + + .prio_changed = prio_changed_idle, + .switched_to = switched_to_idle, +/* no .task_new for idle tasks */ };
kernel/sched_rt.c +89 -0
104 lines not on this page · raw message
Steven Rostedt
reviewerPATCH v2 3/4 SCHED - Only adjust overload state when changing
In reply to Steven RostedtFrom: Gregory Haskins <[email protected]>
The overload set/clears were originally idempotent when this logic was first implemented. But that is no longer true due to the addition of the atomic counter and this logic was never updated to work properly with that change. So only adjust the overload state if it is actually changing to avoid getting out of sync.
---
kernel/sched_rt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
kernel/sched_rt.c +5 -3
@@ -34,9 +34,11 @@ static inline void rt_clear_overload(strstatic void update_rt_migration (struct rq *rq) {if (rq->rt.rt_nr_migratory && (rq->rt.rt_nr_running >1 )) { -rt_set_overload (rq); - rq->rt.overloaded =1 ; - }else { +if (!rq->rt.overloaded) { +rt_set_overload (rq); + rq->rt.overloaded =1 ; + } + }else if (rq->rt.overloaded) {rt_clear_overload (rq); rq->rt.overloaded =0 ; }
Steven Rostedt
reviewerPATCH v2 4/4 Subject: SCHED - Clean up some old cpuset logic
In reply to Steven RostedtFrom: Gregory Haskins <[email protected]>
We had support for overlapping cpuset based rto logic in early prototypes that is no longer used, so clean it up.
---
kernel/sched_rt.c | 33 --------------------------------- 1 file changed, 33 deletions(-)
kernel/sched_rt.c +0 -33
@@ -586,38 +586,6 @@ static int pull_rt_task(struct rq *this_continue ; src_rq =cpu_rq (cpu); -if (unlikely (src_rq->rt.rt_nr_running <=1 )) { -/* -* It is possible that overlapping cpusets -* will miss clearing a non overloaded runqueue. -* Clear it now. -*/ -if (double_lock_balance (this_rq, src_rq)) { -/* unlocked our runqueue lock */ -struct task_struct *old_next = next; - - next =pick_next_task_rt (this_rq); -if (next != old_next) - ret =1 ; - } -if (likely (src_rq->rt.rt_nr_running <=1 )) { -/* -* Small chance that this_rq->curr changed -* but it's really harmless here. -*/ -rt_clear_overload (this_rq); - }else { -/* -* Heh, the src_rq is now overloaded, since -* we already have the src_rq lock, go straight -* to pulling tasks from it. -*/ - goto try_pulling; - } -spin_unlock (&src_rq->lock); -continue ; - } -/* * We can potentially drop this_rq's lock in * double_lock_balance, and another CPU could
@@ -641,7 +609,6 @@ static int pull_rt_task(struct rq *this_continue ; } - try_pulling: p =pick_next_highest_task_rt (src_rq, this_cpu);/*
Quoted 1 line · Steven Rostedt
This patch series goes against Ingo's sched-devel git tree.
thanks, i've applied them.
Ingo