aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXiao Guangrong <xiaoguangrong@cn.fujitsu.com>2009-12-09 04:51:30 -0500
committerIngo Molnar <mingo@elte.hu>2009-12-09 04:59:12 -0500
commitc0c9e72150c07b4a6766cd24a6f685ec2dc9c343 (patch)
tree1672baebe9ef71d560820e70e3f6865bc6aaaf5b
parent822a6961112f0c9101d3359d8524604c3309ee6c (diff)
perf sched: Fix for getting task's execution time
In current code, task's execute time is got by reading '/proc/<pid>/sched' file, it's wrong if the task is created by pthread_create(), because every thread task has same pid. This way also has two demerits: 1: 'perf sched replay' can't work if the kernel is not compiled with the 'CONFIG_SCHED_DEBUG' option 2: perf tool should depend on proc file system So, this patch uses PERF_COUNT_SW_TASK_CLOCK to get task's execution time instead of reading /proc file. Changelog v2 -> v3: use PERF_COUNT_SW_TASK_CLOCK instead of rusage() as Ingo's suggestion Reported-by: Torok Edwin <edwintorok@gmail.com> Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> Cc: Xiao Guangrong <ericxiao.gr@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <4B1F7322.80103@cn.fujitsu.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--tools/perf/builtin-sched.c55
1 files changed, 27 insertions, 28 deletions
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 19f43faa9f81..b12b23ac06f3 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -13,7 +13,6 @@
13#include "util/debug.h" 13#include "util/debug.h"
14#include "util/data_map.h" 14#include "util/data_map.h"
15 15
16#include <sys/types.h>
17#include <sys/prctl.h> 16#include <sys/prctl.h>
18 17
19#include <semaphore.h> 18#include <semaphore.h>
@@ -414,34 +413,33 @@ static u64 get_cpu_usage_nsec_parent(void)
414 return sum; 413 return sum;
415} 414}
416 415
417static u64 get_cpu_usage_nsec_self(void) 416static int self_open_counters(void)
418{ 417{
419 char filename [] = "/proc/1234567890/sched"; 418 struct perf_event_attr attr;
420 unsigned long msecs, nsecs; 419 int fd;
421 char *line = NULL;
422 u64 total = 0;
423 size_t len = 0;
424 ssize_t chars;
425 FILE *file;
426 int ret;
427 420
428 sprintf(filename, "/proc/%d/sched", getpid()); 421 memset(&attr, 0, sizeof(attr));
429 file = fopen(filename, "r");
430 BUG_ON(!file);
431 422
432 while ((chars = getline(&line, &len, file)) != -1) { 423 attr.type = PERF_TYPE_SOFTWARE;
433 ret = sscanf(line, "se.sum_exec_runtime : %ld.%06ld\n", 424 attr.config = PERF_COUNT_SW_TASK_CLOCK;
434 &msecs, &nsecs);
435 if (ret == 2) {
436 total = msecs*1e6 + nsecs;
437 break;
438 }
439 }
440 if (line)
441 free(line);
442 fclose(file);
443 425
444 return total; 426 fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
427
428 if (fd < 0)
429 die("Error: sys_perf_event_open() syscall returned"
430 "with %d (%s)\n", fd, strerror(errno));
431 return fd;
432}
433
434static u64 get_cpu_usage_nsec_self(int fd)
435{
436 u64 runtime;
437 int ret;
438
439 ret = read(fd, &runtime, sizeof(runtime));
440 BUG_ON(ret != sizeof(runtime));
441
442 return runtime;
445} 443}
446 444
447static void *thread_func(void *ctx) 445static void *thread_func(void *ctx)
@@ -450,9 +448,11 @@ static void *thread_func(void *ctx)
450 u64 cpu_usage_0, cpu_usage_1; 448 u64 cpu_usage_0, cpu_usage_1;
451 unsigned long i, ret; 449 unsigned long i, ret;
452 char comm2[22]; 450 char comm2[22];
451 int fd;
453 452
454 sprintf(comm2, ":%s", this_task->comm); 453 sprintf(comm2, ":%s", this_task->comm);
455 prctl(PR_SET_NAME, comm2); 454 prctl(PR_SET_NAME, comm2);
455 fd = self_open_counters();
456 456
457again: 457again:
458 ret = sem_post(&this_task->ready_for_work); 458 ret = sem_post(&this_task->ready_for_work);
@@ -462,16 +462,15 @@ again:
462 ret = pthread_mutex_unlock(&start_work_mutex); 462 ret = pthread_mutex_unlock(&start_work_mutex);
463 BUG_ON(ret); 463 BUG_ON(ret);
464 464
465 cpu_usage_0 = get_cpu_usage_nsec_self(); 465 cpu_usage_0 = get_cpu_usage_nsec_self(fd);
466 466
467 for (i = 0; i < this_task->nr_events; i++) { 467 for (i = 0; i < this_task->nr_events; i++) {
468 this_task->curr_event = i; 468 this_task->curr_event = i;
469 process_sched_event(this_task, this_task->atoms[i]); 469 process_sched_event(this_task, this_task->atoms[i]);
470 } 470 }
471 471
472 cpu_usage_1 = get_cpu_usage_nsec_self(); 472 cpu_usage_1 = get_cpu_usage_nsec_self(fd);
473 this_task->cpu_usage = cpu_usage_1 - cpu_usage_0; 473 this_task->cpu_usage = cpu_usage_1 - cpu_usage_0;
474
475 ret = sem_post(&this_task->work_done_sem); 474 ret = sem_post(&this_task->work_done_sem);
476 BUG_ON(ret); 475 BUG_ON(ret);
477 476