aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan <hermanjl@hermanjl-Aspire-5553G.(none)>2012-03-05 18:00:39 -0500
committerJonathan <hermanjl@hermanjl-Aspire-5553G.(none)>2012-03-05 18:00:39 -0500
commit61266395ff4f371933c104cff6671aae7f43c3fd (patch)
tree4e0c1bf15015a80a57db728c5857005234481f4b
parent8bcd73ddae5d74fb9b2b8aaedd3aa6a39ef3f75d (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.txt225
-rw-r--r--kernel-shark.c15
-rw-r--r--rt-graph.h11
-rw-r--r--rt-plot-task.c54
-rw-r--r--rt-plot-task.h22
-rw-r--r--task-list.c99
-rw-r--r--task-list.h20
-rw-r--r--trace-graph.c7
-rw-r--r--trace-graph.h29
-rw-r--r--trace-plot-cpu.c16
-rw-r--r--trace-plot-task.c148
-rw-r--r--trace-plot-task.h118
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
2Can't do this until cpus set up!
3
40. Load all events w/ proper stuff
5
61. Create list of rt_tasks
72. Create seperate dailog for rt tasks w/ a callback.
83. Allow dialog to be filtered.
94. Create dummy task thing that just says hi.
105. Make it print out when it reads stuff.
116. Draw shit
127. Draw new shit.
13
14
15struct 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
44struct parse-events.h {
45 /* Can write shit into it person by person */
46 struct trace_seq;
47};
48
49struct unknown {
50
51};
52
53struct trace-graph.c {
54
55};
56
57/* trace-graph.c */
58
59
60
61struct 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
167struct 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
157static 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
164static void print_time(unsigned long long time) 153static 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}
diff --git a/rt-graph.h b/rt-graph.h
index 3037301..3357b52 100644
--- a/rt-graph.h
+++ b/rt-graph.h
@@ -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
8struct rt_graph_info { 9struct 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);
60void init_rt_event_cache(struct rt_graph_info *rtinfo); 61void init_rt_event_cache(struct rt_graph_info *rtinfo);
61 62
62/* Metadata */
63void rt_plot_task_plotted(struct rt_graph_info *rt_info, gint **plotted);
64
65/* Callbacks for managing task list */
66void rt_plot_task_update_callback(gboolean accept, gint *selected,
67 gint *non_select, gpointer data);
68void 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
3static 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
13void 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
22void rt_plot_task_plotted(struct graph_info *ginfo, gint **plotted)
23{
24 graph_tasks_plotted(ginfo, TASK_PLOT_RT, plotted);
25}
26
27void 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
6struct 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
14void rt_plot_task(struct graph_info *ginfo, int pid, int pos);
15void rt_plot_task_plotted(struct graph_info *ginfo,
16 gint **plotted);
17void 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
3static guint get_task_hash_key(gint pid)
4{
5 return trace_hash(pid) % TASK_HASH_SIZE;
6}
7
8struct 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 */
24struct 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 */
37struct 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 */
57void 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 */
78gint *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
10struct task_list {
11 struct task_list *next;
12 gint pid;
13};
14
15struct task_list* find_task_list(struct task_list **tasks, int pid);
16struct task_list* add_task_hash(struct task_list **tasks, int pid);
17void free_task_hash(struct task_list **tasks);
18gint* 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;
70static void redraw_pixmap_backend(struct graph_info *ginfo); 70static void redraw_pixmap_backend(struct graph_info *ginfo);
71static void update_label_window(struct graph_info *ginfo); 71static void update_label_window(struct graph_info *ginfo);
72 72
73static 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
80static int convert_time_to_x(struct graph_info *ginfo, guint64 time) 73static 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
31struct graph_info; 32struct 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 */ 393static inline void convert_nano(unsigned long long time, unsigned long *sec,
393void graph_plot_task(struct graph_info *ginfo, int pid, int pos); 394 unsigned long *usec)
394void 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}
398void graph_plot_task_plotted(struct graph_info *ginfo, 399
399 gint **plotted); 400static 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
408static 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
33static 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
42static 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
49static struct record *get_record_from_time(struct graph_info *ginfo, int cpu, 33static 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
29struct task_plot_info { 29gboolean 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
40static 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
47static 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
56static int hash_cpu(int cpu)
57{
58 cpu = (cpu << 3) + cpu * 21;
59
60 return trace_hash(cpu);
61}
62
63static 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
76static gboolean record_matches_pid(struct graph_info *ginfo, 42gboolean 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
110static void set_cpu_to_time(int cpu, struct graph_info *ginfo, unsigned long long time) 76void 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
129static void set_cpus_to_time(struct graph_info *ginfo, unsigned long long time) 95void 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
137static int task_plot_match_time(struct graph_info *ginfo, struct graph_plot *plot, 103int 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
176struct offset_cache { 142struct offset_cache *save_offsets(struct graph_info *ginfo)
177 guint64 *offsets;
178};
179
180static 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
199static void restore_offsets(struct graph_info *ginfo, struct offset_cache *offsets) 161void 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
218static struct record * 180struct record *
219find_record(struct graph_info *ginfo, gint pid, guint64 time) 181find_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
248static int task_plot_display_last_event(struct graph_info *ginfo, 210int 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
321static void task_plot_start(struct graph_info *ginfo, struct graph_plot *plot, 283void 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
334static void update_last_record(struct graph_info *ginfo, 296void 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
415static int task_plot_event(struct graph_info *ginfo, 377int 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
558static struct record * 520struct record *
559task_plot_find_record(struct graph_info *ginfo, struct graph_plot *plot, 521task_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
572static struct record * 534struct record *
573find_previous_record(struct graph_info *ginfo, struct record *start_record, 535find_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
612static struct record * 574struct record *
613get_display_record(struct graph_info *ginfo, int pid, unsigned long long time) 575get_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 718void 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 */
763void 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
781void 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 */
745void graph_plot_task_plotted(struct graph_info *ginfo,
746 gint **plotted)
747{
748 graph_tasks_plotted(ginfo, TASK_PLOT_LINUX, plotted);
749}
750
751void 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
818void 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
842void graph_plot_init_tasks(struct graph_info *ginfo) 827void 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
854void 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
869void graph_plot_task(struct graph_info *ginfo, int pid, int pos) 865void 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
8struct graph_info;
9struct graph_plot;
10struct plot_info;
11
12enum 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 */
30struct 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 */
43gboolean is_running(struct graph_info *ginfo, struct record *record);
44gboolean 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 */
49void 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
54struct record *
55find_record(struct graph_info *ginfo, gint pid, guint64 time);
56struct record *find_previous_record(struct graph_info *ginfo,
57 struct record *start_record,
58 int pid, int cpu);
59struct record *get_display_record(struct graph_info *ginfo, int pid,
60 unsigned long long time);
61
62/* Seeking in data file */
63void set_cpu_to_time(int cpu, struct graph_info *ginfo, unsigned long long time);
64void set_cpus_to_time(struct graph_info *ginfo, unsigned long long time);
65
66/* Saving / restoring state */
67struct offset_cache {
68 guint64 *offsets;
69};
70struct offset_cache *save_offsets(struct graph_info *ginfo);
71void restore_offsets(struct graph_info *ginfo, struct offset_cache *offsets);
72
73/* Callbacks */
74int task_plot_match_time(struct graph_info *ginfo, struct graph_plot *plot,
75 unsigned long long time);
76int task_plot_display_last_event(struct graph_info *ginfo,
77 struct graph_plot *plot,
78 struct trace_seq *s,
79 unsigned long long time);
80void task_plot_start(struct graph_info *ginfo, struct graph_plot *plot,
81 unsigned long long time);
82int task_plot_event(struct graph_info *ginfo, struct graph_plot *plot,
83 struct record *record, struct plot_info *info);
84struct record *task_plot_find_record(struct graph_info *ginfo,
85 struct graph_plot *plot,
86 unsigned long long time);
87int task_plot_display_info(struct graph_info *ginfo,
88 struct graph_plot *plot,
89 struct trace_seq *s,
90 unsigned long long time);
91void task_plot_destroy(struct graph_info *ginfo, struct graph_plot *plot);
92
93/* Plot management */
94void graph_plot_task(struct graph_info *ginfo, int pid, int pos);
95void graph_plot_task_plotted(struct graph_info *ginfo,
96 gint **plotted);
97
98void graph_plot_task_update_callback(gboolean accept,
99 gint *selected,
100 gint *non_select,
101 gpointer data);
102
103void graph_plot_init_tasks(struct graph_info *ginfo);
104
105/* Shared functionality for inheriting structs */
106typedef void (plot_task_cb)(struct graph_info *ginfo, int pid, int pos);
107void 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);
113void init_task_plot_info(struct graph_info *ginfo,
114 struct task_plot_info *task_info,
115 enum task_plot_type type, int pid);
116void graph_tasks_plotted(struct graph_info *ginfo, enum task_plot_type type,
117 gint **plotted);
118#endif