diff options
Diffstat (limited to 'trace-cmd.c')
-rw-r--r-- | trace-cmd.c | 110 |
1 files changed, 97 insertions, 13 deletions
diff --git a/trace-cmd.c b/trace-cmd.c index 5e394a6..75bc325 100644 --- a/trace-cmd.c +++ b/trace-cmd.c | |||
@@ -57,6 +57,8 @@ static int sleep_time = 1000; | |||
57 | static int cpu_count; | 57 | static int cpu_count; |
58 | static int *pids; | 58 | static int *pids; |
59 | 59 | ||
60 | static int filter_task; | ||
61 | |||
60 | struct event_list { | 62 | struct event_list { |
61 | struct event_list *next; | 63 | struct event_list *next; |
62 | const char *event; | 64 | const char *event; |
@@ -229,6 +231,65 @@ static int set_ftrace(int set) | |||
229 | return 0; | 231 | return 0; |
230 | } | 232 | } |
231 | 233 | ||
234 | static char *get_tracing_file(const char *name); | ||
235 | static void put_tracing_file(char *file); | ||
236 | |||
237 | static void clear_trace(void) | ||
238 | { | ||
239 | FILE *fp; | ||
240 | char *path; | ||
241 | |||
242 | /* reset the trace */ | ||
243 | path = get_tracing_file("trace"); | ||
244 | fp = fopen(path, "w"); | ||
245 | if (!fp) | ||
246 | die("writing to '%s'", path); | ||
247 | put_tracing_file(path); | ||
248 | fwrite("0", 1, 1, fp); | ||
249 | fclose(fp); | ||
250 | } | ||
251 | |||
252 | static void update_ftrace_pid(const char *pid) | ||
253 | { | ||
254 | char *path; | ||
255 | int fd; | ||
256 | |||
257 | path = get_tracing_file("set_ftrace_pid"); | ||
258 | if (!path) | ||
259 | return; | ||
260 | |||
261 | fd = open(path, O_WRONLY); | ||
262 | if (fd < 0) | ||
263 | return; | ||
264 | |||
265 | if (write(fd, pid, strlen(pid)) < 0) | ||
266 | die("error writing to %s", path); | ||
267 | |||
268 | close(fd); | ||
269 | } | ||
270 | |||
271 | static void update_pid_event_filters(char *pid); | ||
272 | |||
273 | static void update_task_filter(void) | ||
274 | { | ||
275 | int pid = getpid(); | ||
276 | char spid[100]; | ||
277 | |||
278 | if (!filter_task) { | ||
279 | update_ftrace_pid(""); | ||
280 | return; | ||
281 | } | ||
282 | |||
283 | snprintf(spid, 100, "%d", pid); | ||
284 | |||
285 | update_ftrace_pid(spid); | ||
286 | |||
287 | update_pid_event_filters(spid); | ||
288 | |||
289 | /* clear the trace */ | ||
290 | |||
291 | } | ||
292 | |||
232 | void run_cmd(int argc, char **argv) | 293 | void run_cmd(int argc, char **argv) |
233 | { | 294 | { |
234 | int status; | 295 | int status; |
@@ -238,6 +299,7 @@ void run_cmd(int argc, char **argv) | |||
238 | die("failed to fork"); | 299 | die("failed to fork"); |
239 | if (!pid) { | 300 | if (!pid) { |
240 | /* child */ | 301 | /* child */ |
302 | update_task_filter(); | ||
241 | if (execvp(argv[0], argv)) | 303 | if (execvp(argv[0], argv)) |
242 | exit(-1); | 304 | exit(-1); |
243 | } | 305 | } |
@@ -664,22 +726,12 @@ static void disable_tracing(void) | |||
664 | 726 | ||
665 | static void disable_all(void) | 727 | static void disable_all(void) |
666 | { | 728 | { |
667 | FILE *fp; | ||
668 | char *path; | ||
669 | |||
670 | disable_tracing(); | 729 | disable_tracing(); |
671 | 730 | ||
672 | set_plugin("nop"); | 731 | set_plugin("nop"); |
673 | disable_event("all"); | 732 | disable_event("all"); |
674 | 733 | ||
675 | /* reset the trace */ | 734 | clear_trace(); |
676 | path = get_tracing_file("trace"); | ||
677 | fp = fopen(path, "w"); | ||
678 | if (!fp) | ||
679 | die("writing to '%s'", path); | ||
680 | put_tracing_file(path); | ||
681 | fwrite("0", 1, 1, fp); | ||
682 | fclose(fp); | ||
683 | } | 735 | } |
684 | 736 | ||
685 | static void reset_max_latency(void) | 737 | static void reset_max_latency(void) |
@@ -697,6 +749,33 @@ static void reset_max_latency(void) | |||
697 | fclose(fp); | 749 | fclose(fp); |
698 | } | 750 | } |
699 | 751 | ||
752 | static void update_pid_event_filters(char *pid) | ||
753 | { | ||
754 | struct event_list *event; | ||
755 | char *filter; | ||
756 | |||
757 | filter = malloc_or_die(strlen(pid) + strlen("(common_pid==)") + 1); | ||
758 | sprintf(filter, "(common_pid==%s)", pid); | ||
759 | |||
760 | for (event = event_selection; event; event = event->next) { | ||
761 | if (!event->neg) { | ||
762 | if (event->filter) { | ||
763 | event->filter = | ||
764 | realloc(event->filter, | ||
765 | strlen(event->filter) + | ||
766 | strlen("&&") + | ||
767 | strlen(filter) + 1); | ||
768 | strcat(event->filter, "&&"); | ||
769 | strcat(event->filter, filter); | ||
770 | } else | ||
771 | event->filter = strdup(filter); | ||
772 | enable_event(event->event, event->filter); | ||
773 | } | ||
774 | } | ||
775 | |||
776 | free(filter); | ||
777 | } | ||
778 | |||
700 | static void enable_events(void) | 779 | static void enable_events(void) |
701 | { | 780 | { |
702 | struct event_list *event; | 781 | struct event_list *event; |
@@ -889,10 +968,11 @@ void usage(char **argv) | |||
889 | printf("\n" | 968 | printf("\n" |
890 | "%s version %s\n\n" | 969 | "%s version %s\n\n" |
891 | "usage:\n" | 970 | "usage:\n" |
892 | " %s record [-v][-e event [-f filter]][-p plugin][-d][-o file][-s usecs][-O option ] [command ...]\n" | 971 | " %s record [-v][-e event [-f filter]][-p plugin][-F][-d][-o file][-s usecs][-O option ] [command ...]\n" |
893 | " -e run command with event enabled\n" | 972 | " -e run command with event enabled\n" |
894 | " -f filter for previous -e event\n" | 973 | " -f filter for previous -e event\n" |
895 | " -p run command with plugin enabled\n" | 974 | " -p run command with plugin enabled\n" |
975 | " -F filter only on the given process\n" | ||
896 | " -v will negate all -e after it (disable those events)\n" | 976 | " -v will negate all -e after it (disable those events)\n" |
897 | " -d disable function tracer when running\n" | 977 | " -d disable function tracer when running\n" |
898 | " -o data output file [default trace.dat]\n" | 978 | " -o data output file [default trace.dat]\n" |
@@ -981,7 +1061,7 @@ int main (int argc, char **argv) | |||
981 | (strcmp(argv[1], "start") == 0) || | 1061 | (strcmp(argv[1], "start") == 0) || |
982 | ((extract = strcmp(argv[1], "extract") == 0))) { | 1062 | ((extract = strcmp(argv[1], "extract") == 0))) { |
983 | 1063 | ||
984 | while ((c = getopt(argc-1, argv+1, "+he:f:p:do:O:s:v")) >= 0) { | 1064 | while ((c = getopt(argc-1, argv+1, "+he:f:Fp:do:O:s:v")) >= 0) { |
985 | switch (c) { | 1065 | switch (c) { |
986 | case 'h': | 1066 | case 'h': |
987 | usage(argv); | 1067 | usage(argv); |
@@ -1018,6 +1098,9 @@ int main (int argc, char **argv) | |||
1018 | } | 1098 | } |
1019 | break; | 1099 | break; |
1020 | 1100 | ||
1101 | case 'F': | ||
1102 | filter_task = 1; | ||
1103 | break; | ||
1021 | case 'v': | 1104 | case 'v': |
1022 | if (extract) | 1105 | if (extract) |
1023 | usage(argv); | 1106 | usage(argv); |
@@ -1173,6 +1256,7 @@ int main (int argc, char **argv) | |||
1173 | if (run_command) | 1256 | if (run_command) |
1174 | run_cmd((argc - optind) - 1, &argv[optind + 1]); | 1257 | run_cmd((argc - optind) - 1, &argv[optind + 1]); |
1175 | else { | 1258 | else { |
1259 | update_task_filter(); | ||
1176 | /* sleep till we are woken with Ctrl^C */ | 1260 | /* sleep till we are woken with Ctrl^C */ |
1177 | printf("Hit Ctrl^C to stop recording\n"); | 1261 | printf("Hit Ctrl^C to stop recording\n"); |
1178 | while (!finished) | 1262 | while (!finished) |