aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sched.h1
-rw-r--r--kernel/sched.c34
-rw-r--r--kernel/sched_fair.c68
-rw-r--r--kernel/sched_idletask.c5
-rw-r--r--kernel/sched_rt.c8
5 files changed, 72 insertions, 44 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index abcb02738d95..66169005f008 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -871,6 +871,7 @@ struct sched_class {
871 struct sched_domain *sd, enum cpu_idle_type idle, 871 struct sched_domain *sd, enum cpu_idle_type idle,
872 int *all_pinned, int *this_best_prio); 872 int *all_pinned, int *this_best_prio);
873 873
874 void (*set_curr_task) (struct rq *rq);
874 void (*task_tick) (struct rq *rq, struct task_struct *p); 875 void (*task_tick) (struct rq *rq, struct task_struct *p);
875 void (*task_new) (struct rq *rq, struct task_struct *p); 876 void (*task_new) (struct rq *rq, struct task_struct *p);
876}; 877};
diff --git a/kernel/sched.c b/kernel/sched.c
index 72c936d3e332..ee7ac71b12f8 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -3916,7 +3916,7 @@ EXPORT_SYMBOL(sleep_on_timeout);
3916void rt_mutex_setprio(struct task_struct *p, int prio) 3916void rt_mutex_setprio(struct task_struct *p, int prio)
3917{ 3917{
3918 unsigned long flags; 3918 unsigned long flags;
3919 int oldprio, on_rq; 3919 int oldprio, on_rq, running;
3920 struct rq *rq; 3920 struct rq *rq;
3921 3921
3922 BUG_ON(prio < 0 || prio > MAX_PRIO); 3922 BUG_ON(prio < 0 || prio > MAX_PRIO);
@@ -3926,8 +3926,12 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
3926 3926
3927 oldprio = p->prio; 3927 oldprio = p->prio;
3928 on_rq = p->se.on_rq; 3928 on_rq = p->se.on_rq;
3929 if (on_rq) 3929 running = task_running(rq, p);
3930 if (on_rq) {
3930 dequeue_task(rq, p, 0); 3931 dequeue_task(rq, p, 0);
3932 if (running)
3933 p->sched_class->put_prev_task(rq, p);
3934 }
3931 3935
3932 if (rt_prio(prio)) 3936 if (rt_prio(prio))
3933 p->sched_class = &rt_sched_class; 3937 p->sched_class = &rt_sched_class;
@@ -3937,13 +3941,15 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
3937 p->prio = prio; 3941 p->prio = prio;
3938 3942
3939 if (on_rq) { 3943 if (on_rq) {
3944 if (running)
3945 p->sched_class->set_curr_task(rq);
3940 enqueue_task(rq, p, 0); 3946 enqueue_task(rq, p, 0);
3941 /* 3947 /*
3942 * Reschedule if we are currently running on this runqueue and 3948 * Reschedule if we are currently running on this runqueue and
3943 * our priority decreased, or if we are not currently running on 3949 * our priority decreased, or if we are not currently running on
3944 * this runqueue and our priority is higher than the current's 3950 * this runqueue and our priority is higher than the current's
3945 */ 3951 */
3946 if (task_running(rq, p)) { 3952 if (running) {
3947 if (p->prio > oldprio) 3953 if (p->prio > oldprio)
3948 resched_task(rq->curr); 3954 resched_task(rq->curr);
3949 } else { 3955 } else {
@@ -4149,7 +4155,7 @@ __setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio)
4149int sched_setscheduler(struct task_struct *p, int policy, 4155int sched_setscheduler(struct task_struct *p, int policy,
4150 struct sched_param *param) 4156 struct sched_param *param)
4151{ 4157{
4152 int retval, oldprio, oldpolicy = -1, on_rq; 4158 int retval, oldprio, oldpolicy = -1, on_rq, running;
4153 unsigned long flags; 4159 unsigned long flags;
4154 struct rq *rq; 4160 struct rq *rq;
4155 4161
@@ -4231,20 +4237,26 @@ recheck:
4231 } 4237 }
4232 update_rq_clock(rq); 4238 update_rq_clock(rq);
4233 on_rq = p->se.on_rq; 4239 on_rq = p->se.on_rq;
4234 if (on_rq) 4240 running = task_running(rq, p);
4241 if (on_rq) {
4235 deactivate_task(rq, p, 0); 4242 deactivate_task(rq, p, 0);
4243 if (running)
4244 p->sched_class->put_prev_task(rq, p);
4245 }
4236 4246
4237 oldprio = p->prio; 4247 oldprio = p->prio;
4238 __setscheduler(rq, p, policy, param->sched_priority); 4248 __setscheduler(rq, p, policy, param->sched_priority);
4239 4249
4240 if (on_rq) { 4250 if (on_rq) {
4251 if (running)
4252 p->sched_class->set_curr_task(rq);
4241 activate_task(rq, p, 0); 4253 activate_task(rq, p, 0);
4242 /* 4254 /*
4243 * Reschedule if we are currently running on this runqueue and 4255 * Reschedule if we are currently running on this runqueue and
4244 * our priority decreased, or if we are not currently running on 4256 * our priority decreased, or if we are not currently running on
4245 * this runqueue and our priority is higher than the current's 4257 * this runqueue and our priority is higher than the current's
4246 */ 4258 */
4247 if (task_running(rq, p)) { 4259 if (running) {
4248 if (p->prio > oldprio) 4260 if (p->prio > oldprio)
4249 resched_task(rq->curr); 4261 resched_task(rq->curr);
4250 } else { 4262 } else {
@@ -6845,13 +6857,19 @@ static void sched_move_task(struct container_subsys *ss, struct container *cont,
6845 running = task_running(rq, tsk); 6857 running = task_running(rq, tsk);
6846 on_rq = tsk->se.on_rq; 6858 on_rq = tsk->se.on_rq;
6847 6859
6848 if (on_rq) 6860 if (on_rq) {
6849 dequeue_task(rq, tsk, 0); 6861 dequeue_task(rq, tsk, 0);
6862 if (unlikely(running))
6863 tsk->sched_class->put_prev_task(rq, tsk);
6864 }
6850 6865
6851 set_task_cfs_rq(tsk); 6866 set_task_cfs_rq(tsk);
6852 6867
6853 if (on_rq) 6868 if (on_rq) {
6869 if (unlikely(running))
6870 tsk->sched_class->set_curr_task(rq);
6854 enqueue_task(rq, tsk, 0); 6871 enqueue_task(rq, tsk, 0);
6872 }
6855 6873
6856done: 6874done:
6857 task_rq_unlock(rq, &flags); 6875 task_rq_unlock(rq, &flags);
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index 9f93a5c127e8..92563cd5af75 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -472,20 +472,9 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial)
472} 472}
473 473
474static void 474static void
475enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, 475enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup)
476 int wakeup, int set_curr)
477{ 476{
478 /* 477 /*
479 * In case of the 'current'.
480 */
481 if (unlikely(set_curr)) {
482 update_stats_curr_start(cfs_rq, se);
483 cfs_rq->curr = se;
484 account_entity_enqueue(cfs_rq, se);
485 return;
486 }
487
488 /*
489 * Update the fair clock. 478 * Update the fair clock.
490 */ 479 */
491 update_curr(cfs_rq); 480 update_curr(cfs_rq);
@@ -496,7 +485,8 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
496 } 485 }
497 486
498 update_stats_enqueue(cfs_rq, se); 487 update_stats_enqueue(cfs_rq, se);
499 __enqueue_entity(cfs_rq, se); 488 if (se != cfs_rq->curr)
489 __enqueue_entity(cfs_rq, se);
500 account_entity_enqueue(cfs_rq, se); 490 account_entity_enqueue(cfs_rq, se);
501} 491}
502 492
@@ -516,12 +506,8 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep)
516 } 506 }
517 } 507 }
518#endif 508#endif
519 if (likely(se != cfs_rq->curr)) 509 if (se != cfs_rq->curr)
520 __dequeue_entity(cfs_rq, se); 510 __dequeue_entity(cfs_rq, se);
521 else {
522 update_stats_curr_end(cfs_rq, se);
523 cfs_rq->curr = NULL;
524 }
525 account_entity_dequeue(cfs_rq, se); 511 account_entity_dequeue(cfs_rq, se);
526} 512}
527 513
@@ -539,15 +525,20 @@ check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
539 resched_task(rq_of(cfs_rq)->curr); 525 resched_task(rq_of(cfs_rq)->curr);
540} 526}
541 527
542static inline void 528static void
543set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se) 529set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
544{ 530{
545 /* 531 /* 'current' is not kept within the tree. */
546 * Any task has to be enqueued before it get to execute on 532 if (se->on_rq) {
547 * a CPU. So account for the time it spent waiting on the 533 /*
548 * runqueue. 534 * Any task has to be enqueued before it get to execute on
549 */ 535 * a CPU. So account for the time it spent waiting on the
550 update_stats_wait_end(cfs_rq, se); 536 * runqueue.
537 */
538 update_stats_wait_end(cfs_rq, se);
539 __dequeue_entity(cfs_rq, se);
540 }
541
551 update_stats_curr_start(cfs_rq, se); 542 update_stats_curr_start(cfs_rq, se);
552 cfs_rq->curr = se; 543 cfs_rq->curr = se;
553#ifdef CONFIG_SCHEDSTATS 544#ifdef CONFIG_SCHEDSTATS
@@ -568,10 +559,6 @@ static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq)
568{ 559{
569 struct sched_entity *se = __pick_next_entity(cfs_rq); 560 struct sched_entity *se = __pick_next_entity(cfs_rq);
570 561
571 /* 'current' is not kept within the tree. */
572 if (se)
573 __dequeue_entity(cfs_rq, se);
574
575 set_next_entity(cfs_rq, se); 562 set_next_entity(cfs_rq, se);
576 563
577 return se; 564 return se;
@@ -703,17 +690,12 @@ static void enqueue_task_fair(struct rq *rq, struct task_struct *p, int wakeup)
703{ 690{
704 struct cfs_rq *cfs_rq; 691 struct cfs_rq *cfs_rq;
705 struct sched_entity *se = &p->se; 692 struct sched_entity *se = &p->se;
706 int set_curr = 0;
707
708 /* Are we enqueuing the current task? */
709 if (unlikely(task_running(rq, p)))
710 set_curr = 1;
711 693
712 for_each_sched_entity(se) { 694 for_each_sched_entity(se) {
713 if (se->on_rq) 695 if (se->on_rq)
714 break; 696 break;
715 cfs_rq = cfs_rq_of(se); 697 cfs_rq = cfs_rq_of(se);
716 enqueue_entity(cfs_rq, se, wakeup, set_curr); 698 enqueue_entity(cfs_rq, se, wakeup);
717 } 699 }
718} 700}
719 701
@@ -761,7 +743,7 @@ static void yield_task_fair(struct rq *rq)
761 * position within the tree: 743 * position within the tree:
762 */ 744 */
763 dequeue_entity(cfs_rq, se, 0); 745 dequeue_entity(cfs_rq, se, 0);
764 enqueue_entity(cfs_rq, se, 0, 1); 746 enqueue_entity(cfs_rq, se, 0);
765 747
766 return; 748 return;
767 } 749 }
@@ -1004,6 +986,19 @@ static void task_new_fair(struct rq *rq, struct task_struct *p)
1004 resched_task(rq->curr); 986 resched_task(rq->curr);
1005} 987}
1006 988
989/* Account for a task changing its policy or group.
990 *
991 * This routine is mostly called to set cfs_rq->curr field when a task
992 * migrates between groups/classes.
993 */
994static void set_curr_task_fair(struct rq *rq)
995{
996 struct sched_entity *se = &rq->curr->se;
997
998 for_each_sched_entity(se)
999 set_next_entity(cfs_rq_of(se), se);
1000}
1001
1007/* 1002/*
1008 * All the scheduling class methods: 1003 * All the scheduling class methods:
1009 */ 1004 */
@@ -1019,6 +1014,7 @@ struct sched_class fair_sched_class __read_mostly = {
1019 1014
1020 .load_balance = load_balance_fair, 1015 .load_balance = load_balance_fair,
1021 1016
1017 .set_curr_task = set_curr_task_fair,
1022 .task_tick = task_tick_fair, 1018 .task_tick = task_tick_fair,
1023 .task_new = task_new_fair, 1019 .task_new = task_new_fair,
1024}; 1020};
diff --git a/kernel/sched_idletask.c b/kernel/sched_idletask.c
index 3503fb2d9f96..5ebf829cdd73 100644
--- a/kernel/sched_idletask.c
+++ b/kernel/sched_idletask.c
@@ -50,6 +50,10 @@ static void task_tick_idle(struct rq *rq, struct task_struct *curr)
50{ 50{
51} 51}
52 52
53static void set_curr_task_idle(struct rq *rq)
54{
55}
56
53/* 57/*
54 * Simple, special scheduling class for the per-CPU idle tasks: 58 * Simple, special scheduling class for the per-CPU idle tasks:
55 */ 59 */
@@ -66,6 +70,7 @@ static struct sched_class idle_sched_class __read_mostly = {
66 70
67 .load_balance = load_balance_idle, 71 .load_balance = load_balance_idle,
68 72
73 .set_curr_task = set_curr_task_idle,
69 .task_tick = task_tick_idle, 74 .task_tick = task_tick_idle,
70 /* no .task_new for idle tasks */ 75 /* no .task_new for idle tasks */
71}; 76};
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index 3c77c03bdf1e..e1d5f1c8b532 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -218,6 +218,13 @@ static void task_tick_rt(struct rq *rq, struct task_struct *p)
218 } 218 }
219} 219}
220 220
221static void set_curr_task_rt(struct rq *rq)
222{
223 struct task_struct *p = rq->curr;
224
225 p->se.exec_start = rq->clock;
226}
227
221static struct sched_class rt_sched_class __read_mostly = { 228static struct sched_class rt_sched_class __read_mostly = {
222 .enqueue_task = enqueue_task_rt, 229 .enqueue_task = enqueue_task_rt,
223 .dequeue_task = dequeue_task_rt, 230 .dequeue_task = dequeue_task_rt,
@@ -230,5 +237,6 @@ static struct sched_class rt_sched_class __read_mostly = {
230 237
231 .load_balance = load_balance_rt, 238 .load_balance = load_balance_rt,
232 239
240 .set_curr_task = set_curr_task_rt,
233 .task_tick = task_tick_rt, 241 .task_tick = task_tick_rt,
234}; 242};