aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched.c
diff options
context:
space:
mode:
authorMike Galbraith <efault@gmx.de>2006-12-10 05:20:31 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-10 12:55:43 -0500
commitb18ec80396834497933d77b81ec0918519f4e2a7 (patch)
tree659422f11d4ed64725e321105f0465d27bb60d3d /kernel/sched.c
parent08c183f31bdbb709f177f6d3110d5f288ea33933 (diff)
[PATCH] sched: improve migration accuracy
Co-opt rq->timestamp_last_tick to maintain a cache_hot_time evaluation reference timestamp at both tick and sched times to prevent said reference, formerly rq->timestamp_last_tick, from being behind task->last_ran at evaluation time, and to move said reference closer to current time on the remote processor, intent being to improve cache hot evaluation and timestamp adjustment accuracy for task migration. Fix minor sched_time double accounting error which occurs when a task passing through schedule() does not schedule off, and takes the next timer tick. [kenneth.w.chen@intel.com: cleanup] Signed-off-by: Mike Galbraith <efault@gmx.de> Acked-by: Ingo Molnar <mingo@elte.hu> Acked-by: Ken Chen <kenneth.w.chen@intel.com> Cc: Don Mullis <dwm@meer.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/sched.c')
-rw-r--r--kernel/sched.c41
1 files changed, 20 insertions, 21 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index 2b2b780939c9..15ce772a471a 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -225,7 +225,8 @@ struct rq {
225 unsigned long nr_uninterruptible; 225 unsigned long nr_uninterruptible;
226 226
227 unsigned long expired_timestamp; 227 unsigned long expired_timestamp;
228 unsigned long long timestamp_last_tick; 228 /* Cached timestamp set by update_cpu_clock() */
229 unsigned long long most_recent_timestamp;
229 struct task_struct *curr, *idle; 230 struct task_struct *curr, *idle;
230 unsigned long next_balance; 231 unsigned long next_balance;
231 struct mm_struct *prev_mm; 232 struct mm_struct *prev_mm;
@@ -944,8 +945,8 @@ static void activate_task(struct task_struct *p, struct rq *rq, int local)
944 if (!local) { 945 if (!local) {
945 /* Compensate for drifting sched_clock */ 946 /* Compensate for drifting sched_clock */
946 struct rq *this_rq = this_rq(); 947 struct rq *this_rq = this_rq();
947 now = (now - this_rq->timestamp_last_tick) 948 now = (now - this_rq->most_recent_timestamp)
948 + rq->timestamp_last_tick; 949 + rq->most_recent_timestamp;
949 } 950 }
950#endif 951#endif
951 952
@@ -1689,8 +1690,8 @@ void fastcall wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
1689 * Not the local CPU - must adjust timestamp. This should 1690 * Not the local CPU - must adjust timestamp. This should
1690 * get optimised away in the !CONFIG_SMP case. 1691 * get optimised away in the !CONFIG_SMP case.
1691 */ 1692 */
1692 p->timestamp = (p->timestamp - this_rq->timestamp_last_tick) 1693 p->timestamp = (p->timestamp - this_rq->most_recent_timestamp)
1693 + rq->timestamp_last_tick; 1694 + rq->most_recent_timestamp;
1694 __activate_task(p, rq); 1695 __activate_task(p, rq);
1695 if (TASK_PREEMPTS_CURR(p, rq)) 1696 if (TASK_PREEMPTS_CURR(p, rq))
1696 resched_task(rq->curr); 1697 resched_task(rq->curr);
@@ -2068,8 +2069,8 @@ static void pull_task(struct rq *src_rq, struct prio_array *src_array,
2068 set_task_cpu(p, this_cpu); 2069 set_task_cpu(p, this_cpu);
2069 inc_nr_running(p, this_rq); 2070 inc_nr_running(p, this_rq);
2070 enqueue_task(p, this_array); 2071 enqueue_task(p, this_array);
2071 p->timestamp = (p->timestamp - src_rq->timestamp_last_tick) 2072 p->timestamp = (p->timestamp - src_rq->most_recent_timestamp)
2072 + this_rq->timestamp_last_tick; 2073 + this_rq->most_recent_timestamp;
2073 /* 2074 /*
2074 * Note that idle threads have a prio of MAX_PRIO, for this test 2075 * Note that idle threads have a prio of MAX_PRIO, for this test
2075 * to be always true for them. 2076 * to be always true for them.
@@ -2105,10 +2106,15 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu,
2105 * 2) too many balance attempts have failed. 2106 * 2) too many balance attempts have failed.
2106 */ 2107 */
2107 2108
2108 if (sd->nr_balance_failed > sd->cache_nice_tries) 2109 if (sd->nr_balance_failed > sd->cache_nice_tries) {
2110#ifdef CONFIG_SCHEDSTATS
2111 if (task_hot(p, rq->most_recent_timestamp, sd))
2112 schedstat_inc(sd, lb_hot_gained[idle]);
2113#endif
2109 return 1; 2114 return 1;
2115 }
2110 2116
2111 if (task_hot(p, rq->timestamp_last_tick, sd)) 2117 if (task_hot(p, rq->most_recent_timestamp, sd))
2112 return 0; 2118 return 0;
2113 return 1; 2119 return 1;
2114} 2120}
@@ -2206,11 +2212,6 @@ skip_queue:
2206 goto skip_bitmap; 2212 goto skip_bitmap;
2207 } 2213 }
2208 2214
2209#ifdef CONFIG_SCHEDSTATS
2210 if (task_hot(tmp, busiest->timestamp_last_tick, sd))
2211 schedstat_inc(sd, lb_hot_gained[idle]);
2212#endif
2213
2214 pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu); 2215 pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu);
2215 pulled++; 2216 pulled++;
2216 rem_load_move -= tmp->load_weight; 2217 rem_load_move -= tmp->load_weight;
@@ -2971,7 +2972,8 @@ EXPORT_PER_CPU_SYMBOL(kstat);
2971static inline void 2972static inline void
2972update_cpu_clock(struct task_struct *p, struct rq *rq, unsigned long long now) 2973update_cpu_clock(struct task_struct *p, struct rq *rq, unsigned long long now)
2973{ 2974{
2974 p->sched_time += now - max(p->timestamp, rq->timestamp_last_tick); 2975 p->sched_time += now - p->last_ran;
2976 p->last_ran = rq->most_recent_timestamp = now;
2975} 2977}
2976 2978
2977/* 2979/*
@@ -2984,8 +2986,7 @@ unsigned long long current_sched_time(const struct task_struct *p)
2984 unsigned long flags; 2986 unsigned long flags;
2985 2987
2986 local_irq_save(flags); 2988 local_irq_save(flags);
2987 ns = max(p->timestamp, task_rq(p)->timestamp_last_tick); 2989 ns = p->sched_time + sched_clock() - p->last_ran;
2988 ns = p->sched_time + sched_clock() - ns;
2989 local_irq_restore(flags); 2990 local_irq_restore(flags);
2990 2991
2991 return ns; 2992 return ns;
@@ -3176,8 +3177,6 @@ void scheduler_tick(void)
3176 3177
3177 update_cpu_clock(p, rq, now); 3178 update_cpu_clock(p, rq, now);
3178 3179
3179 rq->timestamp_last_tick = now;
3180
3181 if (p == rq->idle) 3180 if (p == rq->idle)
3182 /* Task on the idle queue */ 3181 /* Task on the idle queue */
3183 wake_priority_sleeper(rq); 3182 wake_priority_sleeper(rq);
@@ -5032,8 +5031,8 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
5032 * afterwards, and pretending it was a local activate. 5031 * afterwards, and pretending it was a local activate.
5033 * This way is cleaner and logically correct. 5032 * This way is cleaner and logically correct.
5034 */ 5033 */
5035 p->timestamp = p->timestamp - rq_src->timestamp_last_tick 5034 p->timestamp = p->timestamp - rq_src->most_recent_timestamp
5036 + rq_dest->timestamp_last_tick; 5035 + rq_dest->most_recent_timestamp;
5037 deactivate_task(p, rq_src); 5036 deactivate_task(p, rq_src);
5038 __activate_task(p, rq_dest); 5037 __activate_task(p, rq_dest);
5039 if (TASK_PREEMPTS_CURR(p, rq_dest)) 5038 if (TASK_PREEMPTS_CURR(p, rq_dest))