diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2012-03-24 17:45:12 -0400 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2012-03-24 17:45:12 -0400 |
| commit | b53dd6d749e0a164010f2cf1fedab2b10b8bb305 (patch) | |
| tree | c241366acea35e0ab58509ef7b441c5299a1c0b8 | |
| parent | cc295d3e4924efd31c268a57f01b1412c6513301 (diff) | |
containers: abstracted out common task-type code
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | kernel-shark.c | 28 | ||||
| -rw-r--r-- | rt-graph.c | 141 | ||||
| -rw-r--r-- | rt-graph.h | 27 | ||||
| -rw-r--r-- | rt-plot-cpu.c | 30 | ||||
| -rw-r--r-- | rt-plot-cpu.h | 2 | ||||
| -rw-r--r-- | rt-plot-task.c | 338 | ||||
| -rw-r--r-- | rt-plot-task.h | 4 | ||||
| -rw-r--r-- | trace-graph.h | 2 | ||||
| -rw-r--r-- | trace-plot-task.c | 2 |
10 files changed, 180 insertions, 397 deletions
| @@ -299,7 +299,8 @@ TRACE_GUI_OBJS = trace-filter.o trace-compat.o trace-hash.o trace-dialog.o \ | |||
| 299 | TRACE_CMD_OBJS = trace-cmd.o trace-record.o trace-read.o trace-split.o trace-listen.o \ | 299 | TRACE_CMD_OBJS = trace-cmd.o trace-record.o trace-read.o trace-split.o trace-listen.o \ |
| 300 | trace-stack.o trace-options.o | 300 | trace-stack.o trace-options.o |
| 301 | TRACE_VIEW_OBJS = trace-view.o trace-view-store.o | 301 | TRACE_VIEW_OBJS = trace-view.o trace-view-store.o |
| 302 | RT_GRAPH_OBJS = rt-graph.o rt-plot-task.o rt-plot-cpu.o | 302 | RT_GRAPH_OBJS = rt-graph.o rt-plot-task.o rt-plot-cpu.o rt-plot-container.o rt-plot.o \ |
| 303 | rt-plot-vcpu.o | ||
| 303 | TRACE_GRAPH_OBJS = trace-graph.o trace-plot.o \ | 304 | TRACE_GRAPH_OBJS = trace-graph.o trace-plot.o \ |
| 304 | trace-plot-cpu.o trace-plot-task.o \ | 305 | trace-plot-cpu.o trace-plot-task.o \ |
| 305 | $(RT_GRAPH_OBJS) task-list.o | 306 | $(RT_GRAPH_OBJS) task-list.o |
diff --git a/kernel-shark.c b/kernel-shark.c index 6e41406..6b6cdd4 100644 --- a/kernel-shark.c +++ b/kernel-shark.c | |||
| @@ -1308,6 +1308,18 @@ plot_rt_tasks_clicked (gpointer data) | |||
| 1308 | free(selected); | 1308 | free(selected); |
| 1309 | } | 1309 | } |
| 1310 | 1310 | ||
| 1311 | /* Callback for the clicked signal of the plot real-time tasks button */ | ||
| 1312 | static void | ||
| 1313 | plot_containers_clicked (gpointer data) | ||
| 1314 | { | ||
| 1315 | struct shark_info *info = data; | ||
| 1316 | struct graph_info *ginfo = info->ginfo; | ||
| 1317 | if (!ginfo->handle) | ||
| 1318 | return; | ||
| 1319 | |||
| 1320 | trace_container_dialog(ginfo, NULL); | ||
| 1321 | } | ||
| 1322 | |||
| 1311 | static void | 1323 | static void |
| 1312 | show_all_rt_clicked (gpointer data) | 1324 | show_all_rt_clicked (gpointer data) |
| 1313 | { | 1325 | { |
| @@ -2259,6 +2271,22 @@ void kernel_shark(int argc, char **argv) | |||
| 2259 | 2271 | ||
| 2260 | /* --- Plot - RT CPUs Option --- */ | 2272 | /* --- Plot - RT CPUs Option --- */ |
| 2261 | 2273 | ||
| 2274 | sub_item = gtk_menu_item_new_with_label("Containers"); | ||
| 2275 | |||
| 2276 | /* Add them to the menu */ | ||
| 2277 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | ||
| 2278 | |||
| 2279 | /* We can attach the Quit menu item to our exit function */ | ||
| 2280 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | ||
| 2281 | G_CALLBACK (plot_containers_clicked), | ||
| 2282 | (gpointer) info); | ||
| 2283 | |||
| 2284 | /* We do need to show menu items */ | ||
| 2285 | gtk_widget_show(sub_item); | ||
| 2286 | |||
| 2287 | |||
| 2288 | /* --- Plot - RT CPUs Option --- */ | ||
| 2289 | |||
| 2262 | sub_item = gtk_menu_item_new_with_label("Real-Time CPUs"); | 2290 | sub_item = gtk_menu_item_new_with_label("Real-Time CPUs"); |
| 2263 | 2291 | ||
| 2264 | /* Add them to the menu */ | 2292 | /* Add them to the menu */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | #include <stdio.h> | 1 | #include <stdio.h> |
| 2 | #include <string.h. | 2 | #include <string.h> |
| 3 | #include "trace-graph.h" | 3 | #include "trace-graph.h" |
| 4 | #include "trace-hash.h" | 4 | #include "trace-hash.h" |
| 5 | 5 | ||
| @@ -14,16 +14,11 @@ | |||
| 14 | #define dprintf(l, x...) do { if (0) printf(x); } while (0) | 14 | #define dprintf(l, x...) do { if (0) printf(x); } while (0) |
| 15 | #endif | 15 | #endif |
| 16 | 16 | ||
| 17 | static guint get_event_hash_key(gint eid) | 17 | static inline guint get_event_hash_key(gint eid) |
| 18 | { | 18 | { |
| 19 | return trace_hash(eid) % TS_HASH_SIZE; | 19 | return trace_hash(eid) % TS_HASH_SIZE; |
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | static int get_container_key(gint cid) | ||
| 23 | { | ||
| 24 | return trace_hash(cid) % CONT_HASH_SIZE; | ||
| 25 | } | ||
| 26 | |||
| 27 | /* | 22 | /* |
| 28 | * Returns string value stored in @field. | 23 | * Returns string value stored in @field. |
| 29 | */ | 24 | */ |
| @@ -100,10 +95,10 @@ add_ts_hash(struct ts_list **events, gint eid, gint key, | |||
| 100 | return field; | 95 | return field; |
| 101 | } | 96 | } |
| 102 | 97 | ||
| 103 | /* | 98 | /** |
| 104 | * Return container for @cid and @key, if present. | 99 | * Return container for @cid and @key, if present. |
| 105 | */ | 100 | */ |
| 106 | static struct cont_list* | 101 | struct cont_list* |
| 107 | find_container(struct cont_list **conts, gint cid, gint key) | 102 | find_container(struct cont_list **conts, gint cid, gint key) |
| 108 | { | 103 | { |
| 109 | struct cont_list *list; | 104 | struct cont_list *list; |
| @@ -126,11 +121,13 @@ add_container(struct cont_list **conts, gint cid, char *name) | |||
| 126 | key = get_container_key(cid); | 121 | key = get_container_key(cid); |
| 127 | 122 | ||
| 128 | list = find_container(conts, cid, key); | 123 | list = find_container(conts, cid, key); |
| 124 | |||
| 129 | if (!list) { | 125 | if (!list) { |
| 130 | list = malloc_or_die(sizeof(*list)); | 126 | list = malloc_or_die(sizeof(*list)); |
| 131 | list->cid = cid; | 127 | list->cid = cid; |
| 132 | list->name = name; | 128 | list->name = name; |
| 133 | list->vcpus = NULL; | 129 | list->vcpus = NULL; |
| 130 | list->plotted = FALSE; | ||
| 134 | 131 | ||
| 135 | list->next = conts[key]; | 132 | list->next = conts[key]; |
| 136 | conts[key] = list; | 133 | conts[key] = list; |
| @@ -150,7 +147,7 @@ add_vcpu(struct cont_list **conts, | |||
| 150 | { | 147 | { |
| 151 | int key; | 148 | int key; |
| 152 | struct cont_list *clist; | 149 | struct cont_list *clist; |
| 153 | struct vcpu_list *vlist; | 150 | struct vcpu_list *vlist, *prev, *next; |
| 154 | 151 | ||
| 155 | key = get_container_key(cid); | 152 | key = get_container_key(cid); |
| 156 | clist = find_container(conts, cid, key); | 153 | clist = find_container(conts, cid, key); |
| @@ -168,8 +165,24 @@ add_vcpu(struct cont_list **conts, | |||
| 168 | vlist->params.wcet = wcet; | 165 | vlist->params.wcet = wcet; |
| 169 | vlist->params.period = period; | 166 | vlist->params.period = period; |
| 170 | 167 | ||
| 171 | vlist->next = clist->vcpus; | 168 | /* Insert in order */ |
| 172 | clist->vcpus = vlist; | 169 | if (!clist->vcpus) { |
| 170 | vlist->next = clist->vcpus; | ||
| 171 | clist->vcpus = vlist; | ||
| 172 | } else { | ||
| 173 | prev = clist->vcpus; | ||
| 174 | for (next = prev->next; next; prev = next, next = prev->next) { | ||
| 175 | if (sid < next->sid) { | ||
| 176 | vlist->next = next; | ||
| 177 | prev->next = vlist; | ||
| 178 | break; | ||
| 179 | } | ||
| 180 | } | ||
| 181 | if (!next) { | ||
| 182 | vlist->next = NULL; | ||
| 183 | prev->next = vlist; | ||
| 184 | } | ||
| 185 | } | ||
| 173 | 186 | ||
| 174 | return vlist; | 187 | return vlist; |
| 175 | } | 188 | } |
| @@ -520,7 +533,7 @@ int rt_graph_check_container_param(struct graph_info *ginfo, | |||
| 520 | "litmus_container_param"); | 533 | "litmus_container_param"); |
| 521 | if (!event) | 534 | if (!event) |
| 522 | goto out; | 535 | goto out; |
| 523 | rtg_info->task_param_id = event->id; | 536 | rtg_info->container_param_id = event->id; |
| 524 | dprintf(2, "Found container_param id %d\n", event->id); | 537 | dprintf(2, "Found container_param id %d\n", event->id); |
| 525 | STORE_FIELD(rtg_info, event, cparam, cid); | 538 | STORE_FIELD(rtg_info, event, cparam, cid); |
| 526 | STORE_FIELD(rtg_info, event, cparam, name); | 539 | STORE_FIELD(rtg_info, event, cparam, name); |
| @@ -562,7 +575,7 @@ int rt_graph_check_server_param(struct graph_info *ginfo, struct record *record, | |||
| 562 | "litmus_server_param"); | 575 | "litmus_server_param"); |
| 563 | if (!event) | 576 | if (!event) |
| 564 | goto out; | 577 | goto out; |
| 565 | rtg_info->task_param_id = event->id; | 578 | rtg_info->server_param_id = event->id; |
| 566 | dprintf(2, "Found server_param id %d\n", event->id); | 579 | dprintf(2, "Found server_param id %d\n", event->id); |
| 567 | STORE_FIELD(rtg_info, event, sparam, cid); | 580 | STORE_FIELD(rtg_info, event, sparam, cid); |
| 568 | STORE_FIELD(rtg_info, event, sparam, sid); | 581 | STORE_FIELD(rtg_info, event, sparam, sid); |
| @@ -726,7 +739,8 @@ int rt_graph_check_server_release(struct graph_info *ginfo, | |||
| 726 | */ | 739 | */ |
| 727 | int rt_graph_check_server_completion(struct graph_info *ginfo, | 740 | int rt_graph_check_server_completion(struct graph_info *ginfo, |
| 728 | struct record *record, | 741 | struct record *record, |
| 729 | gint *sid, gint *job) | 742 | gint *sid, gint *job, |
| 743 | unsigned long long *ts) | ||
| 730 | { | 744 | { |
| 731 | struct rt_graph_info *rtg_info = &ginfo->rtg_info; | 745 | struct rt_graph_info *rtg_info = &ginfo->rtg_info; |
| 732 | struct pevent *pevent = ginfo->pevent; | 746 | struct pevent *pevent = ginfo->pevent; |
| @@ -749,6 +763,7 @@ int rt_graph_check_server_completion(struct graph_info *ginfo, | |||
| 749 | if (id == rtg_info->server_completion_id) { | 763 | if (id == rtg_info->server_completion_id) { |
| 750 | LOAD_INT(rtg_info, record, scompletion, sid, sid); | 764 | LOAD_INT(rtg_info, record, scompletion, sid, sid); |
| 751 | LOAD_INT(rtg_info, record, scompletion, job, job); | 765 | LOAD_INT(rtg_info, record, scompletion, job, job); |
| 766 | *ts = get_rts(ginfo, record); | ||
| 752 | 767 | ||
| 753 | dprintf(3, "Read server_completion(job(%d, %d))\n", *sid, *job); | 768 | dprintf(3, "Read server_completion(job(%d, %d))\n", *sid, *job); |
| 754 | ret = 1; | 769 | ret = 1; |
| @@ -874,99 +889,3 @@ get_rts(struct graph_info *ginfo, struct record *record) | |||
| 874 | ts = record->cached_rts; | 889 | ts = record->cached_rts; |
| 875 | return ts; | 890 | return ts; |
| 876 | } | 891 | } |
| 877 | |||
| 878 | /** | ||
| 879 | * next_rts - find a real-time timestamp AROUND an FTRACE time | ||
| 880 | * @ginfo: Current state of the graph | ||
| 881 | * @cpu: CPU to search | ||
| 882 | * @ft_target: FTRACE time to seek towards | ||
| 883 | * | ||
| 884 | * Returns the RT time of a record CLOSELY BEFORE @ft_time. | ||
| 885 | */ | ||
| 886 | unsigned long long | ||
| 887 | next_rts(struct graph_info *ginfo, int cpu, unsigned long long ft_target) | ||
| 888 | { | ||
| 889 | struct record *record; | ||
| 890 | unsigned long long ts = 0ULL; | ||
| 891 | tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, ft_target); | ||
| 892 | record = tracecmd_read_data(ginfo->handle, cpu); | ||
| 893 | if (record) { | ||
| 894 | ts = get_rts(ginfo, record); | ||
| 895 | free_record(record); | ||
| 896 | return ts; | ||
| 897 | } else | ||
| 898 | return 0; | ||
| 899 | } | ||
| 900 | |||
| 901 | /** | ||
| 902 | * set_cpu_to_rts - seek CPU to a time closely preceding a real-time timestamp | ||
| 903 | * @ginfo: Current state o the graph | ||
| 904 | * @cpu: The CPU to seek | ||
| 905 | * @rt_target: RT time to seek towards | ||
| 906 | * | ||
| 907 | * This seeks to a real-time timestamp, not the default ftrace timestamps. | ||
| 908 | * The @cpu seek location will be placed before the given time, but will | ||
| 909 | * not necessarily be placed _right_ before the time. | ||
| 910 | */ | ||
| 911 | void | ||
| 912 | set_cpu_to_rts(struct graph_info *ginfo, unsigned long long rt_target, int cpu) | ||
| 913 | { | ||
| 914 | struct record *record; | ||
| 915 | unsigned long long last_rts, rts, seek_time, last_seek; | ||
| 916 | long long diff; | ||
| 917 | |||
| 918 | rts = next_rts(ginfo, cpu, rt_target); | ||
| 919 | diff = rt_target - rts; | ||
| 920 | |||
| 921 | /* "Guess" a new target based on difference */ | ||
| 922 | seek_time = rt_target + diff; | ||
| 923 | rts = next_rts(ginfo, cpu, seek_time); | ||
| 924 | diff = rt_target - rts; | ||
| 925 | |||
| 926 | /* Zero in in 1.5x the difference increments */ | ||
| 927 | if (rts && diff > 0) { | ||
| 928 | /* rts rt_target | real-time time | ||
| 929 | * seek ? | trace-cmd time | ||
| 930 | * ---|---->>----|-------- | ||
| 931 | */ | ||
| 932 | do { | ||
| 933 | last_seek = seek_time; | ||
| 934 | last_rts = rts; | ||
| 935 | seek_time = seek_time + 1.5 * (rt_target - rts); | ||
| 936 | rts = next_rts(ginfo, cpu, seek_time); | ||
| 937 | } while (rts < rt_target && last_rts != rts); | ||
| 938 | tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, last_seek); | ||
| 939 | seek_time = last_seek; | ||
| 940 | } else if (rts && diff < 0) { | ||
| 941 | /* rt_target rts | real-time time | ||
| 942 | * ? seek | trace-cmd time | ||
| 943 | * ---|----<<----|-------- | ||
| 944 | */ | ||
| 945 | do { | ||
| 946 | seek_time = seek_time - 1.5 * (rts - rt_target); | ||
| 947 | rts = next_rts(ginfo, cpu, seek_time); | ||
| 948 | } while (rts > rt_target); | ||
| 949 | } | ||
| 950 | |||
| 951 | /* Get to first record at or after time */ | ||
| 952 | while ((record = tracecmd_read_data(ginfo->handle, cpu))) { | ||
| 953 | if (get_rts(ginfo, record) >= rt_target) | ||
| 954 | break; | ||
| 955 | free_record(record); | ||
| 956 | } | ||
| 957 | if (record) { | ||
| 958 | tracecmd_set_cursor(ginfo->handle, cpu, record->offset); | ||
| 959 | free_record(record); | ||
| 960 | } else | ||
| 961 | tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, seek_time); | ||
| 962 | } | ||
| 963 | |||
| 964 | /** | ||
| 965 | * set_cpus_to_time - seek all cpus to real-time @rt_target | ||
| 966 | */ | ||
| 967 | void set_cpus_to_rts(struct graph_info *ginfo, unsigned long long rt_target) | ||
| 968 | { | ||
| 969 | int cpu; | ||
| 970 | for (cpu = 0; cpu < ginfo->cpus; cpu++) | ||
| 971 | set_cpu_to_rts(ginfo, rt_target, cpu); | ||
| 972 | } | ||
| @@ -4,8 +4,10 @@ | |||
| 4 | #include <gtk/gtk.h> | 4 | #include <gtk/gtk.h> |
| 5 | #include "task-list.h" | 5 | #include "task-list.h" |
| 6 | #include "trace-cmd.h" | 6 | #include "trace-cmd.h" |
| 7 | #include "rt-plot.h" | ||
| 7 | #include "rt-plot-task.h" | 8 | #include "rt-plot-task.h" |
| 8 | #include "rt-plot-cpu.h" | 9 | #include "rt-plot-cpu.h" |
| 10 | #include "rt-plot-container.h" | ||
| 9 | 11 | ||
| 10 | #define LLABEL 30 | 12 | #define LLABEL 30 |
| 11 | #define SEARCH_PERIODS 3 | 13 | #define SEARCH_PERIODS 3 |
| @@ -102,6 +104,7 @@ struct rt_graph_info { | |||
| 102 | unsigned long long max_period; | 104 | unsigned long long max_period; |
| 103 | }; | 105 | }; |
| 104 | 106 | ||
| 107 | |||
| 105 | /* | 108 | /* |
| 106 | * A list of cached time-stamp fields | 109 | * A list of cached time-stamp fields |
| 107 | */ | 110 | */ |
| @@ -134,6 +137,7 @@ struct vcpu_list { | |||
| 134 | struct cont_list { | 137 | struct cont_list { |
| 135 | struct cont_list *next; | 138 | struct cont_list *next; |
| 136 | gint cid; | 139 | gint cid; |
| 140 | gboolean plotted; | ||
| 137 | const char* name; | 141 | const char* name; |
| 138 | struct vcpu_list *vcpus; | 142 | struct vcpu_list *vcpus; |
| 139 | }; | 143 | }; |
| @@ -173,7 +177,7 @@ int rt_graph_check_server_param(struct graph_info *ginfo, struct record *record, | |||
| 173 | int rt_graph_check_server_switch_to(struct graph_info *ginfo, | 177 | int rt_graph_check_server_switch_to(struct graph_info *ginfo, |
| 174 | struct record *record, | 178 | struct record *record, |
| 175 | gint *sid, gint *job, gint *tid, | 179 | gint *sid, gint *job, gint *tid, |
| 176 | unsigned long long *when); | 180 | unsigned long long *when); |
| 177 | int rt_graph_check_server_switch_away(struct graph_info *ginfo, | 181 | int rt_graph_check_server_switch_away(struct graph_info *ginfo, |
| 178 | struct record *record, | 182 | struct record *record, |
| 179 | gint *sid, gint *job, gint *tid, | 183 | gint *sid, gint *job, gint *tid, |
| @@ -185,7 +189,8 @@ int rt_graph_check_server_release(struct graph_info *ginfo, | |||
| 185 | unsigned long long *deadline); | 189 | unsigned long long *deadline); |
| 186 | int rt_graph_check_server_completion(struct graph_info *ginfo, | 190 | int rt_graph_check_server_completion(struct graph_info *ginfo, |
| 187 | struct record *record, | 191 | struct record *record, |
| 188 | gint *sid, gint *job); | 192 | gint *sid, gint *job, |
| 193 | unsigned long long *when); | ||
| 189 | int rt_graph_check_server_block(struct graph_info *ginfo, | 194 | int rt_graph_check_server_block(struct graph_info *ginfo, |
| 190 | struct record *record, gint *pid, | 195 | struct record *record, gint *pid, |
| 191 | unsigned long long *when); | 196 | unsigned long long *when); |
| @@ -193,15 +198,12 @@ int rt_graph_check_server_resume(struct graph_info *ginfo, struct record *record | |||
| 193 | gint *pid, unsigned long long *when); | 198 | gint *pid, unsigned long long *when); |
| 194 | void init_rt_event_cache(struct rt_graph_info *rtinfo); | 199 | void init_rt_event_cache(struct rt_graph_info *rtinfo); |
| 195 | 200 | ||
| 196 | /* Methods for dealing with RT timestamps */ | ||
| 197 | unsigned long long get_rts(struct graph_info *ginfo, | 201 | unsigned long long get_rts(struct graph_info *ginfo, |
| 198 | struct record *record); | 202 | struct record *record); |
| 199 | unsigned long long next_rts(struct graph_info *ginfo, int cpu, | 203 | |
| 200 | unsigned long long ft_target); | 204 | |
| 201 | void set_cpu_to_rts(struct graph_info *ginfo, | 205 | /* Other */ |
| 202 | unsigned long long rt_target, int cpu); | 206 | struct cont_list* find_container(struct cont_list **conts, gint cid, gint key); |
| 203 | void set_cpus_to_rts(struct graph_info *ginfo, | ||
| 204 | unsigned long long rt_target); | ||
| 205 | 207 | ||
| 206 | static inline void nano_to_milli(unsigned long long time, | 208 | static inline void nano_to_milli(unsigned long long time, |
| 207 | unsigned long long *msec, | 209 | unsigned long long *msec, |
| @@ -216,4 +218,11 @@ static inline float nano_as_milli(unsigned long long time) | |||
| 216 | return (float)time / 1000000ULL; | 218 | return (float)time / 1000000ULL; |
| 217 | } | 219 | } |
| 218 | 220 | ||
| 221 | static inline int get_container_key(gint cid) | ||
| 222 | { | ||
| 223 | return trace_hash(cid) % CONT_HASH_SIZE; | ||
| 224 | } | ||
| 225 | |||
| 226 | #define max_rt_search(ginfo) (SEARCH_PERIODS*ginfo->rtg_info.max_period) | ||
| 227 | |||
| 219 | #endif | 228 | #endif |
diff --git a/rt-plot-cpu.c b/rt-plot-cpu.c index e32f085..28ae26b 100644 --- a/rt-plot-cpu.c +++ b/rt-plot-cpu.c | |||
| @@ -55,13 +55,13 @@ static inline int | |||
| 55 | is_displayed(struct graph_info *ginfo, int eid) | 55 | is_displayed(struct graph_info *ginfo, int eid) |
| 56 | { | 56 | { |
| 57 | struct rt_graph_info *rtg_info = &ginfo->rtg_info; | 57 | struct rt_graph_info *rtg_info = &ginfo->rtg_info; |
| 58 | return !(eid == rtg_info->switch_away_id || | 58 | return (eid == rtg_info->switch_away_id || |
| 59 | eid == rtg_info->switch_to_id || | 59 | eid == rtg_info->switch_to_id || |
| 60 | eid == rtg_info->task_completion_id || | 60 | eid == rtg_info->task_completion_id || |
| 61 | eid == rtg_info->task_block_id || | 61 | eid == rtg_info->task_block_id || |
| 62 | eid == rtg_info->task_resume_id || | 62 | eid == rtg_info->task_resume_id || |
| 63 | eid == rtg_info->task_release_id || | 63 | eid == rtg_info->task_release_id || |
| 64 | eid == ginfo->event_sched_switch_id); | 64 | eid == ginfo->event_sched_switch_id); |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | static struct record* | 67 | static struct record* |
| @@ -78,7 +78,7 @@ __find_record(struct graph_info *ginfo, int cpu, unsigned long long time, | |||
| 78 | eid = pevent_data_type(ginfo->pevent, record); | 78 | eid = pevent_data_type(ginfo->pevent, record); |
| 79 | 79 | ||
| 80 | if (display) | 80 | if (display) |
| 81 | ignored = !is_displayed(ginfo, eid); | 81 | ignored = is_displayed(ginfo, eid); |
| 82 | 82 | ||
| 83 | if (get_rts(ginfo, record) >= time && !ignored) | 83 | if (get_rts(ginfo, record) >= time && !ignored) |
| 84 | break; | 84 | break; |
| @@ -140,6 +140,7 @@ static int get_time_info(struct graph_info *ginfo, | |||
| 140 | cpu = rtc_info->cpu; | 140 | cpu = rtc_info->cpu; |
| 141 | *out_pid = *out_job = is_running = 0; | 141 | *out_pid = *out_job = is_running = 0; |
| 142 | 142 | ||
| 143 | /* TODO: inneficient */ | ||
| 143 | *out_record = find_display_record(ginfo, cpu, time); | 144 | *out_record = find_display_record(ginfo, cpu, time); |
| 144 | record = find_record(ginfo, cpu, time); | 145 | record = find_record(ginfo, cpu, time); |
| 145 | if (!record) | 146 | if (!record) |
| @@ -330,8 +331,9 @@ static void rt_cpu_plot_start(struct graph_info *ginfo, struct graph_plot *plot, | |||
| 330 | static int rt_cpu_plot_event(struct graph_info *ginfo, struct graph_plot *plot, | 331 | static int rt_cpu_plot_event(struct graph_info *ginfo, struct graph_plot *plot, |
| 331 | struct record *record, struct plot_info *info) | 332 | struct record *record, struct plot_info *info) |
| 332 | { | 333 | { |
| 333 | int pid, eid, match, dint; | 334 | int pid = 0, eid, match, dint; |
| 334 | unsigned long long ts, dull; | 335 | unsigned long long ts, dull; |
| 336 | char *dchar; | ||
| 335 | struct rt_cpu_info *rtc_info = plot->private; | 337 | struct rt_cpu_info *rtc_info = plot->private; |
| 336 | 338 | ||
| 337 | if (!record) { | 339 | if (!record) { |
| @@ -348,18 +350,21 @@ static int rt_cpu_plot_event(struct graph_info *ginfo, struct graph_plot *plot, | |||
| 348 | try_sched_switch(ginfo, rtc_info, record, info); | 350 | try_sched_switch(ginfo, rtc_info, record, info); |
| 349 | 351 | ||
| 350 | if (!match) { | 352 | if (!match) { |
| 351 | /* Have to call checks to ensure ids are loaded. Otherwise, | 353 | /* TODO: this should not be necessary! |
| 354 | * Have to call checks to ensure ids are loaded. Otherwise, | ||
| 352 | * is_displayed will not work here or in any other methods. | 355 | * is_displayed will not work here or in any other methods. |
| 353 | */ | 356 | */ |
| 354 | #define ARG ginfo,record, &pid | 357 | #define ARG ginfo,record, &pid |
| 355 | rt_graph_check_task_param(ARG, &dull, &dull); | 358 | rt_graph_check_task_param(ARG, &dull, &dull); |
| 359 | rt_graph_check_container_param(ARG, &dchar); | ||
| 360 | rt_graph_check_server_param(ARG, &dint, &dull, &dull); | ||
| 356 | rt_graph_check_task_release(ARG, &dint, &dull, &dull); | 361 | rt_graph_check_task_release(ARG, &dint, &dull, &dull); |
| 357 | rt_graph_check_task_block(ARG, &dull); | 362 | rt_graph_check_task_block(ARG, &dull); |
| 358 | rt_graph_check_task_resume(ARG, &dull); | 363 | rt_graph_check_task_resume(ARG, &dull); |
| 359 | rt_graph_check_any(ARG, &eid, &ts); | 364 | rt_graph_check_any(ARG, &eid, &ts); |
| 360 | #undef ARG | 365 | #undef ARG |
| 361 | 366 | ||
| 362 | if (is_displayed(ginfo, eid)) { | 367 | if (!is_displayed(ginfo, eid)) { |
| 363 | info->line = TRUE; | 368 | info->line = TRUE; |
| 364 | info->lcolor = hash_pid(pid); | 369 | info->lcolor = hash_pid(pid); |
| 365 | info->ltime = ts; | 370 | info->ltime = ts; |
| @@ -462,8 +467,7 @@ static void rt_cpu_plot_destroy(struct graph_info *ginfo, struct graph_plot *plo | |||
| 462 | free(rtc_info); | 467 | free(rtc_info); |
| 463 | } | 468 | } |
| 464 | 469 | ||
| 465 | 470 | const struct plot_callbacks rt_cpu_cb = { | |
| 466 | static const struct plot_callbacks rt_cpu_cb = { | ||
| 467 | .start = rt_cpu_plot_start, | 471 | .start = rt_cpu_plot_start, |
| 468 | .destroy = rt_cpu_plot_destroy, | 472 | .destroy = rt_cpu_plot_destroy, |
| 469 | .plot_event = rt_cpu_plot_event, | 473 | .plot_event = rt_cpu_plot_event, |
diff --git a/rt-plot-cpu.h b/rt-plot-cpu.h index 2742c76..d7e1e57 100644 --- a/rt-plot-cpu.h +++ b/rt-plot-cpu.h | |||
| @@ -10,6 +10,8 @@ struct rt_cpu_info { | |||
| 10 | char *label; | 10 | char *label; |
| 11 | }; | 11 | }; |
| 12 | 12 | ||
| 13 | const struct plot_callbacks rt_cpu_cb; | ||
| 14 | |||
| 13 | void rt_plot_labeled_cpu(struct graph_info *ginfo, int cpu, char *label); | 15 | void rt_plot_labeled_cpu(struct graph_info *ginfo, int cpu, char *label); |
| 14 | void rt_plot_cpu(struct graph_info *ginfo, int cpu); | 16 | void rt_plot_cpu(struct graph_info *ginfo, int cpu); |
| 15 | void rt_plot_cpus_plotted(struct graph_info *ginfo, | 17 | void rt_plot_cpus_plotted(struct graph_info *ginfo, |
diff --git a/rt-plot-task.c b/rt-plot-task.c index 524b1f9..3175f23 100644 --- a/rt-plot-task.c +++ b/rt-plot-task.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | #include "trace-graph.h" | 3 | #include "trace-graph.h" |
| 4 | #include "trace-filter.h" | 4 | #include "trace-filter.h" |
| 5 | 5 | ||
| 6 | #define DEBUG_LEVEL 0 | 6 | #define DEBUG_LEVEL 4 |
| 7 | #if DEBUG_LEVEL > 0 | 7 | #if DEBUG_LEVEL > 0 |
| 8 | #define dprintf(l, x...) \ | 8 | #define dprintf(l, x...) \ |
| 9 | do { \ | 9 | do { \ |
| @@ -15,31 +15,6 @@ | |||
| 15 | #endif | 15 | #endif |
| 16 | 16 | ||
| 17 | /* | 17 | /* |
| 18 | * Return 1 if @record is relevant to @match_pid. | ||
| 19 | */ | ||
| 20 | static gboolean record_matches_pid(struct graph_info *ginfo, | ||
| 21 | struct record *record, | ||
| 22 | int match_pid) | ||
| 23 | { | ||
| 24 | gint dint, pid = 0, match; | ||
| 25 | unsigned long long dull; | ||
| 26 | |||
| 27 | /* Must use check_* in case record has not been found yet, | ||
| 28 | * this macro was the best of many terrible options. | ||
| 29 | */ | ||
| 30 | #define ARG ginfo, record, &pid | ||
| 31 | match = rt_graph_check_switch_to(ARG, &dint, &dull) || | ||
| 32 | rt_graph_check_switch_away(ARG, &dint, &dull) || | ||
| 33 | rt_graph_check_task_release(ARG, &dint, &dull, &dull) || | ||
| 34 | rt_graph_check_task_completion(ARG, &dint, &dull) || | ||
| 35 | rt_graph_check_task_block(ARG, &dull) || | ||
| 36 | rt_graph_check_task_resume(ARG, &dull) || | ||
| 37 | rt_graph_check_any(ARG, &dint, &dull); | ||
| 38 | #undef ARG | ||
| 39 | return pid == match_pid; | ||
| 40 | } | ||
| 41 | |||
| 42 | /* | ||
| 43 | * Return the first record after @time (within a range) which draws a box. | 18 | * Return the first record after @time (within a range) which draws a box. |
| 44 | */ | 19 | */ |
| 45 | static struct record* | 20 | static struct record* |
| @@ -83,51 +58,6 @@ next_box_record(struct graph_info *ginfo, struct rt_task_info *rtt_info, | |||
| 83 | } | 58 | } |
| 84 | 59 | ||
| 85 | /* | 60 | /* |
| 86 | * Return first relevant record after @time. | ||
| 87 | * @display: If set, only considers records which aren't plotted | ||
| 88 | */ | ||
| 89 | static struct record* | ||
| 90 | __find_record(struct graph_info *ginfo, gint pid, guint64 time, int display) | ||
| 91 | { | ||
| 92 | int next_cpu, match, eid, ignored; | ||
| 93 | struct record *record; | ||
| 94 | struct rt_graph_info *rtg_info = &ginfo->rtg_info; | ||
| 95 | |||
| 96 | set_cpus_to_rts(ginfo, time); | ||
| 97 | while ((record = tracecmd_read_next_data(ginfo->handle, &next_cpu))) { | ||
| 98 | ignored = 0; | ||
| 99 | match = record_matches_pid(ginfo, record, pid); | ||
| 100 | if (display) { | ||
| 101 | eid = pevent_data_type(ginfo->pevent, record); | ||
| 102 | ignored = (eid == rtg_info->switch_away_id || | ||
| 103 | eid == rtg_info->switch_to_id || | ||
| 104 | eid == rtg_info->task_completion_id || | ||
| 105 | eid == rtg_info->task_block_id || | ||
| 106 | eid == rtg_info->task_resume_id || | ||
| 107 | eid == rtg_info->task_release_id); | ||
| 108 | } | ||
| 109 | ignored = ignored || eid == ginfo->event_sched_switch_id; | ||
| 110 | if (get_rts(ginfo, record) >= time && match && !ignored) | ||
| 111 | break; | ||
| 112 | free_record(record); | ||
| 113 | }; | ||
| 114 | |||
| 115 | return record; | ||
| 116 | } | ||
| 117 | |||
| 118 | static inline struct record* | ||
| 119 | find_record(struct graph_info *ginfo, gint pid, guint64 time) | ||
| 120 | { | ||
| 121 | return __find_record(ginfo, pid, time, 0); | ||
| 122 | } | ||
| 123 | |||
| 124 | static inline struct record* | ||
| 125 | find_display_record(struct graph_info *ginfo, gint pid, guint64 time) | ||
| 126 | { | ||
| 127 | return __find_record(ginfo, pid, time, 1); | ||
| 128 | } | ||
| 129 | |||
| 130 | /* | ||
| 131 | * Update current job in @rtt_info, ensuring monotonic increase. | 61 | * Update current job in @rtt_info, ensuring monotonic increase. |
| 132 | */ | 62 | */ |
| 133 | static int update_job(struct rt_task_info *rtt_info, int job) | 63 | static int update_job(struct rt_task_info *rtt_info, int job) |
| @@ -145,56 +75,6 @@ static int update_job(struct rt_task_info *rtt_info, int job) | |||
| 145 | return 1; | 75 | return 1; |
| 146 | } | 76 | } |
| 147 | 77 | ||
| 148 | |||
| 149 | |||
| 150 | /* | ||
| 151 | * Find the information for the last release of @rtt_info on @cpu before @time. | ||
| 152 | * @min_ts: the minimum time stamp to parse | ||
| 153 | * | ||
| 154 | * Returns release record and @out_job, @out_release, and @out_deadline if a | ||
| 155 | * release was found after @mints matching @time. | ||
| 156 | */ | ||
| 157 | static struct record* | ||
| 158 | get_previous_release(struct graph_info *ginfo, struct rt_task_info *rtt_info, | ||
| 159 | int cpu, | ||
| 160 | unsigned long long min_ts, unsigned long long time, | ||
| 161 | int *out_job, | ||
| 162 | unsigned long long *out_release, | ||
| 163 | unsigned long long *out_deadline) | ||
| 164 | { | ||
| 165 | int pid, job, match; | ||
| 166 | unsigned long long release, deadline; | ||
| 167 | struct record *last_record, *record, *ret = NULL; | ||
| 168 | |||
| 169 | last_record = tracecmd_peek_data(ginfo->handle, cpu); | ||
| 170 | *out_job = *out_release = *out_deadline = 0; | ||
| 171 | if (!last_record) | ||
| 172 | return NULL; | ||
| 173 | last_record->ref_count++; | ||
| 174 | |||
| 175 | while ((record = tracecmd_read_prev(ginfo->handle, last_record))) { | ||
| 176 | if (record->ts < min_ts) { | ||
| 177 | free_record(record); | ||
| 178 | goto out; | ||
| 179 | } | ||
| 180 | match = rt_graph_check_task_release(ginfo, record, &pid, &job, | ||
| 181 | &release, &deadline); | ||
| 182 | free_record(last_record); | ||
| 183 | last_record = record; | ||
| 184 | if (match && (pid == rtt_info->pid) && release <= time) { | ||
| 185 | ret = record; | ||
| 186 | last_record = NULL; | ||
| 187 | *out_job = job; | ||
| 188 | *out_release = release; | ||
| 189 | *out_deadline = deadline; | ||
| 190 | break; | ||
| 191 | } | ||
| 192 | }; | ||
| 193 | out: | ||
| 194 | free_record(last_record); | ||
| 195 | return ret; | ||
| 196 | } | ||
| 197 | |||
| 198 | /* | 78 | /* |
| 199 | * Get information about the given @time. | 79 | * Get information about the given @time. |
| 200 | * @out_job: Job number at this time | 80 | * @out_job: Job number at this time |
| @@ -215,15 +95,11 @@ static int get_time_info(struct graph_info *ginfo, | |||
| 215 | struct record **out_record) | 95 | struct record **out_record) |
| 216 | 96 | ||
| 217 | { | 97 | { |
| 218 | int cpu, job; | 98 | int job; |
| 219 | unsigned long long release, deadline, min_ts; | ||
| 220 | struct record *record; | ||
| 221 | struct offset_cache *offsets; | ||
| 222 | struct rt_graph_info *rtg_info = &ginfo->rtg_info; | ||
| 223 | 99 | ||
| 224 | /* Seek CPUs to first record after this time */ | 100 | /* Seek CPUs to first record after this time */ |
| 225 | *out_job = *out_release = *out_deadline = 0; | 101 | *out_record = find_rt_record(ginfo, |
| 226 | *out_record = find_record(ginfo, rtt_info->pid, time); | 102 | (struct rt_plot_common*)rtt_info, time); |
| 227 | if (!*out_record) | 103 | if (!*out_record) |
| 228 | return 0; | 104 | return 0; |
| 229 | 105 | ||
| @@ -236,22 +112,8 @@ static int get_time_info(struct graph_info *ginfo, | |||
| 236 | goto out; | 112 | goto out; |
| 237 | } | 113 | } |
| 238 | 114 | ||
| 239 | min_ts = time - SEARCH_PERIODS * rtg_info->max_period; | 115 | get_previous_release(ginfo, rtt_info->pid, time, |
| 240 | *out_job = *out_release = *out_deadline = 0; | 116 | out_job, out_release, out_deadline); |
| 241 | |||
| 242 | offsets = save_offsets(ginfo); | ||
| 243 | for (cpu = 0; cpu < ginfo->cpus; cpu++) { | ||
| 244 | record = get_previous_release(ginfo, rtt_info, cpu, min_ts, | ||
| 245 | time, &job, &release, &deadline); | ||
| 246 | if (record && record->ts > min_ts) { | ||
| 247 | *out_job = job; | ||
| 248 | *out_release = release; | ||
| 249 | *out_deadline = deadline; | ||
| 250 | min_ts = record->ts; | ||
| 251 | } | ||
| 252 | free_record(record); | ||
| 253 | } | ||
| 254 | restore_offsets(ginfo, offsets); | ||
| 255 | out: | 117 | out: |
| 256 | return 1; | 118 | return 1; |
| 257 | } | 119 | } |
| @@ -537,9 +399,6 @@ static void rt_task_plot_start(struct graph_info *ginfo, struct graph_plot *plot | |||
| 537 | 399 | ||
| 538 | dprintf(4,"%s\n", __FUNCTION__); | 400 | dprintf(4,"%s\n", __FUNCTION__); |
| 539 | 401 | ||
| 540 | rtt_info->wcet = 0ULL; | ||
| 541 | rtt_info->period = 0ULL; | ||
| 542 | |||
| 543 | rtt_info->run_time = time; | 402 | rtt_info->run_time = time; |
| 544 | rtt_info->block_time = time; | 403 | rtt_info->block_time = time; |
| 545 | rtt_info->run_cpu = NO_CPU; | 404 | rtt_info->run_cpu = NO_CPU; |
| @@ -548,7 +407,8 @@ static void rt_task_plot_start(struct graph_info *ginfo, struct graph_plot *plot | |||
| 548 | rtt_info->fresh = TRUE; | 407 | rtt_info->fresh = TRUE; |
| 549 | for (i = 0; i < 3; i++) | 408 | for (i = 0; i < 3; i++) |
| 550 | rtt_info->first_rels[i] = 0ULL; | 409 | rtt_info->first_rels[i] = 0ULL; |
| 551 | rtt_info->last_job = 0; | 410 | rtt_info->last_job = -1; |
| 411 | update_job(rtt_info, 0); | ||
| 552 | } | 412 | } |
| 553 | 413 | ||
| 554 | static void rt_task_plot_destroy(struct graph_info *ginfo, struct graph_plot *plot) | 414 | static void rt_task_plot_destroy(struct graph_info *ginfo, struct graph_plot *plot) |
| @@ -560,143 +420,91 @@ static void rt_task_plot_destroy(struct graph_info *ginfo, struct graph_plot *pl | |||
| 560 | free(rtt_info); | 420 | free(rtt_info); |
| 561 | } | 421 | } |
| 562 | 422 | ||
| 563 | static int rt_task_plot_display_last_event(struct graph_info *ginfo, | 423 | static int |
| 564 | struct graph_plot *plot, | 424 | rt_task_plot_record_matches(struct rt_plot_common *rt, |
| 565 | struct trace_seq *s, | 425 | struct graph_info *ginfo, |
| 566 | unsigned long long time) | 426 | struct record *record) |
| 427 | |||
| 567 | { | 428 | { |
| 568 | int eid; | 429 | struct rt_task_info *rtt_info = (struct rt_task_info*)rt; |
| 569 | struct event_format *event; | 430 | gint dint, pid = 0, match, match_pid; |
| 570 | struct record *record; | 431 | unsigned long long dull; |
| 571 | struct offset_cache *offsets; | ||
| 572 | struct rt_task_info *rtt_info = plot->private; | ||
| 573 | 432 | ||
| 574 | dprintf(4,"%s\n", __FUNCTION__); | 433 | match_pid = rtt_info->pid; |
| 575 | 434 | ||
| 576 | offsets = save_offsets(ginfo); | 435 | /* Must use check_* in case record has not been found yet, |
| 577 | record = find_display_record(ginfo, rtt_info->pid, time); | 436 | * this macro was the best of many terrible options. |
| 578 | restore_offsets(ginfo, offsets); | 437 | */ |
| 579 | if (!record) | 438 | #define ARG ginfo, record, &pid |
| 580 | return 0; | 439 | match = rt_graph_check_switch_to(ARG, &dint, &dull) || |
| 440 | rt_graph_check_switch_away(ARG, &dint, &dull) || | ||
| 441 | rt_graph_check_task_release(ARG, &dint, &dull, &dull) || | ||
| 442 | rt_graph_check_task_completion(ARG, &dint, &dull) || | ||
| 443 | rt_graph_check_task_block(ARG, &dull) || | ||
| 444 | rt_graph_check_task_resume(ARG, &dull) || | ||
| 445 | rt_graph_check_any(ARG, &dint, &dull); | ||
| 446 | #undef ARG | ||
| 447 | return pid == match_pid; | ||
| 448 | } | ||
| 581 | 449 | ||
| 582 | eid = pevent_data_type(ginfo->pevent, record); | ||
| 583 | event = pevent_data_event_from_type(ginfo->pevent, eid); | ||
| 584 | if (event) | ||
| 585 | trace_seq_puts(s, event->name); | ||
| 586 | else | ||
| 587 | trace_seq_printf(s, "UNKNOWN EVENT %d\n", eid); | ||
| 588 | trace_seq_putc(s, '\n'); | ||
| 589 | trace_seq_printf(s, "CPU %d\n", record->cpu); | ||
| 590 | free_record(record); | ||
| 591 | 450 | ||
| 592 | return 1; | 451 | static int rt_task_plot_is_drawn(struct graph_info *ginfo, int eid) |
| 452 | { | ||
| 453 | struct rt_graph_info *rtg_info = &ginfo->rtg_info; | ||
| 454 | |||
| 455 | return (eid == rtg_info->switch_away_id || | ||
| 456 | eid == rtg_info->switch_to_id || | ||
| 457 | eid == rtg_info->task_completion_id || | ||
| 458 | eid == rtg_info->task_block_id || | ||
| 459 | eid == rtg_info->task_resume_id || | ||
| 460 | eid == rtg_info->task_release_id); | ||
| 593 | } | 461 | } |
| 594 | 462 | ||
| 595 | static int rt_task_plot_display_info(struct graph_info *ginfo, | 463 | static struct record* |
| 596 | struct graph_plot *plot, | 464 | rt_task_plot_write_header(struct rt_plot_common *rt, |
| 597 | struct trace_seq *s, | 465 | struct graph_info *ginfo, |
| 598 | unsigned long long time) | 466 | struct trace_seq *s, |
| 467 | unsigned long long time) | ||
| 599 | { | 468 | { |
| 600 | const char *comm; | 469 | const char *comm; |
| 601 | int pid, job, eid; | 470 | int pid, job, found; |
| 602 | struct record *record; | 471 | struct record *record; |
| 603 | struct event_format *event; | 472 | unsigned long long release, deadline; |
| 604 | unsigned long long msec, nsec; | 473 | struct rt_task_info *rtt_info = (struct rt_task_info*)rt; |
| 605 | unsigned long long release, deadline, rts; | ||
| 606 | struct rt_task_info *rtt_info = plot->private; | ||
| 607 | struct offset_cache *offsets; | ||
| 608 | 474 | ||
| 609 | dprintf(4,"%s\n", __FUNCTION__); | 475 | dprintf(4,"%s\n", __FUNCTION__); |
| 610 | 476 | ||
| 611 | offsets = save_offsets(ginfo); | 477 | found = get_time_info(ginfo, rtt_info, time, |
| 612 | get_time_info(ginfo, rtt_info, time, | 478 | &job, &release, &deadline, &record); |
| 613 | &job, &release, &deadline, &record); | 479 | if (!found) |
| 614 | restore_offsets(ginfo, offsets); | 480 | goto out; |
| 615 | 481 | ||
| 616 | pid = rtt_info->pid; | 482 | pid = rtt_info->pid; |
| 617 | comm = pevent_data_comm_from_pid(ginfo->pevent, pid); | 483 | comm = pevent_data_comm_from_pid(ginfo->pevent, pid); |
| 618 | trace_seq_printf(s, "%s-%d:%d\n", comm, pid, job); | 484 | trace_seq_printf(s, "%s-%d:%d\n", comm, pid, job); |
| 619 | 485 | ||
| 620 | if (record) { | 486 | if (in_res(ginfo, deadline, time)) { |
| 621 | rts = get_rts(ginfo, record); | 487 | trace_seq_printf(s, "\nlitmus_deadline\n" |
| 622 | eid = pevent_data_type(ginfo->pevent, record); | 488 | "deadline(job(%d,%d)): %llu\n", |
| 623 | 489 | pid, job, deadline); | |
| 624 | if (in_res(ginfo, deadline, time)) { | ||
| 625 | trace_seq_printf(s, "\nlitmus_deadline\n" | ||
| 626 | "deadline(job(%d,%d)): %llu\n", | ||
| 627 | pid, job, deadline); | ||
| 628 | } | ||
| 629 | if (in_res(ginfo, release, time)) { | ||
| 630 | trace_seq_printf(s, "\nlitmus_release\n" | ||
| 631 | "release(job(%d,%d)): %llu\n", | ||
| 632 | pid, job, release); | ||
| 633 | } | ||
| 634 | |||
| 635 | if (in_res(ginfo, rts, time)) { | ||
| 636 | event = pevent_data_event_from_type(ginfo->pevent, eid); | ||
| 637 | if (event) { | ||
| 638 | trace_seq_putc(s, '\n'); | ||
| 639 | trace_seq_puts(s, event->name); | ||
| 640 | trace_seq_putc(s, '\n'); | ||
| 641 | pevent_event_info(s, event, record); | ||
| 642 | } else | ||
| 643 | trace_seq_printf(s, "\nUNKNOWN EVENT %d\n", eid); | ||
| 644 | } | ||
| 645 | trace_seq_putc(s, '\n'); | ||
| 646 | nano_to_milli(time, &msec, &nsec); | ||
| 647 | trace_seq_printf(s, "%llu.%06llu ms CPU: %03d", | ||
| 648 | msec, nsec, record->cpu); | ||
| 649 | free_record(record); | ||
| 650 | } | 490 | } |
| 651 | 491 | if (in_res(ginfo, release, time)) { | |
| 652 | return 1; | 492 | trace_seq_printf(s, "\nlitmus_release\n" |
| 653 | } | 493 | "release(job(%d,%d)): %llu\n", |
| 654 | 494 | pid, job, release); | |
| 655 | static int rt_task_plot_match_time(struct graph_info *ginfo, | 495 | } |
| 656 | struct graph_plot *plot, | 496 | out: |
| 657 | unsigned long long time) | 497 | return record; |
| 658 | { | ||
| 659 | struct record *record = NULL; | ||
| 660 | struct rt_task_info *rtt_info = plot->private; | ||
| 661 | int next_cpu, match, ret; | ||
| 662 | |||
| 663 | dprintf(4,"%s\n", __FUNCTION__); | ||
| 664 | |||
| 665 | set_cpus_to_rts(ginfo, time); | ||
| 666 | |||
| 667 | do { | ||
| 668 | free_record(record); | ||
| 669 | record = tracecmd_read_next_data(ginfo->handle, &next_cpu); | ||
| 670 | if (!record) | ||
| 671 | return 0; | ||
| 672 | match = record_matches_pid(ginfo, record, rtt_info->pid); | ||
| 673 | } while ((!match && get_rts(ginfo, record) < time + 1) || | ||
| 674 | (match && get_rts(ginfo, record) < time)); | ||
| 675 | |||
| 676 | if (record && get_rts(ginfo, record) == time) | ||
| 677 | ret = 1; | ||
| 678 | free_record(record); | ||
| 679 | |||
| 680 | return ret; | ||
| 681 | } | ||
| 682 | |||
| 683 | static struct record * | ||
| 684 | rt_task_plot_find_record(struct graph_info *ginfo, struct graph_plot *plot, | ||
| 685 | unsigned long long time) | ||
| 686 | { | ||
| 687 | struct rt_task_info *rtt_info = plot->private; | ||
| 688 | return find_record(ginfo, rtt_info->pid, time); | ||
| 689 | } | 498 | } |
| 690 | 499 | ||
| 691 | 500 | const struct plot_callbacks rt_task_cb = { | |
| 692 | static const struct plot_callbacks rt_task_cb = { | ||
| 693 | .start = rt_task_plot_start, | 501 | .start = rt_task_plot_start, |
| 694 | .destroy = rt_task_plot_destroy, | 502 | .destroy = rt_task_plot_destroy, |
| 695 | .plot_event = rt_task_plot_event, | 503 | .plot_event = rt_task_plot_event, |
| 696 | .display_last_event = rt_task_plot_display_last_event, | 504 | .display_last_event = rt_plot_display_last_event, |
| 697 | .display_info = rt_task_plot_display_info, | 505 | .display_info = rt_plot_display_info, |
| 698 | .match_time = rt_task_plot_match_time, | 506 | .match_time = rt_plot_match_time, |
| 699 | .find_record = rt_task_plot_find_record, | 507 | .find_record = rt_plot_find_record, |
| 700 | }; | 508 | }; |
| 701 | 509 | ||
| 702 | void rt_plot_task_update_callback(gboolean accept, | 510 | void rt_plot_task_update_callback(gboolean accept, |
| @@ -806,6 +614,12 @@ void rt_plot_task(struct graph_info *ginfo, int pid, int pos) | |||
| 806 | rtt_info = malloc_or_die(sizeof(*rtt_info)); | 614 | rtt_info = malloc_or_die(sizeof(*rtt_info)); |
| 807 | rtt_info->pid = pid; | 615 | rtt_info->pid = pid; |
| 808 | rtt_info->label = malloc_or_die(LLABEL); | 616 | rtt_info->label = malloc_or_die(LLABEL); |
| 617 | rtt_info->wcet = params->wcet; | ||
| 618 | rtt_info->period = params->period; | ||
| 619 | |||
| 620 | rtt_info->common.record_matches = rt_task_plot_record_matches; | ||
| 621 | rtt_info->common.is_drawn = rt_task_plot_is_drawn; | ||
| 622 | rtt_info->common.write_header = rt_task_plot_write_header; | ||
| 809 | 623 | ||
| 810 | ms_wcet = nano_as_milli(params->wcet); | 624 | ms_wcet = nano_as_milli(params->wcet); |
| 811 | ms_period = nano_as_milli(params->period); | 625 | ms_period = nano_as_milli(params->period); |
| @@ -825,7 +639,7 @@ void rt_plot_task(struct graph_info *ginfo, int pid, int pos) | |||
| 825 | } | 639 | } |
| 826 | 640 | ||
| 827 | void rt_plot_add_all_tasks(struct graph_info *ginfo) | 641 | void rt_plot_add_all_tasks(struct graph_info *ginfo) |
| 828 | { | 642 | { |
| 829 | gint *tasks; | 643 | gint *tasks; |
| 830 | int i; | 644 | int i; |
| 831 | tasks = task_list_pids(ginfo->rtg_info.tasks); | 645 | tasks = task_list_pids(ginfo->rtg_info.tasks); |
diff --git a/rt-plot-task.h b/rt-plot-task.h index a61a2b7..ddbfb1c 100644 --- a/rt-plot-task.h +++ b/rt-plot-task.h | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | #include "trace-plot-task.h" | 4 | #include "trace-plot-task.h" |
| 5 | 5 | ||
| 6 | struct rt_task_info { | 6 | struct rt_task_info { |
| 7 | struct rt_plot_common common; | ||
| 8 | |||
| 7 | int pid; | 9 | int pid; |
| 8 | unsigned long long wcet; | 10 | unsigned long long wcet; |
| 9 | unsigned long long period; | 11 | unsigned long long period; |
| @@ -25,6 +27,8 @@ struct rt_task_info { | |||
| 25 | char *label; | 27 | char *label; |
| 26 | }; | 28 | }; |
| 27 | 29 | ||
| 30 | const struct plot_callbacks rt_task_cb; | ||
| 31 | |||
| 28 | void rt_plot_task(struct graph_info *ginfo, int pid, int pos); | 32 | void rt_plot_task(struct graph_info *ginfo, int pid, int pos); |
| 29 | void rt_plot_tasks_plotted(struct graph_info *ginfo, gint **plotted); | 33 | void rt_plot_tasks_plotted(struct graph_info *ginfo, gint **plotted); |
| 30 | void rt_plot_task_update_callback(gboolean accept, gint *selected, | 34 | void rt_plot_task_update_callback(gboolean accept, gint *selected, |
diff --git a/trace-graph.h b/trace-graph.h index 4bfef4d..d56438d 100644 --- a/trace-graph.h +++ b/trace-graph.h | |||
| @@ -47,6 +47,8 @@ enum graph_plot_type { | |||
| 47 | PLOT_TYPE_TASK, | 47 | PLOT_TYPE_TASK, |
| 48 | PLOT_TYPE_RT_TASK, | 48 | PLOT_TYPE_RT_TASK, |
| 49 | PLOT_TYPE_RT_CPU, | 49 | PLOT_TYPE_RT_CPU, |
| 50 | PLOT_TYPE_SERVER_TASK, | ||
| 51 | PLOT_TYPE_SERVER_CPU | ||
| 50 | }; | 52 | }; |
| 51 | 53 | ||
| 52 | enum plot_time_type { | 54 | enum plot_time_type { |
diff --git a/trace-plot-task.c b/trace-plot-task.c index ec0029d..4bfa038 100644 --- a/trace-plot-task.c +++ b/trace-plot-task.c | |||
| @@ -700,7 +700,7 @@ void task_plot_destroy(struct graph_info *ginfo, struct graph_plot *plot) | |||
| 700 | free(task_info); | 700 | free(task_info); |
| 701 | } | 701 | } |
| 702 | 702 | ||
| 703 | static const struct plot_callbacks task_plot_cb = { | 703 | const struct plot_callbacks task_plot_cb = { |
| 704 | .match_time = task_plot_match_time, | 704 | .match_time = task_plot_match_time, |
| 705 | .plot_event = task_plot_event, | 705 | .plot_event = task_plot_event, |
| 706 | .start = task_plot_start, | 706 | .start = task_plot_start, |
