diff options
| author | Steven Rostedt <srostedt@redhat.com> | 2011-01-17 19:51:43 -0500 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2011-02-01 21:00:59 -0500 |
| commit | 111fc9a48383619c3cf4f4cda6992716d661ba3a (patch) | |
| tree | 5e86ac22701202f6470662ec0d42ed136d2259e6 | |
| parent | 749f8c9a993d1feb059cabf35a35b64153bd68ea (diff) | |
trace-cmd: Add events to handle sched switch/wakeup filters
The sched_switch and sched_wakeup filters are special for tracing
pids. If we are tracing a pid, we want sched_switch and sched_wakeup
to be traced if it is waking up or switching to the given pid.
Since events are now expanded into a list holding the filter
files to be updated. Either reuse or create if necessary the
sched_* events to add the extra filters.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
| -rw-r--r-- | trace-cmd.c | 95 |
1 files changed, 60 insertions, 35 deletions
diff --git a/trace-cmd.c b/trace-cmd.c index ad3ac91..5322e61 100644 --- a/trace-cmd.c +++ b/trace-cmd.c | |||
| @@ -104,6 +104,11 @@ struct event_list { | |||
| 104 | int neg; | 104 | int neg; |
| 105 | }; | 105 | }; |
| 106 | 106 | ||
| 107 | static struct event_list *sched_switch_event; | ||
| 108 | static struct event_list *sched_wakeup_event; | ||
| 109 | static struct event_list *sched_wakeup_new_event; | ||
| 110 | static struct event_list *sched_event; | ||
| 111 | |||
| 107 | static struct event_list *event_selection; | 112 | static struct event_list *event_selection; |
| 108 | struct tracecmd_event_list *listed_events; | 113 | struct tracecmd_event_list *listed_events; |
| 109 | 114 | ||
| @@ -783,55 +788,53 @@ static void disable_all(void) | |||
| 783 | clear_trace(); | 788 | clear_trace(); |
| 784 | } | 789 | } |
| 785 | 790 | ||
| 786 | static void update_filter(const char *event_name, const char *field, | 791 | static void |
| 787 | const char *pid) | 792 | update_sched_event(struct event_list **event, const char *file, |
| 793 | const char *field, const char *pid) | ||
| 788 | { | 794 | { |
| 789 | char buf[BUFSIZ]; | ||
| 790 | char *filter_name; | ||
| 791 | char *path; | ||
| 792 | char *filter; | 795 | char *filter; |
| 793 | int fd; | 796 | char *path; |
| 794 | int ret; | 797 | char *buf; |
| 795 | 798 | char *p; | |
| 796 | filter_name = malloc_or_die(strlen(event_name) + | ||
| 797 | strlen("events//filter") + 1); | ||
| 798 | sprintf(filter_name, "events/%s/filter", event_name); | ||
| 799 | |||
| 800 | path = tracecmd_get_tracing_file(filter_name); | ||
| 801 | free(filter_name); | ||
| 802 | |||
| 803 | /* Ignore if file does not exist */ | ||
| 804 | fd = open(path, O_RDONLY); | ||
| 805 | if (fd < 0) | ||
| 806 | goto out; | ||
| 807 | 799 | ||
| 808 | ret = read(fd, buf, BUFSIZ); | 800 | if (!*event) { |
| 809 | if (ret < 0) | 801 | /* No sched events are being processed, ignore */ |
| 810 | die("Can't read %s", path); | 802 | if (!sched_event) |
| 811 | close(fd); | 803 | return; |
| 804 | *event = malloc_or_die(sizeof(**event)); | ||
| 805 | memset(*event, 0, sizeof(**event)); | ||
| 806 | (*event)->event = file; | ||
| 807 | p = malloc_or_die(strlen(file) + strlen("events//filter") + 1); | ||
| 808 | sprintf(p, "events/%s/filter", file); | ||
| 809 | path = tracecmd_get_tracing_file(p); | ||
| 810 | free(p); | ||
| 811 | (*event)->filter_file = strdup(path); | ||
| 812 | if (sched_event->filter) | ||
| 813 | (*event)->filter = strdup(sched_event->filter); | ||
| 814 | tracecmd_put_tracing_file(path); | ||
| 815 | } | ||
| 812 | 816 | ||
| 813 | if (ret >= BUFSIZ) | 817 | path = (*event)->filter_file; |
| 814 | ret = BUFSIZ - 1; | 818 | if (!path) |
| 819 | return; | ||
| 815 | 820 | ||
| 816 | buf[ret] = 0; | 821 | filter = (*event)->filter; |
| 817 | 822 | ||
| 818 | /* append unless there is currently no filter */ | 823 | if (!filter) { |
| 819 | if (strncmp(buf, "none", 4) == 0) { | ||
| 820 | filter = malloc_or_die(strlen(pid) + strlen(field) + | 824 | filter = malloc_or_die(strlen(pid) + strlen(field) + |
| 821 | strlen("(==)") + 1); | 825 | strlen("(==)") + 1); |
| 822 | sprintf(filter, "(%s==%s)", field, pid); | 826 | sprintf(filter, "(%s==%s)", field, pid); |
| 823 | } else { | 827 | } else { |
| 828 | buf = filter; | ||
| 824 | filter = malloc_or_die(strlen(pid) + strlen(field) + | 829 | filter = malloc_or_die(strlen(pid) + strlen(field) + |
| 825 | strlen(buf) + strlen("()||(==)") + 1); | 830 | strlen(buf) + strlen("()||(==)") + 1); |
| 826 | sprintf(filter, "(%s)||(%s==%s)", buf, field, pid); | 831 | sprintf(filter, "(%s)||(%s==%s)", buf, field, pid); |
| 832 | free(buf); | ||
| 827 | } | 833 | } |
| 828 | 834 | ||
| 829 | write_filter(path, filter); | 835 | (*event)->filter = filter; |
| 830 | |||
| 831 | free(filter); | ||
| 832 | 836 | ||
| 833 | out: | 837 | write_filter(path, filter); |
| 834 | tracecmd_put_tracing_file(path); | ||
| 835 | } | 838 | } |
| 836 | 839 | ||
| 837 | static void update_pid_event_filters(const char *pid) | 840 | static void update_pid_event_filters(const char *pid) |
| @@ -863,9 +866,11 @@ static void update_pid_event_filters(const char *pid) | |||
| 863 | /* | 866 | /* |
| 864 | * Also make sure that the sched_switch to this pid | 867 | * Also make sure that the sched_switch to this pid |
| 865 | * and wakeups of this pid are also traced. | 868 | * and wakeups of this pid are also traced. |
| 869 | * Only need to do this if the events are active. | ||
| 866 | */ | 870 | */ |
| 867 | update_filter("sched/sched_switch", "next_pid", pid); | 871 | update_sched_event(&sched_switch_event, "sched/sched_switch", "next_pid", pid); |
| 868 | update_filter("sched/sched_wakeup", "pid", pid); | 872 | update_sched_event(&sched_wakeup_event, "sched/sched_wakeup", "pid", pid); |
| 873 | update_sched_event(&sched_wakeup_new_event, "sched/sched_wakeup_new", "pid", pid); | ||
| 869 | } | 874 | } |
| 870 | 875 | ||
| 871 | static void enable_events(void) | 876 | static void enable_events(void) |
| @@ -884,6 +889,17 @@ static void enable_events(void) | |||
| 884 | } | 889 | } |
| 885 | } | 890 | } |
| 886 | 891 | ||
| 892 | static void test_event(struct event_list *event, const char *path, | ||
| 893 | const char *name, struct event_list **save, int len) | ||
| 894 | { | ||
| 895 | path += len - strlen(name); | ||
| 896 | |||
| 897 | if (strcmp(path, name) != 0) | ||
| 898 | return; | ||
| 899 | |||
| 900 | *save = event; | ||
| 901 | } | ||
| 902 | |||
| 887 | static int expand_event_files(const char *file, struct event_list *old_event) | 903 | static int expand_event_files(const char *file, struct event_list *old_event) |
| 888 | { | 904 | { |
| 889 | struct event_list *save_events = event_selection; | 905 | struct event_list *save_events = event_selection; |
| @@ -910,6 +926,8 @@ static int expand_event_files(const char *file, struct event_list *old_event) | |||
| 910 | die("No filters found"); | 926 | die("No filters found"); |
| 911 | 927 | ||
| 912 | for (i = 0; i < globbuf.gl_pathc; i++) { | 928 | for (i = 0; i < globbuf.gl_pathc; i++) { |
| 929 | int len; | ||
| 930 | |||
| 913 | path = globbuf.gl_pathv[i]; | 931 | path = globbuf.gl_pathv[i]; |
| 914 | 932 | ||
| 915 | event = malloc_or_die(sizeof(*event)); | 933 | event = malloc_or_die(sizeof(*event)); |
| @@ -932,6 +950,13 @@ static int expand_event_files(const char *file, struct event_list *old_event) | |||
| 932 | event->enable_file = p; | 950 | event->enable_file = p; |
| 933 | else | 951 | else |
| 934 | free(p); | 952 | free(p); |
| 953 | |||
| 954 | len = strlen(path); | ||
| 955 | |||
| 956 | test_event(event, path, "sched/sched_switch", &sched_switch_event, len); | ||
| 957 | test_event(event, path, "sched/sched_wakeup_new", &sched_wakeup_new_event, len); | ||
| 958 | test_event(event, path, "sched/sched_wakeup", &sched_wakeup_event, len); | ||
| 959 | test_event(event, path, "sched", &sched_event, len); | ||
| 935 | } | 960 | } |
| 936 | globfree(&globbuf); | 961 | globfree(&globbuf); |
| 937 | 962 | ||
