diff options
| author | Jonathan <hermanjl@hermanjl-Aspire-5553G.(none)> | 2012-03-05 14:22:27 -0500 |
|---|---|---|
| committer | Jonathan <hermanjl@hermanjl-Aspire-5553G.(none)> | 2012-03-05 14:22:27 -0500 |
| commit | 8bcd73ddae5d74fb9b2b8aaedd3aa6a39ef3f75d (patch) | |
| tree | 9688d2b57716c73b182722acab62101203a9105a | |
| parent | f69435260fd14ef8d9ba13774da0fcba4b5d212c (diff) | |
rt-graph: Litmus events and tasks loaded on startup
| -rw-r--r-- | Makefile | 8 | ||||
| -rw-r--r-- | kernel-shark.c | 44 | ||||
| -rw-r--r-- | rt-graph.c | 78 | ||||
| -rw-r--r-- | rt-graph.h | 31 | ||||
| -rw-r--r-- | trace-graph-main.c | 2 | ||||
| -rw-r--r-- | trace-graph.c | 91 | ||||
| -rw-r--r-- | trace-graph.h | 7 | ||||
| -rw-r--r-- | trace-plot-cpu.c | 20 |
8 files changed, 164 insertions, 117 deletions
| @@ -299,12 +299,14 @@ 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 | TRACE_GRAPH_OBJS = trace-graph.o trace-plot.o trace-plot-cpu.o trace-plot-task.o | 302 | RT_GRAPH_OBJS = rt-graph.o rt-plot-task.o |
| 303 | RT_GRAPH_OBJS = rt-graph.o | 303 | TRACE_GRAPH_OBJS = trace-graph.o trace-plot.o \ |
| 304 | trace-plot-cpu.o trace-plot-task.o \ | ||
| 305 | $(RT_GRAPH_OBJS) task-list.o | ||
| 304 | TRACE_VIEW_MAIN_OBJS = trace-view-main.o $(TRACE_VIEW_OBJS) $(TRACE_GUI_OBJS) | 306 | TRACE_VIEW_MAIN_OBJS = trace-view-main.o $(TRACE_VIEW_OBJS) $(TRACE_GUI_OBJS) |
| 305 | TRACE_GRAPH_MAIN_OBJS = trace-graph-main.o $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS) | 307 | TRACE_GRAPH_MAIN_OBJS = trace-graph-main.o $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS) |
| 306 | KERNEL_SHARK_OBJS = $(TRACE_VIEW_OBJS) $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS) \ | 308 | KERNEL_SHARK_OBJS = $(TRACE_VIEW_OBJS) $(TRACE_GRAPH_OBJS) $(TRACE_GUI_OBJS) \ |
| 307 | $(RT_GRAPH_OBJS) trace-capture.o kernel-shark.o | 309 | trace-capture.o kernel-shark.o |
| 308 | 310 | ||
| 309 | PEVENT_LIB_OBJS = parse-events.o trace-seq.o parse-filter.o parse-utils.o | 311 | PEVENT_LIB_OBJS = parse-events.o trace-seq.o parse-filter.o parse-utils.o |
| 310 | TCMD_LIB_OBJS = $(PEVENT_LIB_OBJS) trace-util.o trace-input.o trace-ftrace.o \ | 312 | TCMD_LIB_OBJS = $(PEVENT_LIB_OBJS) trace-util.o trace-input.o trace-ftrace.o \ |
diff --git a/kernel-shark.c b/kernel-shark.c index 0c89e00..e0c123a 100644 --- a/kernel-shark.c +++ b/kernel-shark.c | |||
| @@ -969,7 +969,7 @@ __list_tasks_clicked (struct shark_info *info, | |||
| 969 | 969 | ||
| 970 | store = TRACE_VIEW_STORE(model); | 970 | store = TRACE_VIEW_STORE(model); |
| 971 | 971 | ||
| 972 | tasks = trace_graph_task_list(ginfo); | 972 | tasks = task_list_pids(ginfo->tasks); |
| 973 | selected = filter_task_pids(task_filter); | 973 | selected = filter_task_pids(task_filter); |
| 974 | 974 | ||
| 975 | trace_task_dialog(info->handle, tasks, selected, func, info); | 975 | trace_task_dialog(info->handle, tasks, selected, func, info); |
| @@ -1068,7 +1068,7 @@ __graph_tasks_clicked (struct shark_info *info, | |||
| 1068 | if (!ginfo->handle) | 1068 | if (!ginfo->handle) |
| 1069 | return; | 1069 | return; |
| 1070 | 1070 | ||
| 1071 | tasks = trace_graph_task_list(ginfo); | 1071 | tasks = task_list_pids(ginfo->tasks); |
| 1072 | selected = filter_task_pids(task_filter); | 1072 | selected = filter_task_pids(task_filter); |
| 1073 | 1073 | ||
| 1074 | trace_task_dialog(ginfo->handle, tasks, selected, func, info); | 1074 | trace_task_dialog(ginfo->handle, tasks, selected, func, info); |
| @@ -1268,7 +1268,7 @@ plot_tasks_clicked (gpointer data) | |||
| 1268 | if (!ginfo->handle) | 1268 | if (!ginfo->handle) |
| 1269 | return; | 1269 | return; |
| 1270 | 1270 | ||
| 1271 | tasks = trace_graph_task_list(ginfo); | 1271 | tasks = task_list_pids(ginfo->tasks); |
| 1272 | graph_plot_task_plotted(ginfo, &selected); | 1272 | graph_plot_task_plotted(ginfo, &selected); |
| 1273 | 1273 | ||
| 1274 | trace_task_dialog(ginfo->handle, tasks, selected, | 1274 | trace_task_dialog(ginfo->handle, tasks, selected, |
| @@ -1277,6 +1277,29 @@ plot_tasks_clicked (gpointer data) | |||
| 1277 | free(selected); | 1277 | free(selected); |
| 1278 | } | 1278 | } |
| 1279 | 1279 | ||
| 1280 | /* Callback for the clicked signal of the plot real-time tasks button */ | ||
| 1281 | static void | ||
| 1282 | plot_rt_tasks_clicked (gpointer data) | ||
| 1283 | { | ||
| 1284 | struct shark_info *info = data; | ||
| 1285 | struct graph_info *ginfo = info->ginfo; | ||
| 1286 | struct rt_graph_info *rtinfo; | ||
| 1287 | gint *selected; | ||
| 1288 | gint *tasks; | ||
| 1289 | |||
| 1290 | if (!ginfo->handle) | ||
| 1291 | return; | ||
| 1292 | |||
| 1293 | rtinfo = &ginfo->rtinfo; | ||
| 1294 | tasks = task_list_pids(rtinfo->tasks); | ||
| 1295 | rt_plot_task_plotted(rtinfo, &selected); | ||
| 1296 | |||
| 1297 | trace_task_dialog(ginfo->handle, tasks, selected, | ||
| 1298 | rt_plot_task_update_callback, rtinfo); | ||
| 1299 | free(tasks); | ||
| 1300 | free(selected); | ||
| 1301 | } | ||
| 1302 | |||
| 1280 | /* Callback for the clicked signal of the help contents button */ | 1303 | /* Callback for the clicked signal of the help contents button */ |
| 1281 | static void | 1304 | static void |
| 1282 | help_content_clicked (gpointer data) | 1305 | help_content_clicked (gpointer data) |
| @@ -2184,6 +2207,21 @@ void kernel_shark(int argc, char **argv) | |||
| 2184 | /* We do need to show menu items */ | 2207 | /* We do need to show menu items */ |
| 2185 | gtk_widget_show(sub_item); | 2208 | gtk_widget_show(sub_item); |
| 2186 | 2209 | ||
| 2210 | /* --- Plot - RT Tasks Option --- */ | ||
| 2211 | |||
| 2212 | sub_item = gtk_menu_item_new_with_label("Real-Time Tasks"); | ||
| 2213 | |||
| 2214 | /* Add them to the menu */ | ||
| 2215 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | ||
| 2216 | |||
| 2217 | /* We can attach the Quit menu item to our exit function */ | ||
| 2218 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | ||
| 2219 | G_CALLBACK (plot_rt_tasks_clicked), | ||
| 2220 | (gpointer) info); | ||
| 2221 | |||
| 2222 | /* We do need to show menu items */ | ||
| 2223 | gtk_widget_show(sub_item); | ||
| 2224 | |||
| 2187 | 2225 | ||
| 2188 | /* --- End Plot Options --- */ | 2226 | /* --- End Plot Options --- */ |
| 2189 | gtk_menu_item_set_submenu(GTK_MENU_ITEM (menu_item), menu); | 2227 | gtk_menu_item_set_submenu(GTK_MENU_ITEM (menu_item), menu); |
| @@ -1,5 +1,16 @@ | |||
| 1 | #include "rt-graph.h" | 1 | #include "rt-graph.h" |
| 2 | #include "trace-hash.h" | ||
| 2 | 3 | ||
| 4 | #define DEBUG_LEVEL 1 | ||
| 5 | #if DEBUG_LEVEL > 0 | ||
| 6 | #define dprintf(l, x...) \ | ||
| 7 | do { \ | ||
| 8 | if (l <= DEBUG_LEVEL) \ | ||
| 9 | printf(x); \ | ||
| 10 | } while (0) | ||
| 11 | #else | ||
| 12 | #define dprintf(l, x...) do { if (0) printf(x); } while (0) | ||
| 13 | #endif | ||
| 3 | /** | 14 | /** |
| 4 | * rt_graph_check_task_param - check for litmus_task_param record | 15 | * rt_graph_check_task_param - check for litmus_task_param record |
| 5 | * Return 1 and @pid, @wcet, and @period if the record matches | 16 | * Return 1 and @pid, @wcet, and @period if the record matches |
| @@ -22,8 +33,9 @@ int rt_graph_check_task_param(struct rt_graph_info *rtinfo, | |||
| 22 | event = pevent_find_event_by_name(pevent, "litmus", | 33 | event = pevent_find_event_by_name(pevent, "litmus", |
| 23 | "litmus_task_param"); | 34 | "litmus_task_param"); |
| 24 | if (!event) | 35 | if (!event) |
| 25 | return 0; | 36 | goto out; |
| 26 | rtinfo->task_param_id = event->id; | 37 | rtinfo->task_param_id = event->id; |
| 38 | dprintf(2, "Found task_param id %d\n", event->id); | ||
| 27 | rtinfo->param_pid_field = pevent_find_field(event, "pid"); | 39 | rtinfo->param_pid_field = pevent_find_field(event, "pid"); |
| 28 | rtinfo->param_wcet_field = pevent_find_field(event, "wcet"); | 40 | rtinfo->param_wcet_field = pevent_find_field(event, "wcet"); |
| 29 | rtinfo->param_period_field = pevent_find_field(event, "period"); | 41 | rtinfo->param_period_field = pevent_find_field(event, "period"); |
| @@ -39,8 +51,13 @@ int rt_graph_check_task_param(struct rt_graph_info *rtinfo, | |||
| 39 | pevent_read_number_field(rtinfo->param_period_field, | 51 | pevent_read_number_field(rtinfo->param_period_field, |
| 40 | record->data, period); | 52 | record->data, period); |
| 41 | ret = 1; | 53 | ret = 1; |
| 42 | } | 54 | dprintf(3, "Read task_param (%d) record for task %d " |
| 55 | "(%llu, %llu)\n", id, *pid, *wcet, *period); | ||
| 43 | 56 | ||
| 57 | /* Only of these per task, so we can safely add new tasks now */ | ||
| 58 | add_task_hash(rtinfo->tasks, *pid); | ||
| 59 | } | ||
| 60 | out: | ||
| 44 | return ret; | 61 | return ret; |
| 45 | } | 62 | } |
| 46 | 63 | ||
| @@ -50,7 +67,7 @@ int rt_graph_check_task_param(struct rt_graph_info *rtinfo, | |||
| 50 | */ | 67 | */ |
| 51 | int rt_graph_check_task_release(struct rt_graph_info *rtinfo, | 68 | int rt_graph_check_task_release(struct rt_graph_info *rtinfo, |
| 52 | struct pevent *pevent, struct record *record, | 69 | struct pevent *pevent, struct record *record, |
| 53 | gint *pid, gint *job, | 70 | gint *pid, gint *job, unsigned long long *release, |
| 54 | unsigned long long *deadline) | 71 | unsigned long long *deadline) |
| 55 | { | 72 | { |
| 56 | struct event_format *event; | 73 | struct event_format *event; |
| @@ -62,10 +79,12 @@ int rt_graph_check_task_release(struct rt_graph_info *rtinfo, | |||
| 62 | event = pevent_find_event_by_name(pevent, "litmus", | 79 | event = pevent_find_event_by_name(pevent, "litmus", |
| 63 | "litmus_task_release"); | 80 | "litmus_task_release"); |
| 64 | if (!event) | 81 | if (!event) |
| 65 | return 0; | 82 | goto out; |
| 66 | rtinfo->task_release_id = event->id; | 83 | rtinfo->task_release_id = event->id; |
| 84 | dprintf(2, "Found task_release id %d\n", event->id); | ||
| 67 | rtinfo->release_pid_field = pevent_find_field(event, "pid"); | 85 | rtinfo->release_pid_field = pevent_find_field(event, "pid"); |
| 68 | rtinfo->release_job_field = pevent_find_field(event, "job"); | 86 | rtinfo->release_job_field = pevent_find_field(event, "job"); |
| 87 | rtinfo->release_release_field = pevent_find_field(event, "release"); | ||
| 69 | rtinfo->release_deadline_field = pevent_find_field(event, "deadline"); | 88 | rtinfo->release_deadline_field = pevent_find_field(event, "deadline"); |
| 70 | } | 89 | } |
| 71 | 90 | ||
| @@ -77,11 +96,15 @@ int rt_graph_check_task_release(struct rt_graph_info *rtinfo, | |||
| 77 | pevent_read_number_field(rtinfo->release_job_field, | 96 | pevent_read_number_field(rtinfo->release_job_field, |
| 78 | record->data, &val); | 97 | record->data, &val); |
| 79 | *job = val; | 98 | *job = val; |
| 99 | pevent_read_number_field(rtinfo->release_release_field, | ||
| 100 | record->data, release); | ||
| 80 | pevent_read_number_field(rtinfo->release_deadline_field, | 101 | pevent_read_number_field(rtinfo->release_deadline_field, |
| 81 | record->data, deadline); | 102 | record->data, deadline); |
| 82 | ret = 1; | 103 | ret = 1; |
| 104 | dprintf(3, "Read task_release (%d) record for job %d:%d, " | ||
| 105 | "dead: %llu\n", id, *pid, *job, *deadline); | ||
| 83 | } | 106 | } |
| 84 | 107 | out: | |
| 85 | return ret; | 108 | return ret; |
| 86 | } | 109 | } |
| 87 | 110 | ||
| @@ -91,21 +114,23 @@ int rt_graph_check_task_release(struct rt_graph_info *rtinfo, | |||
| 91 | */ | 114 | */ |
| 92 | int rt_graph_check_task_completion(struct rt_graph_info *rtinfo, | 115 | int rt_graph_check_task_completion(struct rt_graph_info *rtinfo, |
| 93 | struct pevent *pevent, struct record *record, | 116 | struct pevent *pevent, struct record *record, |
| 94 | gint *pid, gint *job) | 117 | gint *pid, gint *job, unsigned long long *when) |
| 95 | { | 118 | { |
| 96 | struct event_format *event; | 119 | struct event_format *event; |
| 97 | unsigned long long val; | 120 | unsigned long long val; |
| 98 | gint id; | 121 | gint id; |
| 99 | int ret = 0; | 122 | int ret = 0; |
| 100 | 123 | ||
| 101 | if (rtinfo->task_param_id < 0) { | 124 | if (rtinfo->task_completion_id < 0) { |
| 102 | event = pevent_find_event_by_name(pevent, "litmus", | 125 | event = pevent_find_event_by_name(pevent, "litmus", |
| 103 | "litmus_task_completion"); | 126 | "litmus_task_completion"); |
| 104 | if (!event) | 127 | if (!event) |
| 105 | return 0; | 128 | goto out; |
| 106 | rtinfo->task_completion_id = event->id; | 129 | rtinfo->task_completion_id = event->id; |
| 130 | dprintf(2, "Found task_completion id %d\n", event->id); | ||
| 107 | rtinfo->completion_pid_field = pevent_find_field(event, "pid"); | 131 | rtinfo->completion_pid_field = pevent_find_field(event, "pid"); |
| 108 | rtinfo->completion_job_field = pevent_find_field(event, "job"); | 132 | rtinfo->completion_job_field = pevent_find_field(event, "job"); |
| 133 | rtinfo->completion_when_field = pevent_find_field(event, "when"); | ||
| 109 | } | 134 | } |
| 110 | 135 | ||
| 111 | id = pevent_data_type(pevent, record); | 136 | id = pevent_data_type(pevent, record); |
| @@ -116,9 +141,13 @@ int rt_graph_check_task_completion(struct rt_graph_info *rtinfo, | |||
| 116 | pevent_read_number_field(rtinfo->completion_job_field, | 141 | pevent_read_number_field(rtinfo->completion_job_field, |
| 117 | record->data, &val); | 142 | record->data, &val); |
| 118 | *job = val; | 143 | *job = val; |
| 144 | pevent_read_number_field(rtinfo->completion_when_field, | ||
| 145 | record->data, when); | ||
| 119 | ret = 1; | 146 | ret = 1; |
| 147 | dprintf(3, "Read task_completion (%d) record for job %d:%d\n", | ||
| 148 | id, *pid, *job); | ||
| 120 | } | 149 | } |
| 121 | 150 | out: | |
| 122 | return ret; | 151 | return ret; |
| 123 | } | 152 | } |
| 124 | 153 | ||
| @@ -128,7 +157,7 @@ int rt_graph_check_task_completion(struct rt_graph_info *rtinfo, | |||
| 128 | */ | 157 | */ |
| 129 | int rt_graph_check_task_block(struct rt_graph_info *rtinfo, | 158 | int rt_graph_check_task_block(struct rt_graph_info *rtinfo, |
| 130 | struct pevent *pevent, struct record *record, | 159 | struct pevent *pevent, struct record *record, |
| 131 | gint *pid) | 160 | gint *pid, unsigned long long *when) |
| 132 | { | 161 | { |
| 133 | struct event_format *event; | 162 | struct event_format *event; |
| 134 | unsigned long long val; | 163 | unsigned long long val; |
| @@ -139,9 +168,11 @@ int rt_graph_check_task_block(struct rt_graph_info *rtinfo, | |||
| 139 | event = pevent_find_event_by_name(pevent, "litmus", | 168 | event = pevent_find_event_by_name(pevent, "litmus", |
| 140 | "litmus_task_block"); | 169 | "litmus_task_block"); |
| 141 | if (!event) | 170 | if (!event) |
| 142 | return 0; | 171 | goto out; |
| 172 | dprintf(2, "Found task_block id %d\n", event->id); | ||
| 143 | rtinfo->task_block_id = event->id; | 173 | rtinfo->task_block_id = event->id; |
| 144 | rtinfo->block_pid_field = pevent_find_field(event, "pid"); | 174 | rtinfo->block_pid_field = pevent_find_field(event, "pid"); |
| 175 | rtinfo->block_when_field = pevent_find_field(event, "when"); | ||
| 145 | } | 176 | } |
| 146 | 177 | ||
| 147 | id = pevent_data_type(pevent, record); | 178 | id = pevent_data_type(pevent, record); |
| @@ -149,9 +180,13 @@ int rt_graph_check_task_block(struct rt_graph_info *rtinfo, | |||
| 149 | pevent_read_number_field(rtinfo->block_pid_field, | 180 | pevent_read_number_field(rtinfo->block_pid_field, |
| 150 | record->data, &val); | 181 | record->data, &val); |
| 151 | *pid = val; | 182 | *pid = val; |
| 183 | pevent_read_number_field(rtinfo->block_when_field, | ||
| 184 | record->data, when); | ||
| 152 | ret = 1; | 185 | ret = 1; |
| 186 | dprintf(3, "Read task_block (%d) record for task %d\n", | ||
| 187 | id, *pid); | ||
| 153 | } | 188 | } |
| 154 | 189 | out: | |
| 155 | return ret; | 190 | return ret; |
| 156 | } | 191 | } |
| 157 | 192 | ||
| @@ -161,7 +196,7 @@ int rt_graph_check_task_block(struct rt_graph_info *rtinfo, | |||
| 161 | */ | 196 | */ |
| 162 | int rt_graph_check_task_resume(struct rt_graph_info *rtinfo, | 197 | int rt_graph_check_task_resume(struct rt_graph_info *rtinfo, |
| 163 | struct pevent *pevent, struct record *record, | 198 | struct pevent *pevent, struct record *record, |
| 164 | gint *pid) | 199 | gint *pid, unsigned long long *when) |
| 165 | { | 200 | { |
| 166 | struct event_format *event; | 201 | struct event_format *event; |
| 167 | unsigned long long val; | 202 | unsigned long long val; |
| @@ -172,9 +207,11 @@ int rt_graph_check_task_resume(struct rt_graph_info *rtinfo, | |||
| 172 | event = pevent_find_event_by_name(pevent, "litmus", | 207 | event = pevent_find_event_by_name(pevent, "litmus", |
| 173 | "litmus_task_resume"); | 208 | "litmus_task_resume"); |
| 174 | if (!event) | 209 | if (!event) |
| 175 | return 0; | 210 | goto out; |
| 211 | dprintf(2, "Found task_resume id %d\n", event->id); | ||
| 176 | rtinfo->task_resume_id = event->id; | 212 | rtinfo->task_resume_id = event->id; |
| 177 | rtinfo->resume_pid_field = pevent_find_field(event, "pid"); | 213 | rtinfo->resume_pid_field = pevent_find_field(event, "pid"); |
| 214 | rtinfo->resume_when_field = pevent_find_field(event, "when"); | ||
| 178 | } | 215 | } |
| 179 | 216 | ||
| 180 | id = pevent_data_type(pevent, record); | 217 | id = pevent_data_type(pevent, record); |
| @@ -182,9 +219,13 @@ int rt_graph_check_task_resume(struct rt_graph_info *rtinfo, | |||
| 182 | pevent_read_number_field(rtinfo->resume_pid_field, | 219 | pevent_read_number_field(rtinfo->resume_pid_field, |
| 183 | record->data, &val); | 220 | record->data, &val); |
| 184 | *pid = val; | 221 | *pid = val; |
| 222 | pevent_read_number_field(rtinfo->resume_when_field, | ||
| 223 | record->data, when); | ||
| 185 | ret = 1; | 224 | ret = 1; |
| 225 | dprintf(3, "Read task_resume (%d) record for task %d\n", | ||
| 226 | id, *pid); | ||
| 186 | } | 227 | } |
| 187 | 228 | out: | |
| 188 | return ret; | 229 | return ret; |
| 189 | } | 230 | } |
| 190 | 231 | ||
| @@ -193,7 +234,7 @@ int rt_graph_check_task_resume(struct rt_graph_info *rtinfo, | |||
| 193 | */ | 234 | */ |
| 194 | void init_rt_event_cache(struct rt_graph_info *rtinfo) | 235 | void init_rt_event_cache(struct rt_graph_info *rtinfo) |
| 195 | { | 236 | { |
| 196 | print("hello"); | 237 | dprintf(1, "Initializing RT event cache\n"); |
| 197 | rtinfo->task_param_id = -1; | 238 | rtinfo->task_param_id = -1; |
| 198 | rtinfo->task_release_id = -1; | 239 | rtinfo->task_release_id = -1; |
| 199 | rtinfo->task_completion_id = -1; | 240 | rtinfo->task_completion_id = -1; |
| @@ -206,11 +247,16 @@ void init_rt_event_cache(struct rt_graph_info *rtinfo) | |||
| 206 | 247 | ||
| 207 | rtinfo->release_pid_field = NULL; | 248 | rtinfo->release_pid_field = NULL; |
| 208 | rtinfo->release_job_field = NULL; | 249 | rtinfo->release_job_field = NULL; |
| 250 | rtinfo->release_release_field = NULL; | ||
| 209 | rtinfo->release_deadline_field = NULL; | 251 | rtinfo->release_deadline_field = NULL; |
| 210 | 252 | ||
| 211 | rtinfo->completion_pid_field = NULL; | 253 | rtinfo->completion_pid_field = NULL; |
| 212 | rtinfo->completion_job_field = NULL; | 254 | rtinfo->completion_job_field = NULL; |
| 255 | rtinfo->completion_when_field = NULL; | ||
| 213 | 256 | ||
| 214 | rtinfo->block_pid_field = NULL; | 257 | rtinfo->block_pid_field = NULL; |
| 258 | rtinfo->block_when_field = NULL; | ||
| 259 | |||
| 215 | rtinfo->resume_pid_field = NULL; | 260 | rtinfo->resume_pid_field = NULL; |
| 261 | rtinfo->resume_when_field = NULL; | ||
| 216 | } | 262 | } |
| @@ -3,9 +3,13 @@ | |||
| 3 | 3 | ||
| 4 | #include <gtk/gtk.h> | 4 | #include <gtk/gtk.h> |
| 5 | #include "trace-cmd.h" | 5 | #include "trace-cmd.h" |
| 6 | #include "task-list.h" | ||
| 6 | 7 | ||
| 7 | struct rt_graph_info { | 8 | struct rt_graph_info { |
| 8 | 9 | ||
| 10 | /* List of all tasks */ | ||
| 11 | struct task_list *tasks[TASK_HASH_SIZE]; | ||
| 12 | |||
| 9 | /* Cache of event fields so that they don't need to be located | 13 | /* Cache of event fields so that they don't need to be located |
| 10 | * during each access. | 14 | * during each access. |
| 11 | */ | 15 | */ |
| @@ -13,33 +17,54 @@ struct rt_graph_info { | |||
| 13 | struct format_field *param_pid_field; | 17 | struct format_field *param_pid_field; |
| 14 | struct format_field *param_wcet_field; | 18 | struct format_field *param_wcet_field; |
| 15 | struct format_field *param_period_field; | 19 | struct format_field *param_period_field; |
| 20 | |||
| 16 | gint task_release_id; | 21 | gint task_release_id; |
| 17 | struct format_field *release_pid_field; | 22 | struct format_field *release_pid_field; |
| 18 | struct format_field *release_job_field; | 23 | struct format_field *release_job_field; |
| 24 | struct format_field *release_release_field; | ||
| 19 | struct format_field *release_deadline_field; | 25 | struct format_field *release_deadline_field; |
| 26 | |||
| 20 | gint task_completion_id; | 27 | gint task_completion_id; |
| 21 | struct format_field *completion_pid_field; | 28 | struct format_field *completion_pid_field; |
| 22 | struct format_field *completion_job_field; | 29 | struct format_field *completion_job_field; |
| 30 | struct format_field *completion_when_field; | ||
| 31 | |||
| 23 | gint task_block_id; | 32 | gint task_block_id; |
| 24 | struct format_field *block_pid_field; | 33 | struct format_field *block_pid_field; |
| 34 | struct format_field *block_when_field; | ||
| 35 | |||
| 25 | gint task_resume_id; | 36 | gint task_resume_id; |
| 26 | struct format_field *resume_pid_field; | 37 | struct format_field *resume_pid_field; |
| 38 | struct format_field *resume_when_field; | ||
| 27 | 39 | ||
| 28 | }; | 40 | }; |
| 29 | 41 | ||
| 42 | /* Event parsers */ | ||
| 30 | int rt_graph_check_task_param(struct rt_graph_info *rtinfo, struct pevent *pevent, | 43 | int rt_graph_check_task_param(struct rt_graph_info *rtinfo, struct pevent *pevent, |
| 31 | struct record *record, gint *pid, | 44 | struct record *record, gint *pid, |
| 32 | unsigned long long *wcet, | 45 | unsigned long long *wcet, |
| 33 | unsigned long long *period); | 46 | unsigned long long *period); |
| 34 | int rt_graph_check_task_release(struct rt_graph_info *rtinfo, struct pevent *pevent, | 47 | int rt_graph_check_task_release(struct rt_graph_info *rtinfo, struct pevent *pevent, |
| 35 | struct record *record, gint *pid, gint *job, | 48 | struct record *record, gint *pid, gint *job, |
| 49 | unsigned long long *release, | ||
| 36 | unsigned long long *deadline); | 50 | unsigned long long *deadline); |
| 37 | int rt_graph_check_task_completion(struct rt_graph_info *rtinfo, struct pevent *pevent, | 51 | int rt_graph_check_task_completion(struct rt_graph_info *rtinfo, struct pevent *pevent, |
| 38 | struct record *record, gint *pid, gint *job); | 52 | struct record *record, gint *pid, gint *job, |
| 53 | unsigned long long *when); | ||
| 39 | int rt_graph_check_task_block(struct rt_graph_info *rtinfo, struct pevent *pevent, | 54 | int rt_graph_check_task_block(struct rt_graph_info *rtinfo, struct pevent *pevent, |
| 40 | struct record *record, gint *pid); | 55 | struct record *record, gint *pid, |
| 56 | unsigned long long *when); | ||
| 41 | int rt_graph_check_task_resume(struct rt_graph_info *rtinfo, struct pevent *pevent, | 57 | int rt_graph_check_task_resume(struct rt_graph_info *rtinfo, struct pevent *pevent, |
| 42 | struct record *record, gint *pid); | 58 | struct record *record, gint *pid, |
| 59 | unsigned long long *when); | ||
| 43 | void init_rt_event_cache(struct rt_graph_info *rtinfo); | 60 | void init_rt_event_cache(struct rt_graph_info *rtinfo); |
| 44 | 61 | ||
| 62 | /* Metadata */ | ||
| 63 | void rt_plot_task_plotted(struct rt_graph_info *rt_info, gint **plotted); | ||
| 64 | |||
| 65 | /* Callbacks for managing task list */ | ||
| 66 | void rt_plot_task_update_callback(gboolean accept, gint *selected, | ||
| 67 | gint *non_select, gpointer data); | ||
| 68 | void rt_plot_task_plotted(struct rt_graph_info *rtinfo, gint **plotted); | ||
| 69 | |||
| 45 | #endif | 70 | #endif |
diff --git a/trace-graph-main.c b/trace-graph-main.c index f2c8e54..b296994 100644 --- a/trace-graph-main.c +++ b/trace-graph-main.c | |||
| @@ -145,7 +145,7 @@ plot_tasks_clicked (gpointer data) | |||
| 145 | if (!ginfo->handle) | 145 | if (!ginfo->handle) |
| 146 | return; | 146 | return; |
| 147 | 147 | ||
| 148 | tasks = trace_graph_task_list(ginfo); | 148 | tasks = task_list_pids(ginfo->tasks); |
| 149 | graph_plot_task_plotted(ginfo, &selected); | 149 | graph_plot_task_plotted(ginfo, &selected); |
| 150 | 150 | ||
| 151 | trace_task_dialog(ginfo->handle, tasks, selected, | 151 | trace_task_dialog(ginfo->handle, tasks, selected, |
diff --git a/trace-graph.c b/trace-graph.c index 6dafadf..819482e 100644 --- a/trace-graph.c +++ b/trace-graph.c | |||
| @@ -70,91 +70,6 @@ static GdkGC *red; | |||
| 70 | static void redraw_pixmap_backend(struct graph_info *ginfo); | 70 | static void redraw_pixmap_backend(struct graph_info *ginfo); |
| 71 | static void update_label_window(struct graph_info *ginfo); | 71 | static void update_label_window(struct graph_info *ginfo); |
| 72 | 72 | ||
| 73 | struct task_list { | ||
| 74 | struct task_list *next; | ||
| 75 | gint pid; | ||
| 76 | }; | ||
| 77 | |||
| 78 | static guint get_task_hash_key(gint pid) | ||
| 79 | { | ||
| 80 | return trace_hash(pid) % TASK_HASH_SIZE; | ||
| 81 | } | ||
| 82 | |||
| 83 | static struct task_list *find_task_hash(struct graph_info *ginfo, | ||
| 84 | gint key, gint pid) | ||
| 85 | { | ||
| 86 | struct task_list *list; | ||
| 87 | |||
| 88 | for (list = ginfo->tasks[key]; list; list = list->next) { | ||
| 89 | if (list->pid == pid) | ||
| 90 | return list; | ||
| 91 | } | ||
| 92 | |||
| 93 | return NULL; | ||
| 94 | } | ||
| 95 | |||
| 96 | static struct task_list *add_task_hash(struct graph_info *ginfo, | ||
| 97 | int pid) | ||
| 98 | { | ||
| 99 | struct task_list *list; | ||
| 100 | guint key = get_task_hash_key(pid); | ||
| 101 | |||
| 102 | list = find_task_hash(ginfo, key, pid); | ||
| 103 | if (list) | ||
| 104 | return list; | ||
| 105 | |||
| 106 | list = malloc_or_die(sizeof(*list)); | ||
| 107 | list->pid = pid; | ||
| 108 | list->next = ginfo->tasks[key]; | ||
| 109 | ginfo->tasks[key] = list; | ||
| 110 | |||
| 111 | return list; | ||
| 112 | } | ||
| 113 | |||
| 114 | static void free_task_hash(struct graph_info *ginfo) | ||
| 115 | { | ||
| 116 | struct task_list *list; | ||
| 117 | int i; | ||
| 118 | |||
| 119 | for (i = 0; i < TASK_HASH_SIZE; i++) { | ||
| 120 | while (ginfo->tasks[i]) { | ||
| 121 | list = ginfo->tasks[i]; | ||
| 122 | ginfo->tasks[i] = list->next; | ||
| 123 | free(list); | ||
| 124 | } | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | /** | ||
| 129 | * trace_graph_task_list - return an allocated list of all found tasks | ||
| 130 | * @ginfo: The graph info structure | ||
| 131 | * | ||
| 132 | * Returns an allocated list of pids found in the graph, ending | ||
| 133 | * with a -1. This array must be freed with free(). | ||
| 134 | */ | ||
| 135 | gint *trace_graph_task_list(struct graph_info *ginfo) | ||
| 136 | { | ||
| 137 | struct task_list *list; | ||
| 138 | gint *pids; | ||
| 139 | gint count = 0; | ||
| 140 | gint i; | ||
| 141 | |||
| 142 | for (i = 0; i < TASK_HASH_SIZE; i++) { | ||
| 143 | list = ginfo->tasks[i]; | ||
| 144 | while (list) { | ||
| 145 | if (count) | ||
| 146 | pids = realloc(pids, sizeof(*pids) * (count + 2)); | ||
| 147 | else | ||
| 148 | pids = malloc(sizeof(*pids) * 2); | ||
| 149 | pids[count++] = list->pid; | ||
| 150 | pids[count] = -1; | ||
| 151 | list = list->next; | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | return pids; | ||
| 156 | } | ||
| 157 | |||
| 158 | static void convert_nano(unsigned long long time, unsigned long *sec, | 73 | static void convert_nano(unsigned long long time, unsigned long *sec, |
| 159 | unsigned long *usec) | 74 | unsigned long *usec) |
| 160 | { | 75 | { |
| @@ -210,6 +125,8 @@ static void init_event_cache(struct graph_info *ginfo) | |||
| 210 | * it into the pevent command line list. | 125 | * it into the pevent command line list. |
| 211 | */ | 126 | */ |
| 212 | ginfo->read_comms = TRUE; | 127 | ginfo->read_comms = TRUE; |
| 128 | |||
| 129 | init_rt_event_cache(&ginfo->rtinfo); | ||
| 213 | } | 130 | } |
| 214 | 131 | ||
| 215 | struct filter_task_item * | 132 | struct filter_task_item * |
| @@ -1082,7 +999,7 @@ int trace_graph_check_sched_switch(struct graph_info *ginfo, | |||
| 1082 | if (ginfo->read_comms) { | 999 | if (ginfo->read_comms) { |
| 1083 | /* record all pids, for task plots */ | 1000 | /* record all pids, for task plots */ |
| 1084 | this_pid = pevent_data_pid(ginfo->pevent, record); | 1001 | this_pid = pevent_data_pid(ginfo->pevent, record); |
| 1085 | add_task_hash(ginfo, this_pid); | 1002 | add_task_hash(ginfo->tasks, this_pid); |
| 1086 | } | 1003 | } |
| 1087 | 1004 | ||
| 1088 | if (ginfo->event_sched_switch_id < 0) { | 1005 | if (ginfo->event_sched_switch_id < 0) { |
| @@ -2385,7 +2302,7 @@ void trace_graph_free_info(struct graph_info *ginfo) | |||
| 2385 | pevent_filter_free(ginfo->event_filter); | 2302 | pevent_filter_free(ginfo->event_filter); |
| 2386 | trace_graph_plot_free(ginfo); | 2303 | trace_graph_plot_free(ginfo); |
| 2387 | tracecmd_close(ginfo->handle); | 2304 | tracecmd_close(ginfo->handle); |
| 2388 | free_task_hash(ginfo); | 2305 | free_task_hash(ginfo->tasks); |
| 2389 | 2306 | ||
| 2390 | ginfo->cursor = 0; | 2307 | ginfo->cursor = 0; |
| 2391 | } | 2308 | } |
diff --git a/trace-graph.h b/trace-graph.h index c3ae5a3..92d9883 100644 --- a/trace-graph.h +++ b/trace-graph.h | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include "trace-cmd.h" | 25 | #include "trace-cmd.h" |
| 26 | #include "trace-hash.h" | 26 | #include "trace-hash.h" |
| 27 | #include "trace-xml.h" | 27 | #include "trace-xml.h" |
| 28 | #include "task-list.h" | ||
| 28 | #include "rt-graph.h" | 29 | #include "rt-graph.h" |
| 29 | 30 | ||
| 30 | struct graph_info; | 31 | struct graph_info; |
| @@ -146,8 +147,6 @@ struct plot_hash { | |||
| 146 | }; | 147 | }; |
| 147 | 148 | ||
| 148 | #define PLOT_HASH_SIZE 1024 | 149 | #define PLOT_HASH_SIZE 1024 |
| 149 | #define TASK_HASH_SIZE 1024 | ||
| 150 | struct task_list; | ||
| 151 | 150 | ||
| 152 | struct graph_info { | 151 | struct graph_info { |
| 153 | struct tracecmd_input *handle; | 152 | struct tracecmd_input *handle; |
| @@ -230,7 +229,7 @@ struct graph_info { | |||
| 230 | struct format_field *wakeup_new_pid_field; | 229 | struct format_field *wakeup_new_pid_field; |
| 231 | struct format_field *wakeup_new_success_field; | 230 | struct format_field *wakeup_new_success_field; |
| 232 | 231 | ||
| 233 | struct rt_graph_info rt_info; | 232 | struct rt_graph_info rtinfo; |
| 234 | 233 | ||
| 235 | gboolean read_comms; /* Read all comms on first load */ | 234 | gboolean read_comms; /* Read all comms on first load */ |
| 236 | 235 | ||
| @@ -308,7 +307,6 @@ gboolean trace_graph_filter_on_event(struct graph_info *ginfo, struct record *re | |||
| 308 | void trace_graph_copy_filter(struct graph_info *ginfo, | 307 | void trace_graph_copy_filter(struct graph_info *ginfo, |
| 309 | gboolean all_events, | 308 | gboolean all_events, |
| 310 | struct event_filter *event_filter); | 309 | struct event_filter *event_filter); |
| 311 | gint *trace_graph_task_list(struct graph_info *ginfo); | ||
| 312 | 310 | ||
| 313 | int trace_graph_load_filters(struct graph_info *ginfo, | 311 | int trace_graph_load_filters(struct graph_info *ginfo, |
| 314 | struct tracecmd_xml_handle *handle); | 312 | struct tracecmd_xml_handle *handle); |
| @@ -400,4 +398,5 @@ void graph_plot_task_update_callback(gboolean accept, | |||
| 400 | void graph_plot_task_plotted(struct graph_info *ginfo, | 398 | void graph_plot_task_plotted(struct graph_info *ginfo, |
| 401 | gint **plotted); | 399 | gint **plotted); |
| 402 | 400 | ||
| 401 | |||
| 403 | #endif /* _TRACE_GRAPH_H */ | 402 | #endif /* _TRACE_GRAPH_H */ |
diff --git a/trace-plot-cpu.c b/trace-plot-cpu.c index 7514b34..5dea225 100644 --- a/trace-plot-cpu.c +++ b/trace-plot-cpu.c | |||
| @@ -95,11 +95,31 @@ static int filter_record(struct graph_info *ginfo, | |||
| 95 | const char *comm; | 95 | const char *comm; |
| 96 | int wake_pid; | 96 | int wake_pid; |
| 97 | int filter; | 97 | int filter; |
| 98 | gint rpid; | ||
| 99 | gint job; | ||
| 100 | unsigned long long release; | ||
| 101 | unsigned long long deadline; | ||
| 102 | unsigned long long period; | ||
| 103 | unsigned long long wcet; | ||
| 104 | unsigned long long when; | ||
| 98 | 105 | ||
| 99 | *orig_pid = pevent_data_pid(ginfo->pevent, record); | 106 | *orig_pid = pevent_data_pid(ginfo->pevent, record); |
| 100 | 107 | ||
| 101 | filter = trace_graph_filter_on_task(ginfo, *orig_pid); | 108 | filter = trace_graph_filter_on_task(ginfo, *orig_pid); |
| 102 | 109 | ||
| 110 | |||
| 111 | /* Load real-time records */ | ||
| 112 | rt_graph_check_task_param(&ginfo->rtinfo, ginfo->pevent, record, | ||
| 113 | &rpid, &wcet, &period); | ||
| 114 | rt_graph_check_task_release(&ginfo->rtinfo, ginfo->pevent, record, | ||
| 115 | &rpid, &job, &release, &deadline); | ||
| 116 | rt_graph_check_task_completion(&ginfo->rtinfo, ginfo->pevent, record, | ||
| 117 | &rpid, &job, &when); | ||
| 118 | rt_graph_check_task_block(&ginfo->rtinfo, ginfo->pevent, record, | ||
| 119 | &rpid, &when); | ||
| 120 | rt_graph_check_task_resume(&ginfo->rtinfo, ginfo->pevent, record, | ||
| 121 | &rpid, &when); | ||
| 122 | |||
| 103 | if (trace_graph_check_sched_switch(ginfo, record, sched_pid, &comm)) { | 123 | if (trace_graph_check_sched_switch(ginfo, record, sched_pid, &comm)) { |
| 104 | is_sched_switch = TRUE; | 124 | is_sched_switch = TRUE; |
| 105 | 125 | ||
