aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-01-03 14:56:24 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-03 14:56:24 -0500
commit61420f59a589c0668f70cbe725785837c78ece90 (patch)
tree79ae77d731cd2425677b9527d50079d8cf34c3b2 /kernel
parentd97106ab53f812910a62d18afb9dbe882819c1ba (diff)
parentc742b31c03f37c5c499178f09f57381aa6c70131 (diff)
Merge branch 'cputime' of git://git390.osdl.marist.edu/pub/scm/linux-2.6
* 'cputime' of git://git390.osdl.marist.edu/pub/scm/linux-2.6: [PATCH] fast vdso implementation for CLOCK_THREAD_CPUTIME_ID [PATCH] improve idle cputime accounting [PATCH] improve precision of idle time detection. [PATCH] improve precision of process accounting. [PATCH] idle cputime accounting [PATCH] fix scaled & unscaled cputime accounting
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched.c115
-rw-r--r--kernel/time/tick-sched.c12
-rw-r--r--kernel/timer.c15
3 files changed, 82 insertions, 60 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index 27ba1d642f0f..930bf2e6d714 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -4150,13 +4150,17 @@ unsigned long long task_delta_exec(struct task_struct *p)
4150 * Account user cpu time to a process. 4150 * Account user cpu time to a process.
4151 * @p: the process that the cpu time gets accounted to 4151 * @p: the process that the cpu time gets accounted to
4152 * @cputime: the cpu time spent in user space since the last update 4152 * @cputime: the cpu time spent in user space since the last update
4153 * @cputime_scaled: cputime scaled by cpu frequency
4153 */ 4154 */
4154void account_user_time(struct task_struct *p, cputime_t cputime) 4155void account_user_time(struct task_struct *p, cputime_t cputime,
4156 cputime_t cputime_scaled)
4155{ 4157{
4156 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; 4158 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
4157 cputime64_t tmp; 4159 cputime64_t tmp;
4158 4160
4161 /* Add user time to process. */
4159 p->utime = cputime_add(p->utime, cputime); 4162 p->utime = cputime_add(p->utime, cputime);
4163 p->utimescaled = cputime_add(p->utimescaled, cputime_scaled);
4160 account_group_user_time(p, cputime); 4164 account_group_user_time(p, cputime);
4161 4165
4162 /* Add user time to cpustat. */ 4166 /* Add user time to cpustat. */
@@ -4173,51 +4177,48 @@ void account_user_time(struct task_struct *p, cputime_t cputime)
4173 * Account guest cpu time to a process. 4177 * Account guest cpu time to a process.
4174 * @p: the process that the cpu time gets accounted to 4178 * @p: the process that the cpu time gets accounted to
4175 * @cputime: the cpu time spent in virtual machine since the last update 4179 * @cputime: the cpu time spent in virtual machine since the last update
4180 * @cputime_scaled: cputime scaled by cpu frequency
4176 */ 4181 */
4177static void account_guest_time(struct task_struct *p, cputime_t cputime) 4182static void account_guest_time(struct task_struct *p, cputime_t cputime,
4183 cputime_t cputime_scaled)
4178{ 4184{
4179 cputime64_t tmp; 4185 cputime64_t tmp;
4180 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; 4186 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
4181 4187
4182 tmp = cputime_to_cputime64(cputime); 4188 tmp = cputime_to_cputime64(cputime);
4183 4189
4190 /* Add guest time to process. */
4184 p->utime = cputime_add(p->utime, cputime); 4191 p->utime = cputime_add(p->utime, cputime);
4192 p->utimescaled = cputime_add(p->utimescaled, cputime_scaled);
4185 account_group_user_time(p, cputime); 4193 account_group_user_time(p, cputime);
4186 p->gtime = cputime_add(p->gtime, cputime); 4194 p->gtime = cputime_add(p->gtime, cputime);
4187 4195
4196 /* Add guest time to cpustat. */
4188 cpustat->user = cputime64_add(cpustat->user, tmp); 4197 cpustat->user = cputime64_add(cpustat->user, tmp);
4189 cpustat->guest = cputime64_add(cpustat->guest, tmp); 4198 cpustat->guest = cputime64_add(cpustat->guest, tmp);
4190} 4199}
4191 4200
4192/* 4201/*
4193 * Account scaled user cpu time to a process.
4194 * @p: the process that the cpu time gets accounted to
4195 * @cputime: the cpu time spent in user space since the last update
4196 */
4197void account_user_time_scaled(struct task_struct *p, cputime_t cputime)
4198{
4199 p->utimescaled = cputime_add(p->utimescaled, cputime);
4200}
4201
4202/*
4203 * Account system cpu time to a process. 4202 * Account system cpu time to a process.
4204 * @p: the process that the cpu time gets accounted to 4203 * @p: the process that the cpu time gets accounted to
4205 * @hardirq_offset: the offset to subtract from hardirq_count() 4204 * @hardirq_offset: the offset to subtract from hardirq_count()
4206 * @cputime: the cpu time spent in kernel space since the last update 4205 * @cputime: the cpu time spent in kernel space since the last update
4206 * @cputime_scaled: cputime scaled by cpu frequency
4207 */ 4207 */
4208void account_system_time(struct task_struct *p, int hardirq_offset, 4208void account_system_time(struct task_struct *p, int hardirq_offset,
4209 cputime_t cputime) 4209 cputime_t cputime, cputime_t cputime_scaled)
4210{ 4210{
4211 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; 4211 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
4212 struct rq *rq = this_rq();
4213 cputime64_t tmp; 4212 cputime64_t tmp;
4214 4213
4215 if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) { 4214 if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) {
4216 account_guest_time(p, cputime); 4215 account_guest_time(p, cputime, cputime_scaled);
4217 return; 4216 return;
4218 } 4217 }
4219 4218
4219 /* Add system time to process. */
4220 p->stime = cputime_add(p->stime, cputime); 4220 p->stime = cputime_add(p->stime, cputime);
4221 p->stimescaled = cputime_add(p->stimescaled, cputime_scaled);
4221 account_group_system_time(p, cputime); 4222 account_group_system_time(p, cputime);
4222 4223
4223 /* Add system time to cpustat. */ 4224 /* Add system time to cpustat. */
@@ -4226,48 +4227,84 @@ void account_system_time(struct task_struct *p, int hardirq_offset,
4226 cpustat->irq = cputime64_add(cpustat->irq, tmp); 4227 cpustat->irq = cputime64_add(cpustat->irq, tmp);
4227 else if (softirq_count()) 4228 else if (softirq_count())
4228 cpustat->softirq = cputime64_add(cpustat->softirq, tmp); 4229 cpustat->softirq = cputime64_add(cpustat->softirq, tmp);
4229 else if (p != rq->idle)
4230 cpustat->system = cputime64_add(cpustat->system, tmp);
4231 else if (atomic_read(&rq->nr_iowait) > 0)
4232 cpustat->iowait = cputime64_add(cpustat->iowait, tmp);
4233 else 4230 else
4234 cpustat->idle = cputime64_add(cpustat->idle, tmp); 4231 cpustat->system = cputime64_add(cpustat->system, tmp);
4232
4235 /* Account for system time used */ 4233 /* Account for system time used */
4236 acct_update_integrals(p); 4234 acct_update_integrals(p);
4237} 4235}
4238 4236
4239/* 4237/*
4240 * Account scaled system cpu time to a process. 4238 * Account for involuntary wait time.
4241 * @p: the process that the cpu time gets accounted to 4239 * @steal: the cpu time spent in involuntary wait
4242 * @hardirq_offset: the offset to subtract from hardirq_count()
4243 * @cputime: the cpu time spent in kernel space since the last update
4244 */ 4240 */
4245void account_system_time_scaled(struct task_struct *p, cputime_t cputime) 4241void account_steal_time(cputime_t cputime)
4246{ 4242{
4247 p->stimescaled = cputime_add(p->stimescaled, cputime); 4243 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
4244 cputime64_t cputime64 = cputime_to_cputime64(cputime);
4245
4246 cpustat->steal = cputime64_add(cpustat->steal, cputime64);
4248} 4247}
4249 4248
4250/* 4249/*
4251 * Account for involuntary wait time. 4250 * Account for idle time.
4252 * @p: the process from which the cpu time has been stolen 4251 * @cputime: the cpu time spent in idle wait
4253 * @steal: the cpu time spent in involuntary wait
4254 */ 4252 */
4255void account_steal_time(struct task_struct *p, cputime_t steal) 4253void account_idle_time(cputime_t cputime)
4256{ 4254{
4257 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; 4255 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
4258 cputime64_t tmp = cputime_to_cputime64(steal); 4256 cputime64_t cputime64 = cputime_to_cputime64(cputime);
4259 struct rq *rq = this_rq(); 4257 struct rq *rq = this_rq();
4260 4258
4261 if (p == rq->idle) { 4259 if (atomic_read(&rq->nr_iowait) > 0)
4262 p->stime = cputime_add(p->stime, steal); 4260 cpustat->iowait = cputime64_add(cpustat->iowait, cputime64);
4263 if (atomic_read(&rq->nr_iowait) > 0) 4261 else
4264 cpustat->iowait = cputime64_add(cpustat->iowait, tmp); 4262 cpustat->idle = cputime64_add(cpustat->idle, cputime64);
4265 else
4266 cpustat->idle = cputime64_add(cpustat->idle, tmp);
4267 } else
4268 cpustat->steal = cputime64_add(cpustat->steal, tmp);
4269} 4263}
4270 4264
4265#ifndef CONFIG_VIRT_CPU_ACCOUNTING
4266
4267/*
4268 * Account a single tick of cpu time.
4269 * @p: the process that the cpu time gets accounted to
4270 * @user_tick: indicates if the tick is a user or a system tick
4271 */
4272void account_process_tick(struct task_struct *p, int user_tick)
4273{
4274 cputime_t one_jiffy = jiffies_to_cputime(1);
4275 cputime_t one_jiffy_scaled = cputime_to_scaled(one_jiffy);
4276 struct rq *rq = this_rq();
4277
4278 if (user_tick)
4279 account_user_time(p, one_jiffy, one_jiffy_scaled);
4280 else if (p != rq->idle)
4281 account_system_time(p, HARDIRQ_OFFSET, one_jiffy,
4282 one_jiffy_scaled);
4283 else
4284 account_idle_time(one_jiffy);
4285}
4286
4287/*
4288 * Account multiple ticks of steal time.
4289 * @p: the process from which the cpu time has been stolen
4290 * @ticks: number of stolen ticks
4291 */
4292void account_steal_ticks(unsigned long ticks)
4293{
4294 account_steal_time(jiffies_to_cputime(ticks));
4295}
4296
4297/*
4298 * Account multiple ticks of idle time.
4299 * @ticks: number of stolen ticks
4300 */
4301void account_idle_ticks(unsigned long ticks)
4302{
4303 account_idle_time(jiffies_to_cputime(ticks));
4304}
4305
4306#endif
4307
4271/* 4308/*
4272 * Use precise platform statistics if available: 4309 * Use precise platform statistics if available:
4273 */ 4310 */
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 76a574bbef97..1b6c05bd0d0a 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -419,7 +419,9 @@ void tick_nohz_restart_sched_tick(void)
419{ 419{
420 int cpu = smp_processor_id(); 420 int cpu = smp_processor_id();
421 struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); 421 struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
422#ifndef CONFIG_VIRT_CPU_ACCOUNTING
422 unsigned long ticks; 423 unsigned long ticks;
424#endif
423 ktime_t now; 425 ktime_t now;
424 426
425 local_irq_disable(); 427 local_irq_disable();
@@ -441,6 +443,7 @@ void tick_nohz_restart_sched_tick(void)
441 tick_do_update_jiffies64(now); 443 tick_do_update_jiffies64(now);
442 cpumask_clear_cpu(cpu, nohz_cpu_mask); 444 cpumask_clear_cpu(cpu, nohz_cpu_mask);
443 445
446#ifndef CONFIG_VIRT_CPU_ACCOUNTING
444 /* 447 /*
445 * We stopped the tick in idle. Update process times would miss the 448 * We stopped the tick in idle. Update process times would miss the
446 * time we slept as update_process_times does only a 1 tick 449 * time we slept as update_process_times does only a 1 tick
@@ -450,12 +453,9 @@ void tick_nohz_restart_sched_tick(void)
450 /* 453 /*
451 * We might be one off. Do not randomly account a huge number of ticks! 454 * We might be one off. Do not randomly account a huge number of ticks!
452 */ 455 */
453 if (ticks && ticks < LONG_MAX) { 456 if (ticks && ticks < LONG_MAX)
454 add_preempt_count(HARDIRQ_OFFSET); 457 account_idle_ticks(ticks);
455 account_system_time(current, HARDIRQ_OFFSET, 458#endif
456 jiffies_to_cputime(ticks));
457 sub_preempt_count(HARDIRQ_OFFSET);
458 }
459 459
460 touch_softlockup_watchdog(); 460 touch_softlockup_watchdog();
461 /* 461 /*
diff --git a/kernel/timer.c b/kernel/timer.c
index 566257d1dc10..dee3f641a7a7 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1018,21 +1018,6 @@ unsigned long get_next_timer_interrupt(unsigned long now)
1018} 1018}
1019#endif 1019#endif
1020 1020
1021#ifndef CONFIG_VIRT_CPU_ACCOUNTING
1022void account_process_tick(struct task_struct *p, int user_tick)
1023{
1024 cputime_t one_jiffy = jiffies_to_cputime(1);
1025
1026 if (user_tick) {
1027 account_user_time(p, one_jiffy);
1028 account_user_time_scaled(p, cputime_to_scaled(one_jiffy));
1029 } else {
1030 account_system_time(p, HARDIRQ_OFFSET, one_jiffy);
1031 account_system_time_scaled(p, cputime_to_scaled(one_jiffy));
1032 }
1033}
1034#endif
1035
1036/* 1021/*
1037 * Called from the timer interrupt handler to charge one tick to the current 1022 * Called from the timer interrupt handler to charge one tick to the current
1038 * process. user_tick is 1 if the tick is user time, 0 for system. 1023 * process. user_tick is 1 if the tick is user time, 0 for system.