From b53dd6d749e0a164010f2cf1fedab2b10b8bb305 Mon Sep 17 00:00:00 2001 From: Jonathan Herman Date: Sat, 24 Mar 2012 17:45:12 -0400 Subject: containers: abstracted out common task-type code --- Makefile | 3 +- kernel-shark.c | 28 +++++ rt-graph.c | 141 +++++------------------ rt-graph.h | 27 +++-- rt-plot-cpu.c | 30 ++--- rt-plot-cpu.h | 2 + rt-plot-task.c | 338 ++++++++++++------------------------------------------ rt-plot-task.h | 4 + trace-graph.h | 2 + trace-plot-task.c | 2 +- 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 \ TRACE_CMD_OBJS = trace-cmd.o trace-record.o trace-read.o trace-split.o trace-listen.o \ trace-stack.o trace-options.o TRACE_VIEW_OBJS = trace-view.o trace-view-store.o -RT_GRAPH_OBJS = rt-graph.o rt-plot-task.o rt-plot-cpu.o +RT_GRAPH_OBJS = rt-graph.o rt-plot-task.o rt-plot-cpu.o rt-plot-container.o rt-plot.o \ + rt-plot-vcpu.o TRACE_GRAPH_OBJS = trace-graph.o trace-plot.o \ trace-plot-cpu.o trace-plot-task.o \ $(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) free(selected); } +/* Callback for the clicked signal of the plot real-time tasks button */ +static void +plot_containers_clicked (gpointer data) +{ + struct shark_info *info = data; + struct graph_info *ginfo = info->ginfo; + if (!ginfo->handle) + return; + + trace_container_dialog(ginfo, NULL); +} + static void show_all_rt_clicked (gpointer data) { @@ -2257,6 +2269,22 @@ void kernel_shark(int argc, char **argv) /* We do need to show menu items */ gtk_widget_show(sub_item); + /* --- Plot - RT CPUs Option --- */ + + sub_item = gtk_menu_item_new_with_label("Containers"); + + /* Add them to the menu */ + gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); + + /* We can attach the Quit menu item to our exit function */ + g_signal_connect_swapped (G_OBJECT (sub_item), "activate", + G_CALLBACK (plot_containers_clicked), + (gpointer) info); + + /* We do need to show menu items */ + gtk_widget_show(sub_item); + + /* --- Plot - RT CPUs Option --- */ sub_item = gtk_menu_item_new_with_label("Real-Time CPUs"); 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 @@ #include -#include #include "trace-graph.h" #include "trace-hash.h" @@ -14,16 +14,11 @@ #define dprintf(l, x...) do { if (0) printf(x); } while (0) #endif -static guint get_event_hash_key(gint eid) +static inline guint get_event_hash_key(gint eid) { return trace_hash(eid) % TS_HASH_SIZE; } -static int get_container_key(gint cid) -{ - return trace_hash(cid) % CONT_HASH_SIZE; -} - /* * Returns string value stored in @field. */ @@ -100,10 +95,10 @@ add_ts_hash(struct ts_list **events, gint eid, gint key, return field; } -/* +/** * Return container for @cid and @key, if present. */ -static struct cont_list* +struct cont_list* find_container(struct cont_list **conts, gint cid, gint key) { struct cont_list *list; @@ -126,11 +121,13 @@ add_container(struct cont_list **conts, gint cid, char *name) key = get_container_key(cid); list = find_container(conts, cid, key); + if (!list) { list = malloc_or_die(sizeof(*list)); list->cid = cid; list->name = name; list->vcpus = NULL; + list->plotted = FALSE; list->next = conts[key]; conts[key] = list; @@ -150,7 +147,7 @@ add_vcpu(struct cont_list **conts, { int key; struct cont_list *clist; - struct vcpu_list *vlist; + struct vcpu_list *vlist, *prev, *next; key = get_container_key(cid); clist = find_container(conts, cid, key); @@ -168,8 +165,24 @@ add_vcpu(struct cont_list **conts, vlist->params.wcet = wcet; vlist->params.period = period; - vlist->next = clist->vcpus; - clist->vcpus = vlist; + /* Insert in order */ + if (!clist->vcpus) { + vlist->next = clist->vcpus; + clist->vcpus = vlist; + } else { + prev = clist->vcpus; + for (next = prev->next; next; prev = next, next = prev->next) { + if (sid < next->sid) { + vlist->next = next; + prev->next = vlist; + break; + } + } + if (!next) { + vlist->next = NULL; + prev->next = vlist; + } + } return vlist; } @@ -520,7 +533,7 @@ int rt_graph_check_container_param(struct graph_info *ginfo, "litmus_container_param"); if (!event) goto out; - rtg_info->task_param_id = event->id; + rtg_info->container_param_id = event->id; dprintf(2, "Found container_param id %d\n", event->id); STORE_FIELD(rtg_info, event, cparam, cid); STORE_FIELD(rtg_info, event, cparam, name); @@ -562,7 +575,7 @@ int rt_graph_check_server_param(struct graph_info *ginfo, struct record *record, "litmus_server_param"); if (!event) goto out; - rtg_info->task_param_id = event->id; + rtg_info->server_param_id = event->id; dprintf(2, "Found server_param id %d\n", event->id); STORE_FIELD(rtg_info, event, sparam, cid); STORE_FIELD(rtg_info, event, sparam, sid); @@ -726,7 +739,8 @@ int rt_graph_check_server_release(struct graph_info *ginfo, */ int rt_graph_check_server_completion(struct graph_info *ginfo, struct record *record, - gint *sid, gint *job) + gint *sid, gint *job, + unsigned long long *ts) { struct rt_graph_info *rtg_info = &ginfo->rtg_info; struct pevent *pevent = ginfo->pevent; @@ -749,6 +763,7 @@ int rt_graph_check_server_completion(struct graph_info *ginfo, if (id == rtg_info->server_completion_id) { LOAD_INT(rtg_info, record, scompletion, sid, sid); LOAD_INT(rtg_info, record, scompletion, job, job); + *ts = get_rts(ginfo, record); dprintf(3, "Read server_completion(job(%d, %d))\n", *sid, *job); ret = 1; @@ -874,99 +889,3 @@ get_rts(struct graph_info *ginfo, struct record *record) ts = record->cached_rts; return ts; } - -/** - * next_rts - find a real-time timestamp AROUND an FTRACE time - * @ginfo: Current state of the graph - * @cpu: CPU to search - * @ft_target: FTRACE time to seek towards - * - * Returns the RT time of a record CLOSELY BEFORE @ft_time. - */ -unsigned long long -next_rts(struct graph_info *ginfo, int cpu, unsigned long long ft_target) -{ - struct record *record; - unsigned long long ts = 0ULL; - tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, ft_target); - record = tracecmd_read_data(ginfo->handle, cpu); - if (record) { - ts = get_rts(ginfo, record); - free_record(record); - return ts; - } else - return 0; -} - -/** - * set_cpu_to_rts - seek CPU to a time closely preceding a real-time timestamp - * @ginfo: Current state o the graph - * @cpu: The CPU to seek - * @rt_target: RT time to seek towards - * - * This seeks to a real-time timestamp, not the default ftrace timestamps. - * The @cpu seek location will be placed before the given time, but will - * not necessarily be placed _right_ before the time. - */ -void -set_cpu_to_rts(struct graph_info *ginfo, unsigned long long rt_target, int cpu) -{ - struct record *record; - unsigned long long last_rts, rts, seek_time, last_seek; - long long diff; - - rts = next_rts(ginfo, cpu, rt_target); - diff = rt_target - rts; - - /* "Guess" a new target based on difference */ - seek_time = rt_target + diff; - rts = next_rts(ginfo, cpu, seek_time); - diff = rt_target - rts; - - /* Zero in in 1.5x the difference increments */ - if (rts && diff > 0) { - /* rts rt_target | real-time time - * seek ? | trace-cmd time - * ---|---->>----|-------- - */ - do { - last_seek = seek_time; - last_rts = rts; - seek_time = seek_time + 1.5 * (rt_target - rts); - rts = next_rts(ginfo, cpu, seek_time); - } while (rts < rt_target && last_rts != rts); - tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, last_seek); - seek_time = last_seek; - } else if (rts && diff < 0) { - /* rt_target rts | real-time time - * ? seek | trace-cmd time - * ---|----<<----|-------- - */ - do { - seek_time = seek_time - 1.5 * (rts - rt_target); - rts = next_rts(ginfo, cpu, seek_time); - } while (rts > rt_target); - } - - /* Get to first record at or after time */ - while ((record = tracecmd_read_data(ginfo->handle, cpu))) { - if (get_rts(ginfo, record) >= rt_target) - break; - free_record(record); - } - if (record) { - tracecmd_set_cursor(ginfo->handle, cpu, record->offset); - free_record(record); - } else - tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, seek_time); -} - -/** - * set_cpus_to_time - seek all cpus to real-time @rt_target - */ -void set_cpus_to_rts(struct graph_info *ginfo, unsigned long long rt_target) -{ - int cpu; - for (cpu = 0; cpu < ginfo->cpus; cpu++) - set_cpu_to_rts(ginfo, rt_target, cpu); -} 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 @@ #include #include "task-list.h" #include "trace-cmd.h" +#include "rt-plot.h" #include "rt-plot-task.h" #include "rt-plot-cpu.h" +#include "rt-plot-container.h" #define LLABEL 30 #define SEARCH_PERIODS 3 @@ -102,6 +104,7 @@ struct rt_graph_info { unsigned long long max_period; }; + /* * A list of cached time-stamp fields */ @@ -134,6 +137,7 @@ struct vcpu_list { struct cont_list { struct cont_list *next; gint cid; + gboolean plotted; const char* name; struct vcpu_list *vcpus; }; @@ -173,7 +177,7 @@ int rt_graph_check_server_param(struct graph_info *ginfo, struct record *record, int rt_graph_check_server_switch_to(struct graph_info *ginfo, struct record *record, gint *sid, gint *job, gint *tid, - unsigned long long *when); + unsigned long long *when); int rt_graph_check_server_switch_away(struct graph_info *ginfo, struct record *record, gint *sid, gint *job, gint *tid, @@ -185,7 +189,8 @@ int rt_graph_check_server_release(struct graph_info *ginfo, unsigned long long *deadline); int rt_graph_check_server_completion(struct graph_info *ginfo, struct record *record, - gint *sid, gint *job); + gint *sid, gint *job, + unsigned long long *when); int rt_graph_check_server_block(struct graph_info *ginfo, struct record *record, gint *pid, unsigned long long *when); @@ -193,15 +198,12 @@ int rt_graph_check_server_resume(struct graph_info *ginfo, struct record *record gint *pid, unsigned long long *when); void init_rt_event_cache(struct rt_graph_info *rtinfo); -/* Methods for dealing with RT timestamps */ unsigned long long get_rts(struct graph_info *ginfo, struct record *record); -unsigned long long next_rts(struct graph_info *ginfo, int cpu, - unsigned long long ft_target); -void set_cpu_to_rts(struct graph_info *ginfo, - unsigned long long rt_target, int cpu); -void set_cpus_to_rts(struct graph_info *ginfo, - unsigned long long rt_target); + + +/* Other */ +struct cont_list* find_container(struct cont_list **conts, gint cid, gint key); static inline void nano_to_milli(unsigned long long time, unsigned long long *msec, @@ -216,4 +218,11 @@ static inline float nano_as_milli(unsigned long long time) return (float)time / 1000000ULL; } +static inline int get_container_key(gint cid) +{ + return trace_hash(cid) % CONT_HASH_SIZE; +} + +#define max_rt_search(ginfo) (SEARCH_PERIODS*ginfo->rtg_info.max_period) + #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 is_displayed(struct graph_info *ginfo, int eid) { struct rt_graph_info *rtg_info = &ginfo->rtg_info; - return !(eid == rtg_info->switch_away_id || - eid == rtg_info->switch_to_id || - eid == rtg_info->task_completion_id || - eid == rtg_info->task_block_id || - eid == rtg_info->task_resume_id || - eid == rtg_info->task_release_id || - eid == ginfo->event_sched_switch_id); + return (eid == rtg_info->switch_away_id || + eid == rtg_info->switch_to_id || + eid == rtg_info->task_completion_id || + eid == rtg_info->task_block_id || + eid == rtg_info->task_resume_id || + eid == rtg_info->task_release_id || + eid == ginfo->event_sched_switch_id); } static struct record* @@ -78,7 +78,7 @@ __find_record(struct graph_info *ginfo, int cpu, unsigned long long time, eid = pevent_data_type(ginfo->pevent, record); if (display) - ignored = !is_displayed(ginfo, eid); + ignored = is_displayed(ginfo, eid); if (get_rts(ginfo, record) >= time && !ignored) break; @@ -140,6 +140,7 @@ static int get_time_info(struct graph_info *ginfo, cpu = rtc_info->cpu; *out_pid = *out_job = is_running = 0; + /* TODO: inneficient */ *out_record = find_display_record(ginfo, cpu, time); record = find_record(ginfo, cpu, time); if (!record) @@ -330,8 +331,9 @@ static void rt_cpu_plot_start(struct graph_info *ginfo, struct graph_plot *plot, static int rt_cpu_plot_event(struct graph_info *ginfo, struct graph_plot *plot, struct record *record, struct plot_info *info) { - int pid, eid, match, dint; + int pid = 0, eid, match, dint; unsigned long long ts, dull; + char *dchar; struct rt_cpu_info *rtc_info = plot->private; if (!record) { @@ -348,18 +350,21 @@ static int rt_cpu_plot_event(struct graph_info *ginfo, struct graph_plot *plot, try_sched_switch(ginfo, rtc_info, record, info); if (!match) { - /* Have to call checks to ensure ids are loaded. Otherwise, + /* TODO: this should not be necessary! + * Have to call checks to ensure ids are loaded. Otherwise, * is_displayed will not work here or in any other methods. */ #define ARG ginfo,record, &pid rt_graph_check_task_param(ARG, &dull, &dull); + rt_graph_check_container_param(ARG, &dchar); + rt_graph_check_server_param(ARG, &dint, &dull, &dull); rt_graph_check_task_release(ARG, &dint, &dull, &dull); rt_graph_check_task_block(ARG, &dull); rt_graph_check_task_resume(ARG, &dull); rt_graph_check_any(ARG, &eid, &ts); #undef ARG - if (is_displayed(ginfo, eid)) { + if (!is_displayed(ginfo, eid)) { info->line = TRUE; info->lcolor = hash_pid(pid); info->ltime = ts; @@ -462,8 +467,7 @@ static void rt_cpu_plot_destroy(struct graph_info *ginfo, struct graph_plot *plo free(rtc_info); } - -static const struct plot_callbacks rt_cpu_cb = { +const struct plot_callbacks rt_cpu_cb = { .start = rt_cpu_plot_start, .destroy = rt_cpu_plot_destroy, .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 { char *label; }; +const struct plot_callbacks rt_cpu_cb; + void rt_plot_labeled_cpu(struct graph_info *ginfo, int cpu, char *label); void rt_plot_cpu(struct graph_info *ginfo, int cpu); 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 @@ #include "trace-graph.h" #include "trace-filter.h" -#define DEBUG_LEVEL 0 +#define DEBUG_LEVEL 4 #if DEBUG_LEVEL > 0 #define dprintf(l, x...) \ do { \ @@ -14,31 +14,6 @@ #define dprintf(l, x...) do { if (0) printf(x); } while (0) #endif -/* - * Return 1 if @record is relevant to @match_pid. - */ -static gboolean record_matches_pid(struct graph_info *ginfo, - struct record *record, - int match_pid) -{ - gint dint, pid = 0, match; - unsigned long long dull; - - /* Must use check_* in case record has not been found yet, - * this macro was the best of many terrible options. - */ -#define ARG ginfo, record, &pid - match = rt_graph_check_switch_to(ARG, &dint, &dull) || - rt_graph_check_switch_away(ARG, &dint, &dull) || - rt_graph_check_task_release(ARG, &dint, &dull, &dull) || - rt_graph_check_task_completion(ARG, &dint, &dull) || - rt_graph_check_task_block(ARG, &dull) || - rt_graph_check_task_resume(ARG, &dull) || - rt_graph_check_any(ARG, &dint, &dull); -#undef ARG - return pid == match_pid; -} - /* * Return the first record after @time (within a range) which draws a box. */ @@ -82,51 +57,6 @@ next_box_record(struct graph_info *ginfo, struct rt_task_info *rtt_info, return ret; } -/* - * Return first relevant record after @time. - * @display: If set, only considers records which aren't plotted - */ -static struct record* -__find_record(struct graph_info *ginfo, gint pid, guint64 time, int display) -{ - int next_cpu, match, eid, ignored; - struct record *record; - struct rt_graph_info *rtg_info = &ginfo->rtg_info; - - set_cpus_to_rts(ginfo, time); - while ((record = tracecmd_read_next_data(ginfo->handle, &next_cpu))) { - ignored = 0; - match = record_matches_pid(ginfo, record, pid); - if (display) { - eid = pevent_data_type(ginfo->pevent, record); - ignored = (eid == rtg_info->switch_away_id || - eid == rtg_info->switch_to_id || - eid == rtg_info->task_completion_id || - eid == rtg_info->task_block_id || - eid == rtg_info->task_resume_id || - eid == rtg_info->task_release_id); - } - ignored = ignored || eid == ginfo->event_sched_switch_id; - if (get_rts(ginfo, record) >= time && match && !ignored) - break; - free_record(record); - }; - - return record; -} - -static inline struct record* -find_record(struct graph_info *ginfo, gint pid, guint64 time) -{ - return __find_record(ginfo, pid, time, 0); -} - -static inline struct record* -find_display_record(struct graph_info *ginfo, gint pid, guint64 time) -{ - return __find_record(ginfo, pid, time, 1); -} - /* * Update current job in @rtt_info, ensuring monotonic increase. */ @@ -145,56 +75,6 @@ static int update_job(struct rt_task_info *rtt_info, int job) return 1; } - - -/* - * Find the information for the last release of @rtt_info on @cpu before @time. - * @min_ts: the minimum time stamp to parse - * - * Returns release record and @out_job, @out_release, and @out_deadline if a - * release was found after @mints matching @time. - */ -static struct record* -get_previous_release(struct graph_info *ginfo, struct rt_task_info *rtt_info, - int cpu, - unsigned long long min_ts, unsigned long long time, - int *out_job, - unsigned long long *out_release, - unsigned long long *out_deadline) -{ - int pid, job, match; - unsigned long long release, deadline; - struct record *last_record, *record, *ret = NULL; - - last_record = tracecmd_peek_data(ginfo->handle, cpu); - *out_job = *out_release = *out_deadline = 0; - if (!last_record) - return NULL; - last_record->ref_count++; - - while ((record = tracecmd_read_prev(ginfo->handle, last_record))) { - if (record->ts < min_ts) { - free_record(record); - goto out; - } - match = rt_graph_check_task_release(ginfo, record, &pid, &job, - &release, &deadline); - free_record(last_record); - last_record = record; - if (match && (pid == rtt_info->pid) && release <= time) { - ret = record; - last_record = NULL; - *out_job = job; - *out_release = release; - *out_deadline = deadline; - break; - } - }; - out: - free_record(last_record); - return ret; -} - /* * Get information about the given @time. * @out_job: Job number at this time @@ -215,15 +95,11 @@ static int get_time_info(struct graph_info *ginfo, struct record **out_record) { - int cpu, job; - unsigned long long release, deadline, min_ts; - struct record *record; - struct offset_cache *offsets; - struct rt_graph_info *rtg_info = &ginfo->rtg_info; + int job; /* Seek CPUs to first record after this time */ - *out_job = *out_release = *out_deadline = 0; - *out_record = find_record(ginfo, rtt_info->pid, time); + *out_record = find_rt_record(ginfo, + (struct rt_plot_common*)rtt_info, time); if (!*out_record) return 0; @@ -236,22 +112,8 @@ static int get_time_info(struct graph_info *ginfo, goto out; } - min_ts = time - SEARCH_PERIODS * rtg_info->max_period; - *out_job = *out_release = *out_deadline = 0; - - offsets = save_offsets(ginfo); - for (cpu = 0; cpu < ginfo->cpus; cpu++) { - record = get_previous_release(ginfo, rtt_info, cpu, min_ts, - time, &job, &release, &deadline); - if (record && record->ts > min_ts) { - *out_job = job; - *out_release = release; - *out_deadline = deadline; - min_ts = record->ts; - } - free_record(record); - } - restore_offsets(ginfo, offsets); + get_previous_release(ginfo, rtt_info->pid, time, + out_job, out_release, out_deadline); out: return 1; } @@ -537,9 +399,6 @@ static void rt_task_plot_start(struct graph_info *ginfo, struct graph_plot *plot dprintf(4,"%s\n", __FUNCTION__); - rtt_info->wcet = 0ULL; - rtt_info->period = 0ULL; - rtt_info->run_time = time; rtt_info->block_time = time; rtt_info->run_cpu = NO_CPU; @@ -548,7 +407,8 @@ static void rt_task_plot_start(struct graph_info *ginfo, struct graph_plot *plot rtt_info->fresh = TRUE; for (i = 0; i < 3; i++) rtt_info->first_rels[i] = 0ULL; - rtt_info->last_job = 0; + rtt_info->last_job = -1; + update_job(rtt_info, 0); } 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 free(rtt_info); } -static int rt_task_plot_display_last_event(struct graph_info *ginfo, - struct graph_plot *plot, - struct trace_seq *s, - unsigned long long time) +static int +rt_task_plot_record_matches(struct rt_plot_common *rt, + struct graph_info *ginfo, + struct record *record) + { - int eid; - struct event_format *event; - struct record *record; - struct offset_cache *offsets; - struct rt_task_info *rtt_info = plot->private; + struct rt_task_info *rtt_info = (struct rt_task_info*)rt; + gint dint, pid = 0, match, match_pid; + unsigned long long dull; - dprintf(4,"%s\n", __FUNCTION__); + match_pid = rtt_info->pid; - offsets = save_offsets(ginfo); - record = find_display_record(ginfo, rtt_info->pid, time); - restore_offsets(ginfo, offsets); - if (!record) - return 0; + /* Must use check_* in case record has not been found yet, + * this macro was the best of many terrible options. + */ +#define ARG ginfo, record, &pid + match = rt_graph_check_switch_to(ARG, &dint, &dull) || + rt_graph_check_switch_away(ARG, &dint, &dull) || + rt_graph_check_task_release(ARG, &dint, &dull, &dull) || + rt_graph_check_task_completion(ARG, &dint, &dull) || + rt_graph_check_task_block(ARG, &dull) || + rt_graph_check_task_resume(ARG, &dull) || + rt_graph_check_any(ARG, &dint, &dull); +#undef ARG + return pid == match_pid; +} - eid = pevent_data_type(ginfo->pevent, record); - event = pevent_data_event_from_type(ginfo->pevent, eid); - if (event) - trace_seq_puts(s, event->name); - else - trace_seq_printf(s, "UNKNOWN EVENT %d\n", eid); - trace_seq_putc(s, '\n'); - trace_seq_printf(s, "CPU %d\n", record->cpu); - free_record(record); - return 1; +static int rt_task_plot_is_drawn(struct graph_info *ginfo, int eid) +{ + struct rt_graph_info *rtg_info = &ginfo->rtg_info; + + return (eid == rtg_info->switch_away_id || + eid == rtg_info->switch_to_id || + eid == rtg_info->task_completion_id || + eid == rtg_info->task_block_id || + eid == rtg_info->task_resume_id || + eid == rtg_info->task_release_id); } -static int rt_task_plot_display_info(struct graph_info *ginfo, - struct graph_plot *plot, - struct trace_seq *s, - unsigned long long time) +static struct record* +rt_task_plot_write_header(struct rt_plot_common *rt, + struct graph_info *ginfo, + struct trace_seq *s, + unsigned long long time) { const char *comm; - int pid, job, eid; + int pid, job, found; struct record *record; - struct event_format *event; - unsigned long long msec, nsec; - unsigned long long release, deadline, rts; - struct rt_task_info *rtt_info = plot->private; - struct offset_cache *offsets; + unsigned long long release, deadline; + struct rt_task_info *rtt_info = (struct rt_task_info*)rt; dprintf(4,"%s\n", __FUNCTION__); - offsets = save_offsets(ginfo); - get_time_info(ginfo, rtt_info, time, - &job, &release, &deadline, &record); - restore_offsets(ginfo, offsets); + found = get_time_info(ginfo, rtt_info, time, + &job, &release, &deadline, &record); + if (!found) + goto out; pid = rtt_info->pid; comm = pevent_data_comm_from_pid(ginfo->pevent, pid); trace_seq_printf(s, "%s-%d:%d\n", comm, pid, job); - if (record) { - rts = get_rts(ginfo, record); - eid = pevent_data_type(ginfo->pevent, record); - - if (in_res(ginfo, deadline, time)) { - trace_seq_printf(s, "\nlitmus_deadline\n" - "deadline(job(%d,%d)): %llu\n", - pid, job, deadline); - } - if (in_res(ginfo, release, time)) { - trace_seq_printf(s, "\nlitmus_release\n" - "release(job(%d,%d)): %llu\n", - pid, job, release); - } - - if (in_res(ginfo, rts, time)) { - event = pevent_data_event_from_type(ginfo->pevent, eid); - if (event) { - trace_seq_putc(s, '\n'); - trace_seq_puts(s, event->name); - trace_seq_putc(s, '\n'); - pevent_event_info(s, event, record); - } else - trace_seq_printf(s, "\nUNKNOWN EVENT %d\n", eid); - } - trace_seq_putc(s, '\n'); - nano_to_milli(time, &msec, &nsec); - trace_seq_printf(s, "%llu.%06llu ms CPU: %03d", - msec, nsec, record->cpu); - free_record(record); + if (in_res(ginfo, deadline, time)) { + trace_seq_printf(s, "\nlitmus_deadline\n" + "deadline(job(%d,%d)): %llu\n", + pid, job, deadline); } - - return 1; -} - -static int rt_task_plot_match_time(struct graph_info *ginfo, - struct graph_plot *plot, - unsigned long long time) -{ - struct record *record = NULL; - struct rt_task_info *rtt_info = plot->private; - int next_cpu, match, ret; - - dprintf(4,"%s\n", __FUNCTION__); - - set_cpus_to_rts(ginfo, time); - - do { - free_record(record); - record = tracecmd_read_next_data(ginfo->handle, &next_cpu); - if (!record) - return 0; - match = record_matches_pid(ginfo, record, rtt_info->pid); - } while ((!match && get_rts(ginfo, record) < time + 1) || - (match && get_rts(ginfo, record) < time)); - - if (record && get_rts(ginfo, record) == time) - ret = 1; - free_record(record); - - return ret; -} - -static struct record * -rt_task_plot_find_record(struct graph_info *ginfo, struct graph_plot *plot, - unsigned long long time) -{ - struct rt_task_info *rtt_info = plot->private; - return find_record(ginfo, rtt_info->pid, time); + if (in_res(ginfo, release, time)) { + trace_seq_printf(s, "\nlitmus_release\n" + "release(job(%d,%d)): %llu\n", + pid, job, release); + } + out: + return record; } - -static const struct plot_callbacks rt_task_cb = { +const struct plot_callbacks rt_task_cb = { .start = rt_task_plot_start, .destroy = rt_task_plot_destroy, .plot_event = rt_task_plot_event, - .display_last_event = rt_task_plot_display_last_event, - .display_info = rt_task_plot_display_info, - .match_time = rt_task_plot_match_time, - .find_record = rt_task_plot_find_record, + .display_last_event = rt_plot_display_last_event, + .display_info = rt_plot_display_info, + .match_time = rt_plot_match_time, + .find_record = rt_plot_find_record, }; void rt_plot_task_update_callback(gboolean accept, @@ -806,6 +614,12 @@ void rt_plot_task(struct graph_info *ginfo, int pid, int pos) rtt_info = malloc_or_die(sizeof(*rtt_info)); rtt_info->pid = pid; rtt_info->label = malloc_or_die(LLABEL); + rtt_info->wcet = params->wcet; + rtt_info->period = params->period; + + rtt_info->common.record_matches = rt_task_plot_record_matches; + rtt_info->common.is_drawn = rt_task_plot_is_drawn; + rtt_info->common.write_header = rt_task_plot_write_header; ms_wcet = nano_as_milli(params->wcet); ms_period = nano_as_milli(params->period); @@ -825,7 +639,7 @@ void rt_plot_task(struct graph_info *ginfo, int pid, int pos) } void rt_plot_add_all_tasks(struct graph_info *ginfo) -{ + { gint *tasks; int i; 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 @@ #include "trace-plot-task.h" struct rt_task_info { + struct rt_plot_common common; + int pid; unsigned long long wcet; unsigned long long period; @@ -25,6 +27,8 @@ struct rt_task_info { char *label; }; +const struct plot_callbacks rt_task_cb; + void rt_plot_task(struct graph_info *ginfo, int pid, int pos); void rt_plot_tasks_plotted(struct graph_info *ginfo, gint **plotted); 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 { PLOT_TYPE_TASK, PLOT_TYPE_RT_TASK, PLOT_TYPE_RT_CPU, + PLOT_TYPE_SERVER_TASK, + PLOT_TYPE_SERVER_CPU }; 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) free(task_info); } -static const struct plot_callbacks task_plot_cb = { +const struct plot_callbacks task_plot_cb = { .match_time = task_plot_match_time, .plot_event = task_plot_event, .start = task_plot_start, -- cgit v1.2.2