diff options
| author | Jonathan <hermanjl@hermanjl-Aspire-5553G.(none)> | 2012-03-05 18:00:39 -0500 |
|---|---|---|
| committer | Jonathan <hermanjl@hermanjl-Aspire-5553G.(none)> | 2012-03-05 18:00:39 -0500 |
| commit | 61266395ff4f371933c104cff6671aae7f43c3fd (patch) | |
| tree | 4e0c1bf15015a80a57db728c5857005234481f4b | |
| parent | 8bcd73ddae5d74fb9b2b8aaedd3aa6a39ef3f75d (diff) | |
rt-graph: real-time tasks can be added / removed from the graph
Currently they copy the functionality of regular task.
| -rw-r--r-- | Documentation/structure.txt | 225 | ||||
| -rw-r--r-- | kernel-shark.c | 15 | ||||
| -rw-r--r-- | rt-graph.h | 11 | ||||
| -rw-r--r-- | rt-plot-task.c | 54 | ||||
| -rw-r--r-- | rt-plot-task.h | 22 | ||||
| -rw-r--r-- | task-list.c | 99 | ||||
| -rw-r--r-- | task-list.h | 20 | ||||
| -rw-r--r-- | trace-graph.c | 7 | ||||
| -rw-r--r-- | trace-graph.h | 29 | ||||
| -rw-r--r-- | trace-plot-cpu.c | 16 | ||||
| -rw-r--r-- | trace-plot-task.c | 148 | ||||
| -rw-r--r-- | trace-plot-task.h | 118 |
12 files changed, 635 insertions, 129 deletions
diff --git a/Documentation/structure.txt b/Documentation/structure.txt new file mode 100644 index 0000000..adee54d --- /dev/null +++ b/Documentation/structure.txt | |||
| @@ -0,0 +1,225 @@ | |||
| 1 | |||
| 2 | Can't do this until cpus set up! | ||
| 3 | |||
| 4 | 0. Load all events w/ proper stuff | ||
| 5 | |||
| 6 | 1. Create list of rt_tasks | ||
| 7 | 2. Create seperate dailog for rt tasks w/ a callback. | ||
| 8 | 3. Allow dialog to be filtered. | ||
| 9 | 4. Create dummy task thing that just says hi. | ||
| 10 | 5. Make it print out when it reads stuff. | ||
| 11 | 6. Draw shit | ||
| 12 | 7. Draw new shit. | ||
| 13 | |||
| 14 | |||
| 15 | struct trace-graph.h { | ||
| 16 | /* - header file for generic graphers */ | ||
| 17 | |||
| 18 | /* - What is returned for drawing */ | ||
| 19 | /* struct plot_info; */ | ||
| 20 | |||
| 21 | /* - what you can customize */ | ||
| 22 | /* struct plot_callbacks; */ | ||
| 23 | /* - customized in trace-*-plot.c */ | ||
| 24 | |||
| 25 | /* - one of these per trace-*-plot instantiation */ | ||
| 26 | /* struct graph_plot; */ | ||
| 27 | /* void* private is per trace-*-plot */ | ||
| 28 | /* *cb (callbacks) is the callbacks */ | ||
| 29 | |||
| 30 | |||
| 31 | /* struct graph_callbacks; */ | ||
| 32 | /* struct plot_list; */ | ||
| 33 | /* struct plot_hash; */ | ||
| 34 | |||
| 35 | /* /\* Current state of the displayed graph AS A WHOLE *\/ */ | ||
| 36 | struct graph_info { | ||
| 37 | handle; /* input handle */ | ||
| 38 | }; | ||
| 39 | |||
| 40 | /* - create with trace_graph_plot_insert */ | ||
| 41 | |||
| 42 | }; | ||
| 43 | |||
| 44 | struct parse-events.h { | ||
| 45 | /* Can write shit into it person by person */ | ||
| 46 | struct trace_seq; | ||
| 47 | }; | ||
| 48 | |||
| 49 | struct unknown { | ||
| 50 | |||
| 51 | }; | ||
| 52 | |||
| 53 | struct trace-graph.c { | ||
| 54 | |||
| 55 | }; | ||
| 56 | |||
| 57 | /* trace-graph.c */ | ||
| 58 | |||
| 59 | |||
| 60 | |||
| 61 | struct trace-plot-task.c { | ||
| 62 | |||
| 63 | /*** PRIVATE DATA ***/ | ||
| 64 | |||
| 65 | /* Private to each task plot */ | ||
| 66 | struct task_plot_info { | ||
| 67 | pid /* per task */ | ||
| 68 | /* Other current things, lotta last whatevs */ | ||
| 69 | } | ||
| 70 | |||
| 71 | /*** PRIVATE METHODS ****/ | ||
| 72 | |||
| 73 | /* Return true if the record (which is for this task) is a sched_switch | ||
| 74 | * and the data held is the previous state?? */ | ||
| 75 | is_running(ginfo, record); | ||
| 76 | |||
| 77 | /* Return true if the record is: | ||
| 78 | * a sched_switch to our pid or from our pid, is_sched = TRUE | ||
| 79 | * a wakeup, if we are waking up, wakeup = TRUE | ||
| 80 | * from our pid, all fALSE | ||
| 81 | */ | ||
| 82 | record_matches_pid(ginfo, record, match_pid, &pid, &sched_pid, &is_sched, &wakeup); | ||
| 83 | |||
| 84 | |||
| 85 | /* Sets cpu to given time. Read till that time is passed, freeing everytning | ||
| 86 | * on the way. | ||
| 87 | * If we reach a record at or past our time, set cursor to that time. | ||
| 88 | */ | ||
| 89 | set_cpu_to_time(cpu, ginfo, time); | ||
| 90 | |||
| 91 | /* Call above on all cpus */ | ||
| 92 | set_cpus_to_time(ginfo, time); | ||
| 93 | |||
| 94 | /* Return struct w/ array holding current record offset at each cpu */ | ||
| 95 | save_offsets(ginfo); | ||
| 96 | |||
| 97 | /* Set cursor to each offset, if present. Otherwise, put at end */ | ||
| 98 | restore_offsets(ginfo, offsets); | ||
| 99 | |||
| 100 | /* Return first record after time which is from our pid */ | ||
| 101 | find_record(ginfo, pid, time); | ||
| 102 | |||
| 103 | /* Updates last_whatevers in task info */ | ||
| 104 | update_last_record(ginfo, task_plot_info, record); | ||
| 105 | |||
| 106 | /* Reads backwards until it finds a matching record */ | ||
| 107 | find_previous_record(ginfo, start_record, pid, cpu); | ||
| 108 | |||
| 109 | get_display_record(ginfo, pid, time); | ||
| 110 | |||
| 111 | /**** PUBLIC METHODS *****/ | ||
| 112 | |||
| 113 | /* Basically reset as though you just started reading */ | ||
| 114 | task_plot_start(ginfo, plot, time); | ||
| 115 | |||
| 116 | /* Load the next record for me at or after that time */ | ||
| 117 | task_plot_match_time(ginfo, plot, time); | ||
| 118 | |||
| 119 | /* Get record at time, print info */ | ||
| 120 | task_plot_display_last_event(info, plot, trace_seq s, time); | ||
| 121 | |||
| 122 | /* Always draws a line of the color of the pid. Always. | ||
| 123 | * Then update_last_record. | ||
| 124 | * If record is null, times up, just finish our shit and return. | ||
| 125 | * If was running, and now wakeup, that means another task woke up | ||
| 126 | * We need to end our gd box. If it was us waking up,no box. | ||
| 127 | * return. | ||
| 128 | * If a match | ||
| 129 | * If a new cpu, see if we switched cpu. if so, create a box w/ | ||
| 130 | * proper color for LAST cpu, end it here. | ||
| 131 | * If scheduled, but we weren't currently running, we are now. | ||
| 132 | * Update the last bullshit. If we had a wake time, that means | ||
| 133 | * our wakeup turned into a run. Draw an empty box where we were | ||
| 134 | * awake but not running. Otherwise, reset wake time. | ||
| 135 | * Else if we haven't created a new box, (ie switched cpus), we got | ||
| 136 | * switched out. Create a goddamn box. | ||
| 137 | * Return | ||
| 138 | * If no previous last_records on this cpu, put this record there. | ||
| 139 | * If there was a last cpu, but no match, somehow we aren't running. | ||
| 140 | * Finish the box. | ||
| 141 | */ | ||
| 142 | task_plot_event(ginfo, plot,r ecord, info); | ||
| 143 | |||
| 144 | /* Just frontend for find_record */ | ||
| 145 | task_plot_find_record(ginfo, plot, time); | ||
| 146 | |||
| 147 | /* Print out event info if in current resolution */ | ||
| 148 | task_plot_display_info(ginfo, plot, sequence s, time); | ||
| 149 | |||
| 150 | /* Free private info */ | ||
| 151 | task_plot_destroy(info, plot); | ||
| 152 | |||
| 153 | |||
| 154 | /*** STATIC METHODS ***/ | ||
| 155 | |||
| 156 | /* Return what tasks are plotted */ | ||
| 157 | void graph_plot_task_plotted(ginfo, **plotted); | ||
| 158 | |||
| 159 | /* Called when task is clicked or removed */ | ||
| 160 | graph_plot_task_update_callback(accept, selected, non_selct, data); | ||
| 161 | |||
| 162 | /* Create a plot for a single task, insert into plot */ | ||
| 163 | graph_plot_task(ginfo, pid, pos); | ||
| 164 | |||
| 165 | }; | ||
| 166 | |||
| 167 | struct trace-plot-cpu.c{ | ||
| 168 | /*** DATA ***/ | ||
| 169 | struct cpu_plot_info { | ||
| 170 | cpu, last_time, last_pid, *last_record; | ||
| 171 | }; | ||
| 172 | |||
| 173 | /*** PRIVATE ***/ | ||
| 174 | /* Hashes for pid value, but if idle (aka 0), returns black) */ | ||
| 175 | hash_pid(val); | ||
| 176 | |||
| 177 | /* Sets cpu near time, reads until time is passed, returns last record */ | ||
| 178 | get_record_from_time(ginfo, cpu, time); | ||
| 179 | |||
| 180 | /* Return 1 if the record should be skipped */ | ||
| 181 | filter_record(ginfo, record, &orig_pid, &sched_pid, &sched_switch); | ||
| 182 | |||
| 183 | /* Update last_pid, last_record, and last_time */ | ||
| 184 | update_last_record(ginfo, cpu_info, record); | ||
| 185 | |||
| 186 | /* Uh eh hrm? */ | ||
| 187 | find_record_on_cpu(ginfo, cpu, time); | ||
| 188 | |||
| 189 | |||
| 190 | /*** PUBLIC ***/ | ||
| 191 | /* Gets record around time. Return 1 if exact match */ | ||
| 192 | cpu_plot_match_time(ginfo, plot, time); | ||
| 193 | |||
| 194 | /* Find first non-filtered event after time, write out info into s */ | ||
| 195 | cpu_plot_display_last_event(ginfo, plot, sequence s, time); | ||
| 196 | |||
| 197 | /* Prepare for liftoff ! */ | ||
| 198 | cpu_plot_start(ginfo, plot, time); | ||
| 199 | |||
| 200 | /* Generate stuff as needed */ | ||
| 201 | cpu_plot_event(ginfo, plot, record, info); | ||
| 202 | |||
| 203 | /* Call find record to get a record in this time */ | ||
| 204 | cpu_plot_find_record(ginfo, plot, time); | ||
| 205 | |||
| 206 | /* Write out info for record at or before time */ | ||
| 207 | cpu_plot_display_info(gino, plot, s, time); | ||
| 208 | |||
| 209 | /* You get it */ | ||
| 210 | cpu_plot_destroy(ginfo, plot); | ||
| 211 | |||
| 212 | /*** STATIC ***/ | ||
| 213 | /* Create cpu plot, add to trace graph */ | ||
| 214 | add_cpu_plot(ginfo, cpu); | ||
| 215 | |||
| 216 | /* Return cpus plotted in cpu_mask */ | ||
| 217 | graph_plot_cpus_plotted(ginfo, *all_cpus, **cpu_mask); | ||
| 218 | |||
| 219 | /* Remove unselected plots, add selected plots */ | ||
| 220 | graph_plot_cpus_update_callback(accept, all_cpus, selected_cpu_mast, data); | ||
| 221 | |||
| 222 | /* Automatigically add all cpus */ | ||
| 223 | graph_plot_init_cpus(); | ||
| 224 | |||
| 225 | } | ||
diff --git a/kernel-shark.c b/kernel-shark.c index e0c123a..b24e3b6 100644 --- a/kernel-shark.c +++ b/kernel-shark.c | |||
| @@ -150,17 +150,6 @@ static void update_tree_view_filters(struct shark_info *info, | |||
| 150 | 150 | ||
| 151 | /* graph callbacks */ | 151 | /* graph callbacks */ |
| 152 | 152 | ||
| 153 | /* convert_nano() and print_time() are copied from trace-graph.c for debugging | ||
| 154 | purposes, and should be deleted when this is complete (or merged with | ||
| 155 | trace-graph.c */ | ||
| 156 | |||
| 157 | static void convert_nano(unsigned long long time, unsigned long *sec, | ||
| 158 | unsigned long *usec) | ||
| 159 | { | ||
| 160 | *sec = time / 1000000000ULL; | ||
| 161 | *usec = (time / 1000) % 1000000; | ||
| 162 | } | ||
| 163 | |||
| 164 | static void print_time(unsigned long long time) | 153 | static void print_time(unsigned long long time) |
| 165 | { | 154 | { |
| 166 | unsigned long sec, usec; | 155 | unsigned long sec, usec; |
| @@ -1292,10 +1281,10 @@ plot_rt_tasks_clicked (gpointer data) | |||
| 1292 | 1281 | ||
| 1293 | rtinfo = &ginfo->rtinfo; | 1282 | rtinfo = &ginfo->rtinfo; |
| 1294 | tasks = task_list_pids(rtinfo->tasks); | 1283 | tasks = task_list_pids(rtinfo->tasks); |
| 1295 | rt_plot_task_plotted(rtinfo, &selected); | 1284 | rt_plot_task_plotted(ginfo, &selected); |
| 1296 | 1285 | ||
| 1297 | trace_task_dialog(ginfo->handle, tasks, selected, | 1286 | trace_task_dialog(ginfo->handle, tasks, selected, |
| 1298 | rt_plot_task_update_callback, rtinfo); | 1287 | rt_plot_task_update_callback, ginfo); |
| 1299 | free(tasks); | 1288 | free(tasks); |
| 1300 | free(selected); | 1289 | free(selected); |
| 1301 | } | 1290 | } |
| @@ -2,8 +2,9 @@ | |||
| 2 | #define _RT_GRAPH_H | 2 | #define _RT_GRAPH_H |
| 3 | 3 | ||
| 4 | #include <gtk/gtk.h> | 4 | #include <gtk/gtk.h> |
| 5 | #include "trace-cmd.h" | ||
| 6 | #include "task-list.h" | 5 | #include "task-list.h" |
| 6 | #include "trace-cmd.h" | ||
| 7 | #include "rt-plot-task.h" | ||
| 7 | 8 | ||
| 8 | struct rt_graph_info { | 9 | struct rt_graph_info { |
| 9 | 10 | ||
| @@ -59,12 +60,4 @@ int rt_graph_check_task_resume(struct rt_graph_info *rtinfo, struct pevent *peve | |||
| 59 | unsigned long long *when); | 60 | unsigned long long *when); |
| 60 | void init_rt_event_cache(struct rt_graph_info *rtinfo); | 61 | void init_rt_event_cache(struct rt_graph_info *rtinfo); |
| 61 | 62 | ||
| 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 | |||
| 70 | #endif | 63 | #endif |
diff --git a/rt-plot-task.c b/rt-plot-task.c new file mode 100644 index 0000000..d63c872 --- /dev/null +++ b/rt-plot-task.c | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | #include "trace-graph.h" | ||
| 2 | |||
| 3 | static const struct plot_callbacks rt_task_cb = { | ||
| 4 | .match_time = task_plot_match_time, | ||
| 5 | .plot_event = task_plot_event, | ||
| 6 | .start = task_plot_start, | ||
| 7 | .display_last_event = task_plot_display_last_event, | ||
| 8 | .find_record = task_plot_find_record, | ||
| 9 | .display_info = task_plot_display_info, | ||
| 10 | .destroy = task_plot_destroy | ||
| 11 | }; | ||
| 12 | |||
| 13 | void rt_plot_task_update_callback(gboolean accept, | ||
| 14 | gint *selected, | ||
| 15 | gint *non_select, | ||
| 16 | gpointer data) | ||
| 17 | { | ||
| 18 | graph_tasks_update_callback(TASK_PLOT_RT, rt_plot_task, | ||
| 19 | accept, selected, non_select, data); | ||
| 20 | } | ||
| 21 | |||
| 22 | void rt_plot_task_plotted(struct graph_info *ginfo, gint **plotted) | ||
| 23 | { | ||
| 24 | graph_tasks_plotted(ginfo, TASK_PLOT_RT, plotted); | ||
| 25 | } | ||
| 26 | |||
| 27 | void rt_plot_task(struct graph_info *ginfo, int pid, int pos) | ||
| 28 | { | ||
| 29 | struct rt_graph_info *rtinfo = &ginfo->rtinfo; | ||
| 30 | struct rt_task_info *rt_task; | ||
| 31 | struct graph_plot *plot; | ||
| 32 | const char *comm; | ||
| 33 | char *label; | ||
| 34 | int len; | ||
| 35 | |||
| 36 | if (!find_task_list(rtinfo->tasks, pid)) | ||
| 37 | die("Cannot create RT plot of non-RT task %d!\n", pid); | ||
| 38 | |||
| 39 | rt_task = malloc_or_die(sizeof(*rt_task)); | ||
| 40 | |||
| 41 | init_task_plot_info(ginfo, &rt_task->base, TASK_PLOT_RT, pid); | ||
| 42 | |||
| 43 | comm = pevent_data_comm_from_pid(ginfo->pevent, pid); | ||
| 44 | len = strlen(comm) + 100; | ||
| 45 | label = malloc_or_die(len); | ||
| 46 | snprintf(label, len, "*%s-%d", comm, pid); | ||
| 47 | |||
| 48 | plot = trace_graph_plot_insert(ginfo, pos, label, PLOT_TYPE_TASK, | ||
| 49 | &rt_task_cb, rt_task); | ||
| 50 | free(label); | ||
| 51 | |||
| 52 | trace_graph_plot_add_all_recs(ginfo, plot); | ||
| 53 | } | ||
| 54 | |||
diff --git a/rt-plot-task.h b/rt-plot-task.h new file mode 100644 index 0000000..4cb957a --- /dev/null +++ b/rt-plot-task.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | #ifndef __RT_PLOT_TASK_H | ||
| 2 | #define __RT_PLOT_TASK_H | ||
| 3 | |||
| 4 | #include "trace-plot-task.h" | ||
| 5 | |||
| 6 | struct rt_task_info { | ||
| 7 | struct task_plot_info base; | ||
| 8 | unsigned long long wcet; | ||
| 9 | unsigned long long period; | ||
| 10 | unsigned long long block_time; | ||
| 11 | int last_job; | ||
| 12 | }; | ||
| 13 | |||
| 14 | void rt_plot_task(struct graph_info *ginfo, int pid, int pos); | ||
| 15 | void rt_plot_task_plotted(struct graph_info *ginfo, | ||
| 16 | gint **plotted); | ||
| 17 | void rt_plot_task_update_callback(gboolean accept, | ||
| 18 | gint *selected, | ||
| 19 | gint *non_select, | ||
| 20 | gpointer data); | ||
| 21 | |||
| 22 | #endif | ||
diff --git a/task-list.c b/task-list.c new file mode 100644 index 0000000..4c820bf --- /dev/null +++ b/task-list.c | |||
| @@ -0,0 +1,99 @@ | |||
| 1 | #include "task-list.h" | ||
| 2 | |||
| 3 | static guint get_task_hash_key(gint pid) | ||
| 4 | { | ||
| 5 | return trace_hash(pid) % TASK_HASH_SIZE; | ||
| 6 | } | ||
| 7 | |||
| 8 | struct task_list *find_task_hash(struct task_list **tasks, | ||
| 9 | gint key, gint pid) | ||
| 10 | { | ||
| 11 | struct task_list *list; | ||
| 12 | |||
| 13 | for (list = tasks[key]; list; list = list->next) { | ||
| 14 | if (list->pid == pid) | ||
| 15 | return list; | ||
| 16 | } | ||
| 17 | |||
| 18 | return NULL; | ||
| 19 | } | ||
| 20 | |||
| 21 | /** | ||
| 22 | * find_task_list - return task_list node for pid, or NULL if not present | ||
| 23 | */ | ||
| 24 | struct task_list *find_task_list(struct task_list **tasks, gint pid) | ||
| 25 | { | ||
| 26 | guint key = get_task_hash_key(pid); | ||
| 27 | return find_task_hash(tasks, key, pid); | ||
| 28 | } | ||
| 29 | |||
| 30 | /** | ||
| 31 | * add_task_hash - add pid to a task_list | ||
| 32 | * @tasks: The head of the task_list | ||
| 33 | * @pid: The pid to add | ||
| 34 | * | ||
| 35 | * Return the list entry of the added task | ||
| 36 | */ | ||
| 37 | struct task_list *add_task_hash(struct task_list **tasks, int pid) | ||
| 38 | { | ||
| 39 | struct task_list *list; | ||
| 40 | guint key = get_task_hash_key(pid); | ||
| 41 | |||
| 42 | list = find_task_hash(tasks, key, pid); | ||
| 43 | if (list) | ||
| 44 | return list; | ||
| 45 | |||
| 46 | list = malloc_or_die(sizeof(*list)); | ||
| 47 | list->pid = pid; | ||
| 48 | list->next = tasks[key]; | ||
| 49 | tasks[key] = list; | ||
| 50 | |||
| 51 | return list; | ||
| 52 | } | ||
| 53 | |||
| 54 | /** | ||
| 55 | * free_task_hash - free all nodes in a task_list | ||
| 56 | */ | ||
| 57 | void free_task_hash(struct task_list **tasks) | ||
| 58 | { | ||
| 59 | struct task_list *list; | ||
| 60 | int i; | ||
| 61 | |||
| 62 | for (i = 0; i < TASK_HASH_SIZE; i++) { | ||
| 63 | while (tasks[i]) { | ||
| 64 | list = tasks[i]; | ||
| 65 | tasks[i] = list->next; | ||
| 66 | free(list); | ||
| 67 | } | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | /** | ||
| 72 | * task_list_pids - return an allocated list of all found tasks | ||
| 73 | * @ginfo: The graph info structure | ||
| 74 | * | ||
| 75 | * Returns an allocated list of pids found in the graph, ending | ||
| 76 | * with a -1. This array must be freed with free(). | ||
| 77 | */ | ||
| 78 | gint *task_list_pids(struct task_list **tasks) | ||
| 79 | { | ||
| 80 | struct task_list *list; | ||
| 81 | gint *pids; | ||
| 82 | gint count = 0; | ||
| 83 | gint i; | ||
| 84 | |||
| 85 | for (i = 0; i < TASK_HASH_SIZE; i++) { | ||
| 86 | list = tasks[i]; | ||
| 87 | while (list) { | ||
| 88 | if (count) | ||
| 89 | pids = realloc(pids, sizeof(*pids) * (count + 2)); | ||
| 90 | else | ||
| 91 | pids = malloc(sizeof(*pids) * 2); | ||
| 92 | pids[count++] = list->pid; | ||
| 93 | pids[count] = -1; | ||
| 94 | list = list->next; | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | return pids; | ||
| 99 | } | ||
diff --git a/task-list.h b/task-list.h new file mode 100644 index 0000000..eb1213b --- /dev/null +++ b/task-list.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | #ifndef __TASK_LIST_H | ||
| 2 | #define __TASK_LIST_H | ||
| 3 | |||
| 4 | #include <gtk/gtk.h> | ||
| 5 | #include "trace-cmd.h" | ||
| 6 | #include "trace-hash.h" | ||
| 7 | |||
| 8 | #define TASK_HASH_SIZE 1024 | ||
| 9 | |||
| 10 | struct task_list { | ||
| 11 | struct task_list *next; | ||
| 12 | gint pid; | ||
| 13 | }; | ||
| 14 | |||
| 15 | struct task_list* find_task_list(struct task_list **tasks, int pid); | ||
| 16 | struct task_list* add_task_hash(struct task_list **tasks, int pid); | ||
| 17 | void free_task_hash(struct task_list **tasks); | ||
| 18 | gint* task_list_pids(struct task_list **tasks); | ||
| 19 | |||
| 20 | #endif | ||
diff --git a/trace-graph.c b/trace-graph.c index 819482e..2cf7a95 100644 --- a/trace-graph.c +++ b/trace-graph.c | |||
| @@ -70,13 +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 | static void convert_nano(unsigned long long time, unsigned long *sec, | ||
| 74 | unsigned long *usec) | ||
| 75 | { | ||
| 76 | *sec = time / 1000000000ULL; | ||
| 77 | *usec = (time / 1000) % 1000000; | ||
| 78 | } | ||
| 79 | |||
| 80 | static int convert_time_to_x(struct graph_info *ginfo, guint64 time) | 73 | static int convert_time_to_x(struct graph_info *ginfo, guint64 time) |
| 81 | { | 74 | { |
| 82 | if (time < ginfo->view_start_time) | 75 | if (time < ginfo->view_start_time) |
diff --git a/trace-graph.h b/trace-graph.h index 92d9883..a0c5c54 100644 --- a/trace-graph.h +++ b/trace-graph.h | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include "trace-xml.h" | 27 | #include "trace-xml.h" |
| 28 | #include "task-list.h" | 28 | #include "task-list.h" |
| 29 | #include "rt-graph.h" | 29 | #include "rt-graph.h" |
| 30 | #include "trace-plot-task.h" | ||
| 30 | 31 | ||
| 31 | struct graph_info; | 32 | struct graph_info; |
| 32 | 33 | ||
| @@ -389,14 +390,26 @@ void graph_plot_cpus_update_callback(gboolean accept, | |||
| 389 | guint64 *selected_cpu_mask, | 390 | guint64 *selected_cpu_mask, |
| 390 | gpointer data); | 391 | gpointer data); |
| 391 | 392 | ||
| 392 | /* task plot */ | 393 | static inline void convert_nano(unsigned long long time, unsigned long *sec, |
| 393 | void graph_plot_task(struct graph_info *ginfo, int pid, int pos); | 394 | unsigned long *usec) |
| 394 | void graph_plot_task_update_callback(gboolean accept, | 395 | { |
| 395 | gint *selected, | 396 | *sec = time / 1000000000ULL; |
| 396 | gint *non_select, | 397 | *usec = (time / 1000) % 1000000; |
| 397 | gpointer data); | 398 | } |
| 398 | void graph_plot_task_plotted(struct graph_info *ginfo, | 399 | |
| 399 | gint **plotted); | 400 | static inline gint hash_pid(gint val) |
| 401 | { | ||
| 402 | /* idle always gets black */ | ||
| 403 | if (!val) | ||
| 404 | return 0; | ||
| 405 | return trace_hash(val); | ||
| 406 | } | ||
| 407 | |||
| 408 | static inline int hash_cpu(int cpu) | ||
| 409 | { | ||
| 410 | cpu = (cpu << 3) + cpu * 21; | ||
| 411 | return trace_hash(cpu); | ||
| 412 | } | ||
| 400 | 413 | ||
| 401 | 414 | ||
| 402 | #endif /* _TRACE_GRAPH_H */ | 415 | #endif /* _TRACE_GRAPH_H */ |
diff --git a/trace-plot-cpu.c b/trace-plot-cpu.c index 5dea225..c7a37f5 100644 --- a/trace-plot-cpu.c +++ b/trace-plot-cpu.c | |||
| @@ -30,22 +30,6 @@ struct cpu_plot_info { | |||
| 30 | struct record *last_record; | 30 | struct record *last_record; |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | static gint hash_pid(gint val) | ||
| 34 | { | ||
| 35 | /* idle always gets black */ | ||
| 36 | if (!val) | ||
| 37 | return 0; | ||
| 38 | |||
| 39 | return trace_hash(val); | ||
| 40 | } | ||
| 41 | |||
| 42 | static void convert_nano(unsigned long long time, unsigned long *sec, | ||
| 43 | unsigned long *usec) | ||
| 44 | { | ||
| 45 | *sec = time / 1000000000ULL; | ||
| 46 | *usec = (time / 1000) % 1000000; | ||
| 47 | } | ||
| 48 | |||
| 49 | static struct record *get_record_from_time(struct graph_info *ginfo, int cpu, | 33 | static struct record *get_record_from_time(struct graph_info *ginfo, int cpu, |
| 50 | unsigned long long time) | 34 | unsigned long long time) |
| 51 | { | 35 | { |
diff --git a/trace-plot-task.c b/trace-plot-task.c index 9ca97a3..e4ac13a 100644 --- a/trace-plot-task.c +++ b/trace-plot-task.c | |||
| @@ -26,41 +26,7 @@ | |||
| 26 | #define RED 0xff | 26 | #define RED 0xff |
| 27 | #define GREEN (0xff<<16) | 27 | #define GREEN (0xff<<16) |
| 28 | 28 | ||
| 29 | struct task_plot_info { | 29 | gboolean is_running(struct graph_info *ginfo, struct record *record) |
| 30 | int pid; | ||
| 31 | struct cpu_data *cpu_data; | ||
| 32 | struct record **last_records; | ||
| 33 | unsigned long long last_time; | ||
| 34 | unsigned long long wake_time; | ||
| 35 | unsigned long long display_wake_time; | ||
| 36 | int wake_color; | ||
| 37 | int last_cpu; | ||
| 38 | }; | ||
| 39 | |||
| 40 | static void convert_nano(unsigned long long time, unsigned long *sec, | ||
| 41 | unsigned long *usec) | ||
| 42 | { | ||
| 43 | *sec = time / 1000000000ULL; | ||
| 44 | *usec = (time / 1000) % 1000000; | ||
| 45 | } | ||
| 46 | |||
| 47 | static gint hash_pid(gint val) | ||
| 48 | { | ||
| 49 | /* idle always gets black */ | ||
| 50 | if (!val) | ||
| 51 | return 0; | ||
| 52 | |||
| 53 | return trace_hash(val); | ||
| 54 | } | ||
| 55 | |||
| 56 | static int hash_cpu(int cpu) | ||
| 57 | { | ||
| 58 | cpu = (cpu << 3) + cpu * 21; | ||
| 59 | |||
| 60 | return trace_hash(cpu); | ||
| 61 | } | ||
| 62 | |||
| 63 | static gboolean is_running(struct graph_info *ginfo, struct record *record) | ||
| 64 | { | 30 | { |
| 65 | unsigned long long val; | 31 | unsigned long long val; |
| 66 | int id; | 32 | int id; |
| @@ -73,7 +39,7 @@ static gboolean is_running(struct graph_info *ginfo, struct record *record) | |||
| 73 | return val ? FALSE : TRUE; | 39 | return val ? FALSE : TRUE; |
| 74 | } | 40 | } |
| 75 | 41 | ||
| 76 | static gboolean record_matches_pid(struct graph_info *ginfo, | 42 | gboolean record_matches_pid(struct graph_info *ginfo, |
| 77 | struct record *record, int match_pid, | 43 | struct record *record, int match_pid, |
| 78 | int *pid, int *sched_pid, | 44 | int *pid, int *sched_pid, |
| 79 | gboolean *is_sched, | 45 | gboolean *is_sched, |
| @@ -107,7 +73,7 @@ static gboolean record_matches_pid(struct graph_info *ginfo, | |||
| 107 | return FALSE; | 73 | return FALSE; |
| 108 | } | 74 | } |
| 109 | 75 | ||
| 110 | static void set_cpu_to_time(int cpu, struct graph_info *ginfo, unsigned long long time) | 76 | void set_cpu_to_time(int cpu, struct graph_info *ginfo, unsigned long long time) |
| 111 | { | 77 | { |
| 112 | struct record *record; | 78 | struct record *record; |
| 113 | 79 | ||
| @@ -126,7 +92,7 @@ static void set_cpu_to_time(int cpu, struct graph_info *ginfo, unsigned long lon | |||
| 126 | tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, time); | 92 | tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, time); |
| 127 | } | 93 | } |
| 128 | 94 | ||
| 129 | static void set_cpus_to_time(struct graph_info *ginfo, unsigned long long time) | 95 | void set_cpus_to_time(struct graph_info *ginfo, unsigned long long time) |
| 130 | { | 96 | { |
| 131 | int cpu; | 97 | int cpu; |
| 132 | 98 | ||
| @@ -134,7 +100,7 @@ static void set_cpus_to_time(struct graph_info *ginfo, unsigned long long time) | |||
| 134 | set_cpu_to_time(cpu, ginfo, time); | 100 | set_cpu_to_time(cpu, ginfo, time); |
| 135 | } | 101 | } |
| 136 | 102 | ||
| 137 | static int task_plot_match_time(struct graph_info *ginfo, struct graph_plot *plot, | 103 | int task_plot_match_time(struct graph_info *ginfo, struct graph_plot *plot, |
| 138 | unsigned long long time) | 104 | unsigned long long time) |
| 139 | { | 105 | { |
| 140 | struct task_plot_info *task_info = plot->private; | 106 | struct task_plot_info *task_info = plot->private; |
| @@ -173,11 +139,7 @@ static int task_plot_match_time(struct graph_info *ginfo, struct graph_plot *plo | |||
| 173 | return ret; | 139 | return ret; |
| 174 | } | 140 | } |
| 175 | 141 | ||
| 176 | struct offset_cache { | 142 | struct offset_cache *save_offsets(struct graph_info *ginfo) |
| 177 | guint64 *offsets; | ||
| 178 | }; | ||
| 179 | |||
| 180 | static struct offset_cache *save_offsets(struct graph_info *ginfo) | ||
| 181 | { | 143 | { |
| 182 | struct offset_cache *offsets; | 144 | struct offset_cache *offsets; |
| 183 | struct record *record; | 145 | struct record *record; |
| @@ -196,7 +158,7 @@ static struct offset_cache *save_offsets(struct graph_info *ginfo) | |||
| 196 | return offsets; | 158 | return offsets; |
| 197 | } | 159 | } |
| 198 | 160 | ||
| 199 | static void restore_offsets(struct graph_info *ginfo, struct offset_cache *offsets) | 161 | void restore_offsets(struct graph_info *ginfo, struct offset_cache *offsets) |
| 200 | { | 162 | { |
| 201 | struct record *record; | 163 | struct record *record; |
| 202 | int cpu; | 164 | int cpu; |
| @@ -215,7 +177,7 @@ static void restore_offsets(struct graph_info *ginfo, struct offset_cache *offse | |||
| 215 | free(offsets); | 177 | free(offsets); |
| 216 | } | 178 | } |
| 217 | 179 | ||
| 218 | static struct record * | 180 | struct record * |
| 219 | find_record(struct graph_info *ginfo, gint pid, guint64 time) | 181 | find_record(struct graph_info *ginfo, gint pid, guint64 time) |
| 220 | { | 182 | { |
| 221 | struct record *record = NULL; | 183 | struct record *record = NULL; |
| @@ -245,7 +207,7 @@ find_record(struct graph_info *ginfo, gint pid, guint64 time) | |||
| 245 | return record; | 207 | return record; |
| 246 | } | 208 | } |
| 247 | 209 | ||
| 248 | static int task_plot_display_last_event(struct graph_info *ginfo, | 210 | int task_plot_display_last_event(struct graph_info *ginfo, |
| 249 | struct graph_plot *plot, | 211 | struct graph_plot *plot, |
| 250 | struct trace_seq *s, | 212 | struct trace_seq *s, |
| 251 | unsigned long long time) | 213 | unsigned long long time) |
| @@ -318,7 +280,7 @@ static int task_plot_display_last_event(struct graph_info *ginfo, | |||
| 318 | return 1; | 280 | return 1; |
| 319 | } | 281 | } |
| 320 | 282 | ||
| 321 | static void task_plot_start(struct graph_info *ginfo, struct graph_plot *plot, | 283 | void task_plot_start(struct graph_info *ginfo, struct graph_plot *plot, |
| 322 | unsigned long long time) | 284 | unsigned long long time) |
| 323 | { | 285 | { |
| 324 | struct task_plot_info *task_info = plot->private; | 286 | struct task_plot_info *task_info = plot->private; |
| @@ -331,7 +293,7 @@ static void task_plot_start(struct graph_info *ginfo, struct graph_plot *plot, | |||
| 331 | task_info->display_wake_time = 0ULL; | 293 | task_info->display_wake_time = 0ULL; |
| 332 | } | 294 | } |
| 333 | 295 | ||
| 334 | static void update_last_record(struct graph_info *ginfo, | 296 | void update_last_task_record(struct graph_info *ginfo, |
| 335 | struct task_plot_info *task_info, | 297 | struct task_plot_info *task_info, |
| 336 | struct record *record) | 298 | struct record *record) |
| 337 | { | 299 | { |
| @@ -363,7 +325,7 @@ static void update_last_record(struct graph_info *ginfo, | |||
| 363 | continue; | 325 | continue; |
| 364 | 326 | ||
| 365 | if (cpu == this_cpu) { | 327 | if (cpu == this_cpu) { |
| 366 | static int once; | 328 | int once; |
| 367 | 329 | ||
| 368 | trecord = tracecmd_read_prev(handle, record); | 330 | trecord = tracecmd_read_prev(handle, record); |
| 369 | /* Set cpu cursor back to what it was */ | 331 | /* Set cpu cursor back to what it was */ |
| @@ -374,7 +336,7 @@ static void update_last_record(struct graph_info *ginfo, | |||
| 374 | } | 336 | } |
| 375 | free_record(saved); | 337 | free_record(saved); |
| 376 | } else { | 338 | } else { |
| 377 | static int once; | 339 | int once; |
| 378 | 340 | ||
| 379 | saved = tracecmd_read_data(handle, cpu); | 341 | saved = tracecmd_read_data(handle, cpu); |
| 380 | set_cpu_to_time(cpu, ginfo, ts); | 342 | set_cpu_to_time(cpu, ginfo, ts); |
| @@ -412,7 +374,7 @@ static void update_last_record(struct graph_info *ginfo, | |||
| 412 | } | 374 | } |
| 413 | } | 375 | } |
| 414 | 376 | ||
| 415 | static int task_plot_event(struct graph_info *ginfo, | 377 | int task_plot_event(struct graph_info *ginfo, |
| 416 | struct graph_plot *plot, | 378 | struct graph_plot *plot, |
| 417 | struct record *record, | 379 | struct record *record, |
| 418 | struct plot_info *info) | 380 | struct plot_info *info) |
| @@ -429,7 +391,7 @@ static int task_plot_event(struct graph_info *ginfo, | |||
| 429 | pid = task_info->pid; | 391 | pid = task_info->pid; |
| 430 | 392 | ||
| 431 | if (!record) { | 393 | if (!record) { |
| 432 | update_last_record(ginfo, task_info, record); | 394 | update_last_task_record(ginfo, task_info, record); |
| 433 | /* no more records, finish a box if one was started */ | 395 | /* no more records, finish a box if one was started */ |
| 434 | if (task_info->last_cpu >= 0) { | 396 | if (task_info->last_cpu >= 0) { |
| 435 | info->box = TRUE; | 397 | info->box = TRUE; |
| @@ -468,7 +430,7 @@ static int task_plot_event(struct graph_info *ginfo, | |||
| 468 | * viewable range. Search to see if one exists, and if | 430 | * viewable range. Search to see if one exists, and if |
| 469 | * it is the record we want to match. | 431 | * it is the record we want to match. |
| 470 | */ | 432 | */ |
| 471 | update_last_record(ginfo, task_info, record); | 433 | update_last_task_record(ginfo, task_info, record); |
| 472 | 434 | ||
| 473 | if (is_wakeup) { | 435 | if (is_wakeup) { |
| 474 | /* Wake up but not task */ | 436 | /* Wake up but not task */ |
| @@ -555,7 +517,7 @@ static int task_plot_event(struct graph_info *ginfo, | |||
| 555 | } | 517 | } |
| 556 | 518 | ||
| 557 | 519 | ||
| 558 | static struct record * | 520 | struct record * |
| 559 | task_plot_find_record(struct graph_info *ginfo, struct graph_plot *plot, | 521 | task_plot_find_record(struct graph_info *ginfo, struct graph_plot *plot, |
| 560 | unsigned long long time) | 522 | unsigned long long time) |
| 561 | { | 523 | { |
| @@ -569,7 +531,7 @@ task_plot_find_record(struct graph_info *ginfo, struct graph_plot *plot, | |||
| 569 | 531 | ||
| 570 | #define MAX_SEARCH 20 | 532 | #define MAX_SEARCH 20 |
| 571 | 533 | ||
| 572 | static struct record * | 534 | struct record * |
| 573 | find_previous_record(struct graph_info *ginfo, struct record *start_record, | 535 | find_previous_record(struct graph_info *ginfo, struct record *start_record, |
| 574 | int pid, int cpu) | 536 | int pid, int cpu) |
| 575 | { | 537 | { |
| @@ -609,7 +571,7 @@ find_previous_record(struct graph_info *ginfo, struct record *start_record, | |||
| 609 | return record; | 571 | return record; |
| 610 | } | 572 | } |
| 611 | 573 | ||
| 612 | static struct record * | 574 | struct record * |
| 613 | get_display_record(struct graph_info *ginfo, int pid, unsigned long long time) | 575 | get_display_record(struct graph_info *ginfo, int pid, unsigned long long time) |
| 614 | { | 576 | { |
| 615 | struct record *record; | 577 | struct record *record; |
| @@ -752,16 +714,10 @@ static const struct plot_callbacks task_plot_cb = { | |||
| 752 | .destroy = task_plot_destroy | 714 | .destroy = task_plot_destroy |
| 753 | }; | 715 | }; |
| 754 | 716 | ||
| 755 | /** | 717 | |
| 756 | * graph_plot_task_plotted - return what tasks are plotted | 718 | void graph_tasks_plotted(struct graph_info *ginfo, |
| 757 | * @ginfo: the graph info structure | 719 | enum task_plot_type type, |
| 758 | * @plotted: returns an allocated array of gints holding the pids. | 720 | gint **plotted) |
| 759 | * the last pid is -1, NULL, if none are. | ||
| 760 | * | ||
| 761 | * @plotted must be freed with free() after this is called. | ||
| 762 | */ | ||
| 763 | void graph_plot_task_plotted(struct graph_info *ginfo, | ||
| 764 | gint **plotted) | ||
| 765 | { | 721 | { |
| 766 | struct task_plot_info *task_info; | 722 | struct task_plot_info *task_info; |
| 767 | struct graph_plot *plot; | 723 | struct graph_plot *plot; |
| @@ -778,10 +734,26 @@ void graph_plot_task_plotted(struct graph_info *ginfo, | |||
| 778 | } | 734 | } |
| 779 | } | 735 | } |
| 780 | 736 | ||
| 781 | void graph_plot_task_update_callback(gboolean accept, | 737 | /** |
| 782 | gint *selected, | 738 | * graph_plot_task_plotted - return what tasks are plotted |
| 783 | gint *non_select, | 739 | * @ginfo: the graph info structure |
| 784 | gpointer data) | 740 | * @plotted: returns an allocated array of gints holding the pids. |
| 741 | * the last pid is -1, NULL, if none are. | ||
| 742 | * | ||
| 743 | * @plotted must be freed with free() after this is called. | ||
| 744 | */ | ||
| 745 | void graph_plot_task_plotted(struct graph_info *ginfo, | ||
| 746 | gint **plotted) | ||
| 747 | { | ||
| 748 | graph_tasks_plotted(ginfo, TASK_PLOT_LINUX, plotted); | ||
| 749 | } | ||
| 750 | |||
| 751 | void graph_tasks_update_callback(enum task_plot_type type, | ||
| 752 | plot_task_cb plot_cb, | ||
| 753 | gboolean accept, | ||
| 754 | gint *selected, | ||
| 755 | gint *non_select, | ||
| 756 | gpointer data) | ||
| 785 | { | 757 | { |
| 786 | struct graph_info *ginfo = data; | 758 | struct graph_info *ginfo = data; |
| 787 | struct task_plot_info *task_info; | 759 | struct task_plot_info *task_info; |
| @@ -809,12 +781,16 @@ void graph_plot_task_update_callback(gboolean accept, | |||
| 809 | plot = ginfo->plot_array[i]; | 781 | plot = ginfo->plot_array[i]; |
| 810 | if (plot->type != PLOT_TYPE_TASK) | 782 | if (plot->type != PLOT_TYPE_TASK) |
| 811 | continue; | 783 | continue; |
| 784 | |||
| 785 | task_info = plot->private; | ||
| 786 | if (task_info->type != type) | ||
| 787 | continue; | ||
| 788 | |||
| 812 | /* If non are selected, then remove all */ | 789 | /* If non are selected, then remove all */ |
| 813 | if (!select_size) { | 790 | if (!select_size) { |
| 814 | trace_graph_plot_remove(ginfo, plot); | 791 | trace_graph_plot_remove(ginfo, plot); |
| 815 | continue; | 792 | continue; |
| 816 | } | 793 | } |
| 817 | task_info = plot->private; | ||
| 818 | ptr = bsearch(&task_info->pid, selected, select_size, | 794 | ptr = bsearch(&task_info->pid, selected, select_size, |
| 819 | sizeof(gint), id_cmp); | 795 | sizeof(gint), id_cmp); |
| 820 | if (ptr) { | 796 | if (ptr) { |
| @@ -834,11 +810,20 @@ void graph_plot_task_update_callback(gboolean accept, | |||
| 834 | 810 | ||
| 835 | /* Now add any plots that need to be added */ | 811 | /* Now add any plots that need to be added */ |
| 836 | for (i = 0; i < select_size; i++) | 812 | for (i = 0; i < select_size; i++) |
| 837 | graph_plot_task(ginfo, selected[i], ginfo->plots); | 813 | plot_cb(ginfo, selected[i], ginfo->plots); |
| 838 | 814 | ||
| 839 | trace_graph_refresh(ginfo); | 815 | trace_graph_refresh(ginfo); |
| 840 | } | 816 | } |
| 841 | 817 | ||
| 818 | void graph_plot_task_update_callback(gboolean accept, | ||
| 819 | gint *selected, | ||
| 820 | gint *non_select, | ||
| 821 | gpointer data) | ||
| 822 | { | ||
| 823 | graph_tasks_update_callback(TASK_PLOT_LINUX, graph_plot_task, | ||
| 824 | accept, selected, non_select, data); | ||
| 825 | } | ||
| 826 | |||
| 842 | void graph_plot_init_tasks(struct graph_info *ginfo) | 827 | void graph_plot_init_tasks(struct graph_info *ginfo) |
| 843 | { | 828 | { |
| 844 | struct task_plot_info *task_info; | 829 | struct task_plot_info *task_info; |
| @@ -866,6 +851,17 @@ void graph_plot_init_tasks(struct graph_info *ginfo) | |||
| 866 | &task_plot_cb, task_info); | 851 | &task_plot_cb, task_info); |
| 867 | } | 852 | } |
| 868 | 853 | ||
| 854 | void init_task_plot_info(struct graph_info *ginfo, | ||
| 855 | struct task_plot_info *task_info, | ||
| 856 | enum task_plot_type type, | ||
| 857 | int pid) | ||
| 858 | { | ||
| 859 | task_info->last_records = | ||
| 860 | malloc_or_die(sizeof(struct record *) * ginfo->cpus); | ||
| 861 | task_info->pid = pid; | ||
| 862 | task_info->type = type; | ||
| 863 | } | ||
| 864 | |||
| 869 | void graph_plot_task(struct graph_info *ginfo, int pid, int pos) | 865 | void graph_plot_task(struct graph_info *ginfo, int pid, int pos) |
| 870 | { | 866 | { |
| 871 | struct task_plot_info *task_info; | 867 | struct task_plot_info *task_info; |
| @@ -875,9 +871,9 @@ void graph_plot_task(struct graph_info *ginfo, int pid, int pos) | |||
| 875 | int len; | 871 | int len; |
| 876 | 872 | ||
| 877 | task_info = malloc_or_die(sizeof(*task_info)); | 873 | task_info = malloc_or_die(sizeof(*task_info)); |
| 878 | task_info->last_records = | 874 | |
| 879 | malloc_or_die(sizeof(struct record *) * ginfo->cpus); | 875 | init_task_plot_info(ginfo, task_info, TASK_PLOT_LINUX, pid); |
| 880 | task_info->pid = pid; | 876 | |
| 881 | comm = pevent_data_comm_from_pid(ginfo->pevent, pid); | 877 | comm = pevent_data_comm_from_pid(ginfo->pevent, pid); |
| 882 | 878 | ||
| 883 | len = strlen(comm) + 100; | 879 | len = strlen(comm) + 100; |
diff --git a/trace-plot-task.h b/trace-plot-task.h new file mode 100644 index 0000000..3232339 --- /dev/null +++ b/trace-plot-task.h | |||
| @@ -0,0 +1,118 @@ | |||
| 1 | #ifndef __TRACE_PLOT_TASK_H | ||
| 2 | #define __TRACE_PLOT_TASK_H | ||
| 3 | |||
| 4 | #include <gtk/gtk.h> | ||
| 5 | |||
| 6 | #include "trace-cmd.h" | ||
| 7 | |||
| 8 | struct graph_info; | ||
| 9 | struct graph_plot; | ||
| 10 | struct plot_info; | ||
| 11 | |||
| 12 | enum task_plot_type { | ||
| 13 | TASK_PLOT_OTHER, | ||
| 14 | TASK_PLOT_LINUX, | ||
| 15 | TASK_PLOT_RT | ||
| 16 | }; | ||
| 17 | |||
| 18 | /** | ||
| 19 | * struct task_plot_info - information for plotting a single task | ||
| 20 | * @pid: pid to plot | ||
| 21 | * @cpu_data: state of each cpu | ||
| 22 | * @last_records: cache of recently accessed records | ||
| 23 | * @last_time: time of last record seen by this task graph | ||
| 24 | * @wake_time: time task resumed execution | ||
| 25 | * @display_wake_time: as above, but reset under some circumstances | ||
| 26 | * @wake_color: | ||
| 27 | * @last_cpu: cpu task is currently running on | ||
| 28 | * @type: type of task plot | ||
| 29 | */ | ||
| 30 | struct task_plot_info { | ||
| 31 | int pid; | ||
| 32 | struct cpu_data *cpu_data; | ||
| 33 | struct record **last_records; | ||
| 34 | unsigned long long last_time; | ||
| 35 | unsigned long long wake_time; | ||
| 36 | unsigned long long display_wake_time; | ||
| 37 | int wake_color; | ||
| 38 | int last_cpu; | ||
| 39 | enum task_plot_type type; | ||
| 40 | }; | ||
| 41 | |||
| 42 | /* Querying records */ | ||
| 43 | gboolean is_running(struct graph_info *ginfo, struct record *record); | ||
| 44 | gboolean record_matches_pid(struct graph_info *ginfo, struct record *record, | ||
| 45 | int match_pid, int *pid, int *sched_pid, | ||
| 46 | gboolean *is_sched, gboolean *wakeup); | ||
| 47 | |||
| 48 | /* State maintenance */ | ||
| 49 | void update_last_task_record(struct graph_info *ginfo, struct task_plot_info *task_info, | ||
| 50 | struct record *record); | ||
| 51 | |||
| 52 | /* Searching for records */ | ||
| 53 | #define MAX_SEARCH 20 | ||
| 54 | struct record * | ||
| 55 | find_record(struct graph_info *ginfo, gint pid, guint64 time); | ||
| 56 | struct record *find_previous_record(struct graph_info *ginfo, | ||
| 57 | struct record *start_record, | ||
| 58 | int pid, int cpu); | ||
| 59 | struct record *get_display_record(struct graph_info *ginfo, int pid, | ||
| 60 | unsigned long long time); | ||
| 61 | |||
| 62 | /* Seeking in data file */ | ||
| 63 | void set_cpu_to_time(int cpu, struct graph_info *ginfo, unsigned long long time); | ||
| 64 | void set_cpus_to_time(struct graph_info *ginfo, unsigned long long time); | ||
| 65 | |||
| 66 | /* Saving / restoring state */ | ||
| 67 | struct offset_cache { | ||
| 68 | guint64 *offsets; | ||
| 69 | }; | ||
| 70 | struct offset_cache *save_offsets(struct graph_info *ginfo); | ||
| 71 | void restore_offsets(struct graph_info *ginfo, struct offset_cache *offsets); | ||
| 72 | |||
| 73 | /* Callbacks */ | ||
| 74 | int task_plot_match_time(struct graph_info *ginfo, struct graph_plot *plot, | ||
| 75 | unsigned long long time); | ||
| 76 | int task_plot_display_last_event(struct graph_info *ginfo, | ||
| 77 | struct graph_plot *plot, | ||
| 78 | struct trace_seq *s, | ||
| 79 | unsigned long long time); | ||
| 80 | void task_plot_start(struct graph_info *ginfo, struct graph_plot *plot, | ||
| 81 | unsigned long long time); | ||
| 82 | int task_plot_event(struct graph_info *ginfo, struct graph_plot *plot, | ||
| 83 | struct record *record, struct plot_info *info); | ||
| 84 | struct record *task_plot_find_record(struct graph_info *ginfo, | ||
| 85 | struct graph_plot *plot, | ||
| 86 | unsigned long long time); | ||
| 87 | int task_plot_display_info(struct graph_info *ginfo, | ||
| 88 | struct graph_plot *plot, | ||
| 89 | struct trace_seq *s, | ||
| 90 | unsigned long long time); | ||
| 91 | void task_plot_destroy(struct graph_info *ginfo, struct graph_plot *plot); | ||
| 92 | |||
| 93 | /* Plot management */ | ||
| 94 | void graph_plot_task(struct graph_info *ginfo, int pid, int pos); | ||
| 95 | void graph_plot_task_plotted(struct graph_info *ginfo, | ||
| 96 | gint **plotted); | ||
| 97 | |||
| 98 | void graph_plot_task_update_callback(gboolean accept, | ||
| 99 | gint *selected, | ||
| 100 | gint *non_select, | ||
| 101 | gpointer data); | ||
| 102 | |||
| 103 | void graph_plot_init_tasks(struct graph_info *ginfo); | ||
| 104 | |||
| 105 | /* Shared functionality for inheriting structs */ | ||
| 106 | typedef void (plot_task_cb)(struct graph_info *ginfo, int pid, int pos); | ||
| 107 | void graph_tasks_update_callback(enum task_plot_type type, | ||
| 108 | plot_task_cb plot_cb, | ||
| 109 | gboolean accept, | ||
| 110 | gint *selected, | ||
| 111 | gint *non_select, | ||
| 112 | gpointer data); | ||
| 113 | void init_task_plot_info(struct graph_info *ginfo, | ||
| 114 | struct task_plot_info *task_info, | ||
| 115 | enum task_plot_type type, int pid); | ||
| 116 | void graph_tasks_plotted(struct graph_info *ginfo, enum task_plot_type type, | ||
| 117 | gint **plotted); | ||
| 118 | #endif | ||
