aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sched.c')
-rw-r--r--kernel/sched.c82
1 files changed, 50 insertions, 32 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index a030d4514cdc..613fee54fc89 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -616,6 +616,7 @@ struct rq {
616 616
617 unsigned char idle_at_tick; 617 unsigned char idle_at_tick;
618 /* For active balancing */ 618 /* For active balancing */
619 int post_schedule;
619 int active_balance; 620 int active_balance;
620 int push_cpu; 621 int push_cpu;
621 /* cpu of this runqueue: */ 622 /* cpu of this runqueue: */
@@ -2839,17 +2840,11 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev,
2839 * with the lock held can cause deadlocks; see schedule() for 2840 * with the lock held can cause deadlocks; see schedule() for
2840 * details.) 2841 * details.)
2841 */ 2842 */
2842static int finish_task_switch(struct rq *rq, struct task_struct *prev) 2843static void finish_task_switch(struct rq *rq, struct task_struct *prev)
2843 __releases(rq->lock) 2844 __releases(rq->lock)
2844{ 2845{
2845 struct mm_struct *mm = rq->prev_mm; 2846 struct mm_struct *mm = rq->prev_mm;
2846 long prev_state; 2847 long prev_state;
2847 int post_schedule = 0;
2848
2849#ifdef CONFIG_SMP
2850 if (current->sched_class->needs_post_schedule)
2851 post_schedule = current->sched_class->needs_post_schedule(rq);
2852#endif
2853 2848
2854 rq->prev_mm = NULL; 2849 rq->prev_mm = NULL;
2855 2850
@@ -2880,10 +2875,44 @@ static int finish_task_switch(struct rq *rq, struct task_struct *prev)
2880 kprobe_flush_task(prev); 2875 kprobe_flush_task(prev);
2881 put_task_struct(prev); 2876 put_task_struct(prev);
2882 } 2877 }
2878}
2879
2880#ifdef CONFIG_SMP
2881
2882/* assumes rq->lock is held */
2883static inline void pre_schedule(struct rq *rq, struct task_struct *prev)
2884{
2885 if (prev->sched_class->pre_schedule)
2886 prev->sched_class->pre_schedule(rq, prev);
2887}
2888
2889/* rq->lock is NOT held, but preemption is disabled */
2890static inline void post_schedule(struct rq *rq)
2891{
2892 if (rq->post_schedule) {
2893 unsigned long flags;
2894
2895 spin_lock_irqsave(&rq->lock, flags);
2896 if (rq->curr->sched_class->post_schedule)
2897 rq->curr->sched_class->post_schedule(rq);
2898 spin_unlock_irqrestore(&rq->lock, flags);
2899
2900 rq->post_schedule = 0;
2901 }
2902}
2903
2904#else
2883 2905
2884 return post_schedule; 2906static inline void pre_schedule(struct rq *rq, struct task_struct *p)
2907{
2908}
2909
2910static inline void post_schedule(struct rq *rq)
2911{
2885} 2912}
2886 2913
2914#endif
2915
2887/** 2916/**
2888 * schedule_tail - first thing a freshly forked thread must call. 2917 * schedule_tail - first thing a freshly forked thread must call.
2889 * @prev: the thread we just switched away from. 2918 * @prev: the thread we just switched away from.
@@ -2892,14 +2921,14 @@ asmlinkage void schedule_tail(struct task_struct *prev)
2892 __releases(rq->lock) 2921 __releases(rq->lock)
2893{ 2922{
2894 struct rq *rq = this_rq(); 2923 struct rq *rq = this_rq();
2895 int post_schedule;
2896 2924
2897 post_schedule = finish_task_switch(rq, prev); 2925 finish_task_switch(rq, prev);
2898 2926
2899#ifdef CONFIG_SMP 2927 /*
2900 if (post_schedule) 2928 * FIXME: do we need to worry about rq being invalidated by the
2901 current->sched_class->post_schedule(rq); 2929 * task_switch?
2902#endif 2930 */
2931 post_schedule(rq);
2903 2932
2904#ifdef __ARCH_WANT_UNLOCKED_CTXSW 2933#ifdef __ARCH_WANT_UNLOCKED_CTXSW
2905 /* In this case, finish_task_switch does not reenable preemption */ 2934 /* In this case, finish_task_switch does not reenable preemption */
@@ -2913,7 +2942,7 @@ asmlinkage void schedule_tail(struct task_struct *prev)
2913 * context_switch - switch to the new MM and the new 2942 * context_switch - switch to the new MM and the new
2914 * thread's register state. 2943 * thread's register state.
2915 */ 2944 */
2916static inline int 2945static inline void
2917context_switch(struct rq *rq, struct task_struct *prev, 2946context_switch(struct rq *rq, struct task_struct *prev,
2918 struct task_struct *next) 2947 struct task_struct *next)
2919{ 2948{
@@ -2960,7 +2989,7 @@ context_switch(struct rq *rq, struct task_struct *prev,
2960 * CPUs since it called schedule(), thus the 'rq' on its stack 2989 * CPUs since it called schedule(), thus the 'rq' on its stack
2961 * frame will be invalid. 2990 * frame will be invalid.
2962 */ 2991 */
2963 return finish_task_switch(this_rq(), prev); 2992 finish_task_switch(this_rq(), prev);
2964} 2993}
2965 2994
2966/* 2995/*
@@ -5371,7 +5400,6 @@ asmlinkage void __sched schedule(void)
5371{ 5400{
5372 struct task_struct *prev, *next; 5401 struct task_struct *prev, *next;
5373 unsigned long *switch_count; 5402 unsigned long *switch_count;
5374 int post_schedule = 0;
5375 struct rq *rq; 5403 struct rq *rq;
5376 int cpu; 5404 int cpu;
5377 5405
@@ -5403,10 +5431,7 @@ need_resched_nonpreemptible:
5403 switch_count = &prev->nvcsw; 5431 switch_count = &prev->nvcsw;
5404 } 5432 }
5405 5433
5406#ifdef CONFIG_SMP 5434 pre_schedule(rq, prev);
5407 if (prev->sched_class->pre_schedule)
5408 prev->sched_class->pre_schedule(rq, prev);
5409#endif
5410 5435
5411 if (unlikely(!rq->nr_running)) 5436 if (unlikely(!rq->nr_running))
5412 idle_balance(cpu, rq); 5437 idle_balance(cpu, rq);
@@ -5422,25 +5447,17 @@ need_resched_nonpreemptible:
5422 rq->curr = next; 5447 rq->curr = next;
5423 ++*switch_count; 5448 ++*switch_count;
5424 5449
5425 post_schedule = context_switch(rq, prev, next); /* unlocks the rq */ 5450 context_switch(rq, prev, next); /* unlocks the rq */
5426 /* 5451 /*
5427 * the context switch might have flipped the stack from under 5452 * the context switch might have flipped the stack from under
5428 * us, hence refresh the local variables. 5453 * us, hence refresh the local variables.
5429 */ 5454 */
5430 cpu = smp_processor_id(); 5455 cpu = smp_processor_id();
5431 rq = cpu_rq(cpu); 5456 rq = cpu_rq(cpu);
5432 } else { 5457 } else
5433#ifdef CONFIG_SMP
5434 if (current->sched_class->needs_post_schedule)
5435 post_schedule = current->sched_class->needs_post_schedule(rq);
5436#endif
5437 spin_unlock_irq(&rq->lock); 5458 spin_unlock_irq(&rq->lock);
5438 }
5439 5459
5440#ifdef CONFIG_SMP 5460 post_schedule(rq);
5441 if (post_schedule)
5442 current->sched_class->post_schedule(rq);
5443#endif
5444 5461
5445 if (unlikely(reacquire_kernel_lock(current) < 0)) 5462 if (unlikely(reacquire_kernel_lock(current) < 0))
5446 goto need_resched_nonpreemptible; 5463 goto need_resched_nonpreemptible;
@@ -9403,6 +9420,7 @@ void __init sched_init(void)
9403#ifdef CONFIG_SMP 9420#ifdef CONFIG_SMP
9404 rq->sd = NULL; 9421 rq->sd = NULL;
9405 rq->rd = NULL; 9422 rq->rd = NULL;
9423 rq->post_schedule = 0;
9406 rq->active_balance = 0; 9424 rq->active_balance = 0;
9407 rq->next_balance = jiffies; 9425 rq->next_balance = jiffies;
9408 rq->push_cpu = 0; 9426 rq->push_cpu = 0;