diff options
author | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2011-07-25 18:48:04 -0400 |
---|---|---|
committer | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2011-07-25 18:48:04 -0400 |
commit | 38f0c2047819574a120380810de77c79c2a61bee (patch) | |
tree | 12ba5fd7271a50d14a901f5f759766cc057a113f | |
parent | 784e08135bc3d68f9c3fe02ba32e2e4711d8fcc6 (diff) |
correctly handle PID timestamps
And account for suspension time.
-rw-r--r-- | src/ft2csv.c | 129 |
1 files changed, 115 insertions, 14 deletions
diff --git a/src/ft2csv.c b/src/ft2csv.c index aceeb25..75c9f35 100644 --- a/src/ft2csv.c +++ b/src/ft2csv.c | |||
@@ -97,50 +97,151 @@ static struct timestamp* find_second_ts(struct timestamp* start, | |||
97 | start->event); | 97 | start->event); |
98 | } | 98 | } |
99 | 99 | ||
100 | typedef void (*pair_fmt_t)(struct timestamp* first, struct timestamp* second); | 100 | static struct timestamp* next_pid(struct timestamp* start, struct timestamp* end, |
101 | unsigned int pid, unsigned long id1, unsigned long id2) | ||
102 | { | ||
103 | struct timestamp* pos; | ||
104 | unsigned int last_seqno = 0; | ||
105 | |||
106 | for (pos = start; pos != end; pos++) { | ||
107 | /* check for for holes in the sequence number */ | ||
108 | if (last_seqno && last_seqno + 1 != pos->seq_no) { | ||
109 | /* stumbled across a hole */ | ||
110 | return NULL; | ||
111 | } | ||
112 | last_seqno = pos->seq_no; | ||
113 | |||
114 | /* only care about this PID */ | ||
115 | if (ts_pid_fragment(pos) == pid) { | ||
116 | /* is it the right one? */ | ||
117 | if (pos->event == id1 || pos->event == id2) | ||
118 | return pos; | ||
119 | else | ||
120 | /* Don't allow unexptected IDs interleaved. | ||
121 | * Tasks are sequential, there shouldn't be | ||
122 | * anything else. */ | ||
123 | return NULL; | ||
124 | } | ||
125 | } | ||
126 | return NULL; | ||
127 | } | ||
128 | |||
129 | static struct timestamp* accumulate_exec_time( | ||
130 | struct timestamp* start, struct timestamp* end, | ||
131 | unsigned int pid, unsigned long stop_id, uint64_t *sum) | ||
132 | { | ||
133 | struct timestamp* pos = start; | ||
134 | uint64_t exec_start; | ||
135 | |||
136 | *sum = 0; | ||
137 | |||
138 | while (1) { | ||
139 | exec_start = pos->timestamp; | ||
140 | |||
141 | /* find a suspension */ | ||
142 | pos = next_pid(pos + 1, end, pid, TS_LOCK_SUSPEND, stop_id); | ||
143 | if (!pos) | ||
144 | /* broken stream */ | ||
145 | return NULL; | ||
146 | |||
147 | /* account for exec until pos */ | ||
148 | *sum += pos->timestamp - exec_start; | ||
149 | |||
150 | if (pos->event == stop_id) | ||
151 | /* no suspension */ | ||
152 | return pos; | ||
153 | |||
154 | /* find matching resume */ | ||
155 | pos = next_pid(pos + 1, end, pid, TS_LOCK_RESUME, 0); | ||
156 | if (!pos) | ||
157 | /* broken stream */ | ||
158 | return NULL; | ||
159 | |||
160 | /* must be a resume => start over */ | ||
161 | } | ||
162 | } | ||
163 | |||
164 | typedef void (*pair_fmt_t)(struct timestamp* first, struct timestamp* second, uint64_t exec_time); | ||
101 | 165 | ||
102 | static void print_pair_csv(struct timestamp* first, struct timestamp* second) | 166 | static void print_pair_csv(struct timestamp* first, struct timestamp* second, uint64_t exec_time) |
103 | { | 167 | { |
104 | printf("%llu, %llu, %llu\n", | 168 | printf("%llu, %llu, %llu\n", |
105 | (unsigned long long) first->timestamp, | 169 | (unsigned long long) first->timestamp, |
106 | (unsigned long long) second->timestamp, | 170 | (unsigned long long) second->timestamp, |
107 | (unsigned long long) | 171 | (unsigned long long) exec_time); |
108 | (second->timestamp - first->timestamp)); | ||
109 | } | 172 | } |
110 | 173 | ||
111 | static void print_pair_bin(struct timestamp* first, struct timestamp* second) | 174 | static void print_pair_bin(struct timestamp* first, struct timestamp* second, uint64_t exec_time) |
112 | { | 175 | { |
113 | float delta = second->timestamp - first->timestamp; | 176 | float delta = exec_time; |
114 | fwrite(&delta, sizeof(delta), 1, stdout); | 177 | fwrite(&delta, sizeof(delta), 1, stdout); |
115 | } | 178 | } |
116 | 179 | ||
117 | pair_fmt_t format_pair = print_pair_csv; | 180 | pair_fmt_t format_pair = print_pair_csv; |
118 | 181 | ||
119 | static void show_csv(struct timestamp* first, struct timestamp *end) | 182 | static void find_event_by_pid(struct timestamp* first, struct timestamp* end) |
120 | { | 183 | { |
121 | struct timestamp *second; | 184 | struct timestamp *second; |
122 | 185 | uint64_t exec_time = 0; | |
123 | if (first->cpu == avoid_cpu || | 186 | |
124 | (only_cpu != -1 && first->cpu != only_cpu)) { | 187 | /* special case: take suspensions into account */ |
125 | avoided++; | 188 | if (first->event == TS_LOCK_START) { |
126 | return; | 189 | second = accumulate_exec_time(first, end, |
190 | ts_pid_fragment(first), | ||
191 | first->event + 3, &exec_time); | ||
192 | } else { | ||
193 | second = next_pid(first + 1, end, ts_pid_fragment(first), | ||
194 | first->event + 1, 0); | ||
195 | if (second) | ||
196 | exec_time = second->timestamp - first->timestamp; | ||
127 | } | 197 | } |
198 | if (second) { | ||
199 | if (exec_time > threshold) | ||
200 | filtered++; | ||
201 | else | ||
202 | format_pair(first, second, exec_time); | ||
203 | complete++; | ||
204 | } else | ||
205 | incomplete++; | ||
206 | } | ||
207 | |||
208 | static void find_event_by_eid(struct timestamp *first, struct timestamp* end) | ||
209 | { | ||
210 | struct timestamp *second; | ||
211 | uint64_t exec_time; | ||
128 | 212 | ||
129 | second = find_second_ts(first, end); | 213 | second = find_second_ts(first, end); |
130 | if (second) { | 214 | if (second) { |
131 | if (second->timestamp - first->timestamp > threshold) | 215 | exec_time = second->timestamp - first->timestamp; |
216 | if (exec_time > threshold) | ||
132 | filtered++; | 217 | filtered++; |
133 | else if (first->task_type != TSK_RT && | 218 | else if (first->task_type != TSK_RT && |
134 | second->task_type != TSK_RT && !want_best_effort) | 219 | second->task_type != TSK_RT && !want_best_effort) |
135 | non_rt++; | 220 | non_rt++; |
136 | else { | 221 | else { |
137 | format_pair(first, second); | 222 | format_pair(first, second, exec_time); |
138 | complete++; | 223 | complete++; |
139 | } | 224 | } |
140 | } else | 225 | } else |
141 | incomplete++; | 226 | incomplete++; |
142 | } | 227 | } |
143 | 228 | ||
229 | static void show_csv(struct timestamp* first, struct timestamp *end) | ||
230 | { | ||
231 | |||
232 | |||
233 | if (first->cpu == avoid_cpu || | ||
234 | (only_cpu != -1 && first->cpu != only_cpu)) { | ||
235 | avoided++; | ||
236 | return; | ||
237 | } | ||
238 | |||
239 | if (first->event <= PID_RECORDS_RANGE) | ||
240 | find_event_by_pid(first, end); | ||
241 | else | ||
242 | find_event_by_eid(first, end); | ||
243 | } | ||
244 | |||
144 | typedef void (*single_fmt_t)(struct timestamp* ts); | 245 | typedef void (*single_fmt_t)(struct timestamp* ts); |
145 | 246 | ||
146 | static void print_single_csv(struct timestamp* ts) | 247 | static void print_single_csv(struct timestamp* ts) |