diff options
author | Ingo Molnar <mingo@elte.hu> | 2007-07-09 12:51:59 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2007-07-09 12:51:59 -0400 |
commit | b27f03d4bdc145a09fb7b0c0e004b29f1ee555fa (patch) | |
tree | 37b918b7dcc548671db53d4f3c2fdc673939e086 /fs/proc | |
parent | 1b9f19c2125dd1021b9327111dc40b14b557ee12 (diff) |
sched: make use of precise accounting for /proc task stats
make use of CFS's precise accounting to drive /proc/<pid>/stat statistics.
this code was co-authored by:
Balbir Singh <balbir@linux.vnet.ibm.com>
Dmitry Adamushko <dmitry.adamushko@gmail.com>
Ingo Molnar <mingo@elte.hu>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Dmitry Adamushko <dmitry.adamushko@gmail.com>
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/array.c | 57 |
1 files changed, 47 insertions, 10 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c index 3df644313f9b..98e78e2f18d6 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -310,6 +310,41 @@ int proc_pid_status(struct task_struct *task, char * buffer) | |||
310 | return buffer - orig; | 310 | return buffer - orig; |
311 | } | 311 | } |
312 | 312 | ||
313 | static clock_t task_utime(struct task_struct *p) | ||
314 | { | ||
315 | clock_t utime = cputime_to_clock_t(p->utime), | ||
316 | total = utime + cputime_to_clock_t(p->stime); | ||
317 | u64 temp; | ||
318 | |||
319 | /* | ||
320 | * Use CFS's precise accounting: | ||
321 | */ | ||
322 | temp = (u64)nsec_to_clock_t(p->se.sum_exec_runtime); | ||
323 | |||
324 | if (total) { | ||
325 | temp *= utime; | ||
326 | do_div(temp, total); | ||
327 | } | ||
328 | utime = (clock_t)temp; | ||
329 | |||
330 | return utime; | ||
331 | } | ||
332 | |||
333 | static clock_t task_stime(struct task_struct *p) | ||
334 | { | ||
335 | clock_t stime = cputime_to_clock_t(p->stime); | ||
336 | |||
337 | /* | ||
338 | * Use CFS's precise accounting. (we subtract utime from | ||
339 | * the total, to make sure the total observed by userspace | ||
340 | * grows monotonically - apps rely on that): | ||
341 | */ | ||
342 | stime = nsec_to_clock_t(p->se.sum_exec_runtime) - task_utime(p); | ||
343 | |||
344 | return stime; | ||
345 | } | ||
346 | |||
347 | |||
313 | static int do_task_stat(struct task_struct *task, char * buffer, int whole) | 348 | static int do_task_stat(struct task_struct *task, char * buffer, int whole) |
314 | { | 349 | { |
315 | unsigned long vsize, eip, esp, wchan = ~0UL; | 350 | unsigned long vsize, eip, esp, wchan = ~0UL; |
@@ -324,7 +359,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) | |||
324 | unsigned long long start_time; | 359 | unsigned long long start_time; |
325 | unsigned long cmin_flt = 0, cmaj_flt = 0; | 360 | unsigned long cmin_flt = 0, cmaj_flt = 0; |
326 | unsigned long min_flt = 0, maj_flt = 0; | 361 | unsigned long min_flt = 0, maj_flt = 0; |
327 | cputime_t cutime, cstime, utime, stime; | 362 | cputime_t cutime, cstime; |
363 | clock_t utime, stime; | ||
328 | unsigned long rsslim = 0; | 364 | unsigned long rsslim = 0; |
329 | char tcomm[sizeof(task->comm)]; | 365 | char tcomm[sizeof(task->comm)]; |
330 | unsigned long flags; | 366 | unsigned long flags; |
@@ -342,7 +378,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) | |||
342 | 378 | ||
343 | sigemptyset(&sigign); | 379 | sigemptyset(&sigign); |
344 | sigemptyset(&sigcatch); | 380 | sigemptyset(&sigcatch); |
345 | cutime = cstime = utime = stime = cputime_zero; | 381 | cutime = cstime = cputime_zero; |
382 | utime = stime = 0; | ||
346 | 383 | ||
347 | rcu_read_lock(); | 384 | rcu_read_lock(); |
348 | if (lock_task_sighand(task, &flags)) { | 385 | if (lock_task_sighand(task, &flags)) { |
@@ -368,15 +405,15 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) | |||
368 | do { | 405 | do { |
369 | min_flt += t->min_flt; | 406 | min_flt += t->min_flt; |
370 | maj_flt += t->maj_flt; | 407 | maj_flt += t->maj_flt; |
371 | utime = cputime_add(utime, t->utime); | 408 | utime += task_utime(t); |
372 | stime = cputime_add(stime, t->stime); | 409 | stime += task_stime(t); |
373 | t = next_thread(t); | 410 | t = next_thread(t); |
374 | } while (t != task); | 411 | } while (t != task); |
375 | 412 | ||
376 | min_flt += sig->min_flt; | 413 | min_flt += sig->min_flt; |
377 | maj_flt += sig->maj_flt; | 414 | maj_flt += sig->maj_flt; |
378 | utime = cputime_add(utime, sig->utime); | 415 | utime += cputime_to_clock_t(sig->utime); |
379 | stime = cputime_add(stime, sig->stime); | 416 | stime += cputime_to_clock_t(sig->stime); |
380 | } | 417 | } |
381 | 418 | ||
382 | sid = signal_session(sig); | 419 | sid = signal_session(sig); |
@@ -392,8 +429,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) | |||
392 | if (!whole) { | 429 | if (!whole) { |
393 | min_flt = task->min_flt; | 430 | min_flt = task->min_flt; |
394 | maj_flt = task->maj_flt; | 431 | maj_flt = task->maj_flt; |
395 | utime = task->utime; | 432 | utime = task_utime(task); |
396 | stime = task->stime; | 433 | stime = task_stime(task); |
397 | } | 434 | } |
398 | 435 | ||
399 | /* scale priority and nice values from timeslices to -20..20 */ | 436 | /* scale priority and nice values from timeslices to -20..20 */ |
@@ -424,8 +461,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) | |||
424 | cmin_flt, | 461 | cmin_flt, |
425 | maj_flt, | 462 | maj_flt, |
426 | cmaj_flt, | 463 | cmaj_flt, |
427 | cputime_to_clock_t(utime), | 464 | utime, |
428 | cputime_to_clock_t(stime), | 465 | stime, |
429 | cputime_to_clock_t(cutime), | 466 | cputime_to_clock_t(cutime), |
430 | cputime_to_clock_t(cstime), | 467 | cputime_to_clock_t(cstime), |
431 | priority, | 468 | priority, |