diff options
| author | Bjoern Brandenburg <bbb@mpi-sws.org> | 2012-08-15 10:14:52 -0400 |
|---|---|---|
| committer | Bjoern Brandenburg <bbb@mpi-sws.org> | 2012-10-19 16:38:25 -0400 |
| commit | 44da17bf24f2e67ab71ecb552ebf7b460e64999e (patch) | |
| tree | 2d23a65de5a5c095f2d18c2f2fad0c688de9a49f /src | |
| parent | 2265873941ade09b9ba4eb754278818cd5801d3a (diff) | |
Support matching based on PID in ft2csv
Diffstat (limited to 'src')
| -rw-r--r-- | src/ft2csv.c | 140 |
1 files changed, 126 insertions, 14 deletions
diff --git a/src/ft2csv.c b/src/ft2csv.c index a6b1bf2..ff3db23 100644 --- a/src/ft2csv.c +++ b/src/ft2csv.c | |||
| @@ -27,8 +27,11 @@ | |||
| 27 | 27 | ||
| 28 | #include "timestamp.h" | 28 | #include "timestamp.h" |
| 29 | 29 | ||
| 30 | #define AUTO_SELECT -1 | ||
| 31 | |||
| 30 | static int want_interleaved = 1; | 32 | static int want_interleaved = 1; |
| 31 | static int want_best_effort = 0; | 33 | static int want_best_effort = 0; |
| 34 | static int find_by_pid = AUTO_SELECT; | ||
| 32 | 35 | ||
| 33 | /* discard samples from a specific CPU */ | 36 | /* discard samples from a specific CPU */ |
| 34 | static int avoid_cpu = -1; | 37 | static int avoid_cpu = -1; |
| @@ -94,48 +97,146 @@ static struct timestamp* find_second_ts(struct timestamp* start, | |||
| 94 | start->event); | 97 | start->event); |
| 95 | } | 98 | } |
| 96 | 99 | ||
| 97 | 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 (pos->pid == 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 | } | ||
| 98 | 128 | ||
| 99 | static void print_pair_csv(struct timestamp* first, struct timestamp* second) | 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); | ||
| 165 | |||
| 166 | static void print_pair_csv(struct timestamp* first, struct timestamp* second, uint64_t exec_time) | ||
| 100 | { | 167 | { |
| 101 | printf("%llu, %llu, %llu\n", | 168 | printf("%llu, %llu, %llu\n", |
| 102 | (unsigned long long) first->timestamp, | 169 | (unsigned long long) first->timestamp, |
| 103 | (unsigned long long) second->timestamp, | 170 | (unsigned long long) second->timestamp, |
| 104 | (unsigned long long) | 171 | (unsigned long long) exec_time); |
| 105 | (second->timestamp - first->timestamp)); | ||
| 106 | } | 172 | } |
| 107 | 173 | ||
| 108 | 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) |
| 109 | { | 175 | { |
| 110 | float delta = second->timestamp - first->timestamp; | 176 | float delta = exec_time; |
| 111 | fwrite(&delta, sizeof(delta), 1, stdout); | 177 | fwrite(&delta, sizeof(delta), 1, stdout); |
| 112 | } | 178 | } |
| 113 | 179 | ||
| 114 | pair_fmt_t format_pair = print_pair_csv; | 180 | pair_fmt_t format_pair = print_pair_csv; |
| 115 | 181 | ||
| 116 | static void show_csv(struct timestamp* first, struct timestamp *end) | 182 | static void find_event_by_pid(struct timestamp* first, struct timestamp* end) |
| 117 | { | 183 | { |
| 118 | struct timestamp *second; | 184 | struct timestamp *second; |
| 119 | 185 | uint64_t exec_time = 0; | |
| 120 | if (first->cpu == avoid_cpu || | 186 | |
| 121 | (only_cpu != -1 && first->cpu != only_cpu)) { | 187 | /* special case: take suspensions into account */ |
| 122 | avoided++; | 188 | if (first->event >= SUSPENSION_RANGE) { |
| 123 | return; | 189 | second = accumulate_exec_time(first, end, |
| 190 | first->pid, | ||
| 191 | first->event + 1, &exec_time); | ||
| 192 | } else { | ||
| 193 | second = next_pid(first + 1, end, first->pid, | ||
| 194 | first->event + 1, 0); | ||
| 195 | if (second) | ||
| 196 | exec_time = second->timestamp - first->timestamp; | ||
| 124 | } | 197 | } |
| 198 | if (second) { | ||
| 199 | format_pair(first, second, exec_time); | ||
| 200 | complete++; | ||
| 201 | } else | ||
| 202 | incomplete++; | ||
| 203 | } | ||
| 204 | |||
| 205 | static void find_event_by_eid(struct timestamp *first, struct timestamp* end) | ||
| 206 | { | ||
| 207 | struct timestamp *second; | ||
| 208 | uint64_t exec_time; | ||
| 125 | 209 | ||
| 126 | second = find_second_ts(first, end); | 210 | second = find_second_ts(first, end); |
| 127 | if (second) { | 211 | if (second) { |
| 212 | exec_time = second->timestamp - first->timestamp; | ||
| 128 | if (first->task_type != TSK_RT && | 213 | if (first->task_type != TSK_RT && |
| 129 | second->task_type != TSK_RT && !want_best_effort) | 214 | second->task_type != TSK_RT && !want_best_effort) |
| 130 | non_rt++; | 215 | non_rt++; |
| 131 | else { | 216 | else { |
| 132 | format_pair(first, second); | 217 | format_pair(first, second, exec_time); |
| 133 | complete++; | 218 | complete++; |
| 134 | } | 219 | } |
| 135 | } else | 220 | } else |
| 136 | incomplete++; | 221 | incomplete++; |
| 137 | } | 222 | } |
| 138 | 223 | ||
| 224 | static void show_csv(struct timestamp* first, struct timestamp *end) | ||
| 225 | { | ||
| 226 | |||
| 227 | |||
| 228 | if (first->cpu == avoid_cpu || | ||
| 229 | (only_cpu != -1 && first->cpu != only_cpu)) { | ||
| 230 | avoided++; | ||
| 231 | return; | ||
| 232 | } | ||
| 233 | |||
| 234 | if (find_by_pid) | ||
| 235 | find_event_by_pid(first, end); | ||
| 236 | else | ||
| 237 | find_event_by_eid(first, end); | ||
| 238 | } | ||
| 239 | |||
| 139 | typedef void (*single_fmt_t)(struct timestamp* ts); | 240 | typedef void (*single_fmt_t)(struct timestamp* ts); |
| 140 | 241 | ||
| 141 | static void print_single_csv(struct timestamp* ts) | 242 | static void print_single_csv(struct timestamp* ts) |
| @@ -205,7 +306,7 @@ static void die(char* msg) | |||
| 205 | exit(1); | 306 | exit(1); |
| 206 | } | 307 | } |
| 207 | 308 | ||
| 208 | #define OPTS "ibra:o:" | 309 | #define OPTS "ibra:o:pe" |
| 209 | 310 | ||
| 210 | int main(int argc, char** argv) | 311 | int main(int argc, char** argv) |
| 211 | { | 312 | { |
| @@ -242,6 +343,14 @@ int main(int argc, char** argv) | |||
| 242 | fprintf(stderr, "Using only samples from CPU %d.\n", | 343 | fprintf(stderr, "Using only samples from CPU %d.\n", |
| 243 | only_cpu); | 344 | only_cpu); |
| 244 | break; | 345 | break; |
| 346 | case 'p': | ||
| 347 | find_by_pid = 1; | ||
| 348 | fprintf(stderr, "Matching timestamp pairs based on PID.\n"); | ||
| 349 | break; | ||
| 350 | case 'e': | ||
| 351 | find_by_pid = 0; | ||
| 352 | fprintf(stderr, "Matching timestamp pairs based on event ID.\n"); | ||
| 353 | break; | ||
| 245 | default: | 354 | default: |
| 246 | die("Unknown option."); | 355 | die("Unknown option."); |
| 247 | break; | 356 | break; |
| @@ -261,6 +370,9 @@ int main(int argc, char** argv) | |||
| 261 | die("Unknown event!"); | 370 | die("Unknown event!"); |
| 262 | } | 371 | } |
| 263 | 372 | ||
| 373 | if (find_by_pid == AUTO_SELECT) | ||
| 374 | find_by_pid = id <= PID_RECORDS_RANGE; | ||
| 375 | |||
| 264 | ts = (struct timestamp*) mapped; | 376 | ts = (struct timestamp*) mapped; |
| 265 | count = size / sizeof(struct timestamp); | 377 | count = size / sizeof(struct timestamp); |
| 266 | end = ts + count; | 378 | end = ts + count; |
