aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2012-03-24 17:45:12 -0400
committerJonathan Herman <hermanjl@cs.unc.edu>2012-03-24 17:45:12 -0400
commitb53dd6d749e0a164010f2cf1fedab2b10b8bb305 (patch)
treec241366acea35e0ab58509ef7b441c5299a1c0b8
parentcc295d3e4924efd31c268a57f01b1412c6513301 (diff)
containers: abstracted out common task-type code
-rw-r--r--Makefile3
-rw-r--r--kernel-shark.c28
-rw-r--r--rt-graph.c141
-rw-r--r--rt-graph.h27
-rw-r--r--rt-plot-cpu.c30
-rw-r--r--rt-plot-cpu.h2
-rw-r--r--rt-plot-task.c338
-rw-r--r--rt-plot-task.h4
-rw-r--r--trace-graph.h2
-rw-r--r--trace-plot-task.c2
10 files changed, 180 insertions, 397 deletions
diff --git a/Makefile b/Makefile
index c57b409..f1254c3 100644
--- a/Makefile
+++ b/Makefile
@@ -299,7 +299,8 @@ TRACE_GUI_OBJS = trace-filter.o trace-compat.o trace-hash.o trace-dialog.o \
299TRACE_CMD_OBJS = trace-cmd.o trace-record.o trace-read.o trace-split.o trace-listen.o \ 299TRACE_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
301TRACE_VIEW_OBJS = trace-view.o trace-view-store.o 301TRACE_VIEW_OBJS = trace-view.o trace-view-store.o
302RT_GRAPH_OBJS = rt-graph.o rt-plot-task.o rt-plot-cpu.o 302RT_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
303TRACE_GRAPH_OBJS = trace-graph.o trace-plot.o \ 304TRACE_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 */
1312static void
1313plot_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
1311static void 1323static void
1312show_all_rt_clicked (gpointer data) 1324show_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 */
diff --git a/rt-graph.c b/rt-graph.c
index aba22a9..fbf61bd 100644
--- a/rt-graph.c
+++ b/rt-graph.c
@@ -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
17static guint get_event_hash_key(gint eid) 17static 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
22static 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 */
106static struct cont_list* 101struct cont_list*
107find_container(struct cont_list **conts, gint cid, gint key) 102find_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 */
727int rt_graph_check_server_completion(struct graph_info *ginfo, 740int 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 */
886unsigned long long
887next_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 */
911void
912set_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 */
967void 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}
diff --git a/rt-graph.h b/rt-graph.h
index 68f8cb9..8252d61 100644
--- a/rt-graph.h
+++ b/rt-graph.h
@@ -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 {
134struct cont_list { 137struct 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,
173int rt_graph_check_server_switch_to(struct graph_info *ginfo, 177int 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);
177int rt_graph_check_server_switch_away(struct graph_info *ginfo, 181int 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);
186int rt_graph_check_server_completion(struct graph_info *ginfo, 190int 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);
189int rt_graph_check_server_block(struct graph_info *ginfo, 194int 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);
194void init_rt_event_cache(struct rt_graph_info *rtinfo); 199void init_rt_event_cache(struct rt_graph_info *rtinfo);
195 200
196/* Methods for dealing with RT timestamps */
197unsigned long long get_rts(struct graph_info *ginfo, 201unsigned long long get_rts(struct graph_info *ginfo,
198 struct record *record); 202 struct record *record);
199unsigned long long next_rts(struct graph_info *ginfo, int cpu, 203
200 unsigned long long ft_target); 204
201void set_cpu_to_rts(struct graph_info *ginfo, 205/* Other */
202 unsigned long long rt_target, int cpu); 206struct cont_list* find_container(struct cont_list **conts, gint cid, gint key);
203void set_cpus_to_rts(struct graph_info *ginfo,
204 unsigned long long rt_target);
205 207
206static inline void nano_to_milli(unsigned long long time, 208static 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
221static 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
55is_displayed(struct graph_info *ginfo, int eid) 55is_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
67static struct record* 67static 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,
330static int rt_cpu_plot_event(struct graph_info *ginfo, struct graph_plot *plot, 331static 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 470const struct plot_callbacks rt_cpu_cb = {
466static 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
13const struct plot_callbacks rt_cpu_cb;
14
13void rt_plot_labeled_cpu(struct graph_info *ginfo, int cpu, char *label); 15void rt_plot_labeled_cpu(struct graph_info *ginfo, int cpu, char *label);
14void rt_plot_cpu(struct graph_info *ginfo, int cpu); 16void rt_plot_cpu(struct graph_info *ginfo, int cpu);
15void rt_plot_cpus_plotted(struct graph_info *ginfo, 17void 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 */
20static 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 */
45static struct record* 20static 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 */
89static 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
118static inline struct record*
119find_record(struct graph_info *ginfo, gint pid, guint64 time)
120{
121 return __find_record(ginfo, pid, time, 0);
122}
123
124static inline struct record*
125find_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 */
133static int update_job(struct rt_task_info *rtt_info, int job) 63static 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 */
157static struct record*
158get_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
554static void rt_task_plot_destroy(struct graph_info *ginfo, struct graph_plot *plot) 414static 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
563static int rt_task_plot_display_last_event(struct graph_info *ginfo, 423static int
564 struct graph_plot *plot, 424rt_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; 451static 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
595static int rt_task_plot_display_info(struct graph_info *ginfo, 463static struct record*
596 struct graph_plot *plot, 464rt_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);
655static 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
683static struct record *
684rt_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 500const struct plot_callbacks rt_task_cb = {
692static 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
702void rt_plot_task_update_callback(gboolean accept, 510void 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
827void rt_plot_add_all_tasks(struct graph_info *ginfo) 641void 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
6struct rt_task_info { 6struct 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
30const struct plot_callbacks rt_task_cb;
31
28void rt_plot_task(struct graph_info *ginfo, int pid, int pos); 32void rt_plot_task(struct graph_info *ginfo, int pid, int pos);
29void rt_plot_tasks_plotted(struct graph_info *ginfo, gint **plotted); 33void rt_plot_tasks_plotted(struct graph_info *ginfo, gint **plotted);
30void rt_plot_task_update_callback(gboolean accept, gint *selected, 34void 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
52enum plot_time_type { 54enum 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
703static const struct plot_callbacks task_plot_cb = { 703const 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,