diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2012-10-05 17:14:37 -0400 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2012-10-05 17:14:37 -0400 |
| commit | 93290e83d330653f090b3780e59ea5d2bf1e3bca (patch) | |
| tree | 084663110e9ef4fa1d306f3421deb675fb575d60 | |
| parent | 8e74ea12a1fcbe0a799284163f0cf72bcb916df7 (diff) | |
Rewrote set_cpu_to_rts() and iterate() for increased performance and accuracy.
Container job information functions, like displaying the job in the server's boxes
or the currently running task in pop-ups, rewritten to take advantage of these
changes.
| -rw-r--r-- | rt-plot-container.c | 114 | ||||
| -rw-r--r-- | rt-plot-vcpu.c | 28 | ||||
| -rw-r--r-- | rt-plot.c | 178 | ||||
| -rw-r--r-- | rt-plot.h | 2 | ||||
| -rw-r--r-- | trace-dialog.c | 2 | ||||
| -rw-r--r-- | trace-graph.c | 38 |
6 files changed, 188 insertions, 174 deletions
diff --git a/rt-plot-container.c b/rt-plot-container.c index 94f78ee..6c647fc 100644 --- a/rt-plot-container.c +++ b/rt-plot-container.c | |||
| @@ -22,6 +22,80 @@ int rt_plot_get_containers(struct graph_info *ginfo, gint **conts, | |||
| 22 | return count; | 22 | return count; |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | struct record * | ||
| 26 | rt_read_next_data(struct graph_info *ginfo, struct tracecmd_input *handle, int *rec_cpu) | ||
| 27 | { | ||
| 28 | unsigned long long ts; | ||
| 29 | struct record *record; | ||
| 30 | int next; | ||
| 31 | int cpu; | ||
| 32 | |||
| 33 | if (rec_cpu) | ||
| 34 | *rec_cpu = -1; | ||
| 35 | |||
| 36 | next = -1; | ||
| 37 | ts = 0; | ||
| 38 | |||
| 39 | for (cpu = 0; cpu < ginfo->cpus; cpu++) { | ||
| 40 | record = tracecmd_peek_data(handle, cpu); | ||
| 41 | if (record && (!ts || get_rts(ginfo, record) < ts)) { | ||
| 42 | ts = get_rts(ginfo, record); | ||
| 43 | next = cpu; | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | if (next >= 0) { | ||
| 48 | if (rec_cpu) | ||
| 49 | *rec_cpu = next; | ||
| 50 | return tracecmd_read_data(handle, next); | ||
| 51 | } | ||
| 52 | |||
| 53 | return NULL; | ||
| 54 | } | ||
| 55 | |||
| 56 | struct server_iter_args { | ||
| 57 | unsigned long long goal; | ||
| 58 | int match_sid; | ||
| 59 | |||
| 60 | int *out_job; | ||
| 61 | int *out_tid; | ||
| 62 | int *out_tjob; | ||
| 63 | int is_running; | ||
| 64 | }; | ||
| 65 | |||
| 66 | static int server_iterator(struct graph_info *ginfo, struct record *record, void *data) | ||
| 67 | { | ||
| 68 | int sid, job, tid, tjob, match; | ||
| 69 | struct server_iter_args *args = data; | ||
| 70 | unsigned long long when, time = get_rts(ginfo, record); | ||
| 71 | |||
| 72 | if (time > args->goal + max_rt_search(ginfo)) | ||
| 73 | return 0; | ||
| 74 | if (time < args->goal) | ||
| 75 | return 1; | ||
| 76 | |||
| 77 | #define ARGS ginfo, record, &sid, &job, &tid, &tjob, &when | ||
| 78 | match = rt_graph_check_server_switch_away(ARGS); | ||
| 79 | if (match && sid == args->match_sid) { | ||
| 80 | (*args->out_tid) = tid; | ||
| 81 | (*args->out_tjob) = tjob; | ||
| 82 | (*args->out_job) = job; | ||
| 83 | args->is_running = 1; | ||
| 84 | return 0; | ||
| 85 | |||
| 86 | } | ||
| 87 | |||
| 88 | match = rt_graph_check_server_switch_to(ARGS); | ||
| 89 | if (match && sid == args->match_sid) { | ||
| 90 | /* We must not have been running anything */ | ||
| 91 | (*args->out_job) = job; | ||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | |||
| 95 | #undef ARGS | ||
| 96 | return 1; | ||
| 97 | } | ||
| 98 | |||
| 25 | int get_server_info(struct graph_info *ginfo, struct rt_plot_common *rt, | 99 | int get_server_info(struct graph_info *ginfo, struct rt_plot_common *rt, |
| 26 | int match_sid, unsigned long long time, | 100 | int match_sid, unsigned long long time, |
| 27 | unsigned long long *out_release, | 101 | unsigned long long *out_release, |
| @@ -29,47 +103,19 @@ int get_server_info(struct graph_info *ginfo, struct rt_plot_common *rt, | |||
| 29 | int *out_job, int *out_tid, int *out_tjob, | 103 | int *out_job, int *out_tid, int *out_tjob, |
| 30 | struct record **out_record) | 104 | struct record **out_record) |
| 31 | { | 105 | { |
| 32 | struct record *record; | 106 | struct server_iter_args args = {time, match_sid, |
| 33 | int sid, job, tid, tjob, match, next_cpu, is_running = 0; | 107 | out_job, out_tid, out_tjob, 0}; |
| 34 | unsigned long long when, max_ts; | ||
| 35 | 108 | ||
| 36 | *out_record = find_rt_record(ginfo, rt, time); | 109 | *out_record = find_rt_record(ginfo, rt, time); |
| 37 | if (!(*out_record)) | 110 | if (!*out_record) |
| 38 | return 0; | 111 | return 0; |
| 39 | 112 | ||
| 40 | *out_release = *out_deadline = *out_job = *out_tid = 0; | 113 | *out_release = *out_deadline = *out_job = *out_tid = 0; |
| 41 | 114 | ||
| 42 | /* Get current job info for server task */ | 115 | set_cpus_to_rts(ginfo, time); |
| 43 | get_previous_release(ginfo, rt, sid, time, | 116 | iterate(ginfo, 0, server_iterator, &args); |
| 44 | out_job, out_release, out_deadline); | ||
| 45 | |||
| 46 | /* Need to reset back to current location */ | ||
| 47 | record = find_rt_record(ginfo, rt, time); | ||
| 48 | if (!record) | ||
| 49 | goto out; | ||
| 50 | |||
| 51 | /* TODO: read backwards too */ | ||
| 52 | max_ts = time + max_rt_search(ginfo); | ||
| 53 | do { | ||
| 54 | if (get_rts(ginfo, record) > max_ts) | ||
| 55 | break; | ||
| 56 | |||
| 57 | match = rt_graph_check_server_switch_away(ginfo, record, | ||
| 58 | &sid, &job, &tid, &tjob, | ||
| 59 | &when); | ||
| 60 | if (match && sid == match_sid) { | ||
| 61 | *out_tid = tid; | ||
| 62 | *out_tjob = tjob; | ||
| 63 | is_running = 1; | ||
| 64 | break; | ||
| 65 | } | ||
| 66 | free_record(record); | ||
| 67 | } while ((record = tracecmd_read_next_data(ginfo->handle, &next_cpu))); | ||
| 68 | 117 | ||
| 69 | if (record && record != *out_record) | 118 | return args.is_running; |
| 70 | free_record(record); | ||
| 71 | out: | ||
| 72 | return is_running; | ||
| 73 | } | 119 | } |
| 74 | 120 | ||
| 75 | void rt_plot_container(struct graph_info *ginfo, int cid) | 121 | void rt_plot_container(struct graph_info *ginfo, int cid) |
diff --git a/rt-plot-vcpu.c b/rt-plot-vcpu.c index 8f850b9..e39ae19 100644 --- a/rt-plot-vcpu.c +++ b/rt-plot-vcpu.c | |||
| @@ -13,12 +13,12 @@ | |||
| 13 | #define dprintf(l, x...) do { if (0) printf(x); } while (0) | 13 | #define dprintf(l, x...) do { if (0) printf(x); } while (0) |
| 14 | #endif | 14 | #endif |
| 15 | 15 | ||
| 16 | static void update_tid(struct vcpu_info *info, int tid) | 16 | static void update_label(struct vcpu_info *info, int tid, int tjob) |
| 17 | { | 17 | { |
| 18 | info->fresh = FALSE; | 18 | info->fresh = FALSE; |
| 19 | if (tid != info->run_tid) { | 19 | if (tid != info->run_tid) { |
| 20 | info->run_tid = tid; | 20 | info->run_tid = tid; |
| 21 | snprintf(info->label, LLABEL, "%d", tid); | 21 | snprintf(info->label, LLABEL, "%d:%d", tid, tjob); |
| 22 | } | 22 | } |
| 23 | } | 23 | } |
| 24 | 24 | ||
| @@ -33,7 +33,7 @@ try_server_switch_away(struct graph_info *ginfo, struct vcpu_info *vcpu_info, | |||
| 33 | &sid, &job, | 33 | &sid, &job, |
| 34 | &tid, &tjob, &ts); | 34 | &tid, &tjob, &ts); |
| 35 | if (match && sid == vcpu_info->sid) { | 35 | if (match && sid == vcpu_info->sid) { |
| 36 | update_tid(vcpu_info, tid); | 36 | update_label(vcpu_info, tid, tjob); |
| 37 | 37 | ||
| 38 | if (vcpu_info->run_time && vcpu_info->run_time < ts) { | 38 | if (vcpu_info->run_time && vcpu_info->run_time < ts) { |
| 39 | info->box = TRUE; | 39 | info->box = TRUE; |
| @@ -66,7 +66,7 @@ static int try_server_switch_to(struct graph_info *ginfo, struct vcpu_info *vcpu | |||
| 66 | match = rt_graph_check_server_switch_to(ginfo, record, | 66 | match = rt_graph_check_server_switch_to(ginfo, record, |
| 67 | &sid, &job, &tid, &tjob, &ts); | 67 | &sid, &job, &tid, &tjob, &ts); |
| 68 | if (match && sid == vcpu_info->sid) { | 68 | if (match && sid == vcpu_info->sid) { |
| 69 | update_tid(vcpu_info, tid); | 69 | update_label(vcpu_info, tid, tjob); |
| 70 | vcpu_info->run_time = ts; | 70 | vcpu_info->run_time = ts; |
| 71 | vcpu_info->run_cpu = record->cpu; | 71 | vcpu_info->run_cpu = record->cpu; |
| 72 | vcpu_info->run_tid = tid; | 72 | vcpu_info->run_tid = tid; |
| @@ -151,7 +151,7 @@ static void do_plot_end(struct graph_info *ginfo, struct vcpu_info *vcpu_info, | |||
| 151 | &release, &deadline, | 151 | &release, &deadline, |
| 152 | &job, &tid, &tjob, &record); | 152 | &job, &tid, &tjob, &record); |
| 153 | if (is_running) { | 153 | if (is_running) { |
| 154 | update_tid(vcpu_info, tid); | 154 | update_label(vcpu_info, tid, tjob); |
| 155 | info->box = TRUE; | 155 | info->box = TRUE; |
| 156 | info->bcolor = hash_pid(vcpu_info->run_tid); | 156 | info->bcolor = hash_pid(vcpu_info->run_tid); |
| 157 | info->bfill = is_task_running(ginfo, ginfo->view_end_time, tid); | 157 | info->bfill = is_task_running(ginfo, ginfo->view_end_time, tid); |
| @@ -251,7 +251,7 @@ void rt_vcpu_plot_start(struct graph_info *ginfo, struct graph_plot *plot, | |||
| 251 | vcpu_info->fresh = TRUE; | 251 | vcpu_info->fresh = TRUE; |
| 252 | vcpu_info->running = FALSE; | 252 | vcpu_info->running = FALSE; |
| 253 | vcpu_info->last_job = -1; | 253 | vcpu_info->last_job = -1; |
| 254 | update_tid(vcpu_info, 0); | 254 | update_label(vcpu_info, 0, 0); |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | /** | 257 | /** |
| @@ -276,15 +276,15 @@ int rt_vcpu_plot_record_matches(struct rt_plot_common *rt, | |||
| 276 | int dint, sid, match; | 276 | int dint, sid, match; |
| 277 | unsigned long long dull; | 277 | unsigned long long dull; |
| 278 | 278 | ||
| 279 | #define ARG ginfo, record, &sid | 279 | #define ARG ginfo, record, &sid, &dint |
| 280 | match = rt_graph_check_server_switch_to(ARG, &dint, &dint, &dint, &dull) || | 280 | match = rt_graph_check_server_switch_to(ARG, &dint, &dint, &dull) || |
| 281 | rt_graph_check_server_switch_away(ARG, &dint, &dint, &dint, &dull); | 281 | rt_graph_check_server_switch_away(ARG,&dint, &dint, &dull); |
| 282 | /* rt_graph_check_server_completion(ARG, &dint, &dull) || */ | 282 | rt_graph_check_server_completion(ARG, &dull) || |
| 283 | /* rt_graph_check_server_release(ARG, &dint, &dull, &dull); */ | 283 | rt_graph_check_server_release(ARG, &dull, &dull); |
| 284 | /* rt_graph_check_server_block(ARG, &dull) || */ | 284 | rt_graph_check_server_block(ARG, &dull) || |
| 285 | /* rt_graph_check_server_resume(ARG, &dull); */ | 285 | rt_graph_check_server_resume(ARG, &dull); |
| 286 | #undef ARG | 286 | #undef ARG |
| 287 | return (sid == vcpu_info->sid); | 287 | return (match && sid == vcpu_info->sid); |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | /** | 290 | /** |
| @@ -28,15 +28,15 @@ void insert_record(struct graph_info *ginfo, struct record_list *list, | |||
| 28 | 28 | ||
| 29 | while (pos->next) { | 29 | while (pos->next) { |
| 30 | unsigned long long next_rts = get_rts(ginfo, pos->next->record); | 30 | unsigned long long next_rts = get_rts(ginfo, pos->next->record); |
| 31 | if (( reverse && !next_rts > get_rts(ginfo, record)) || | 31 | if (( reverse && next_rts < get_rts(ginfo, record)) || |
| 32 | (!reverse && next_rts < get_rts(ginfo, record))){ | 32 | (!reverse && next_rts > get_rts(ginfo, record))){ |
| 33 | break; | 33 | break; |
| 34 | } | 34 | } |
| 35 | pos = pos->next; | 35 | pos = pos->next; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | node->next = pos->next; | 38 | node->next = pos->next; |
| 39 | pos->next = node; | 39 | pos->next = node; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | 42 | ||
| @@ -53,7 +53,7 @@ int pop_record(struct graph_info *ginfo, struct record_list *list, | |||
| 53 | list->next = list->next->next; | 53 | list->next = list->next->next; |
| 54 | (*node)->next = 0; | 54 | (*node)->next = 0; |
| 55 | 55 | ||
| 56 | return 1; | 56 | return 1; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | 59 | ||
| @@ -91,7 +91,7 @@ prev_release_iterator(struct graph_info *ginfo, struct record *rec, void *data) | |||
| 91 | *(args->out_job) = job; | 91 | *(args->out_job) = job; |
| 92 | *(args->out_release) = release; | 92 | *(args->out_release) = release; |
| 93 | *(args->out_deadline) = deadline; | 93 | *(args->out_deadline) = deadline; |
| 94 | 94 | ||
| 95 | /* Cache to minimize work later */ | 95 | /* Cache to minimize work later */ |
| 96 | args->common->last_job.no = job; | 96 | args->common->last_job.no = job; |
| 97 | args->common->last_job.release = release; | 97 | args->common->last_job.release = release; |
| @@ -122,14 +122,14 @@ prev_display_iterator(struct graph_info *ginfo, struct record *record, void *dat | |||
| 122 | if (get_rts(ginfo, record) < args->min_ts) { | 122 | if (get_rts(ginfo, record) < args->min_ts) { |
| 123 | return 0; | 123 | return 0; |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | eid = pevent_data_type(ginfo->pevent, record); | 126 | eid = pevent_data_type(ginfo->pevent, record); |
| 127 | ignored = (eid == ginfo->event_sched_switch_id); | 127 | ignored = (eid == ginfo->event_sched_switch_id); |
| 128 | 128 | ||
| 129 | if (!ignored) { | 129 | if (!ignored) { |
| 130 | ignored = args->common->is_drawn(ginfo, eid); | 130 | ignored = args->common->is_drawn(ginfo, eid); |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | if (!ignored && args->common->record_matches(args->common, ginfo, record)) { | 133 | if (!ignored && args->common->record_matches(args->common, ginfo, record)) { |
| 134 | args->result = record; | 134 | args->result = record; |
| 135 | ++record->ref_count; | 135 | ++record->ref_count; |
| @@ -147,8 +147,6 @@ static struct record* | |||
| 147 | find_prev_display_record(struct graph_info *ginfo, struct rt_plot_common *rt_info, | 147 | find_prev_display_record(struct graph_info *ginfo, struct rt_plot_common *rt_info, |
| 148 | unsigned long long time, unsigned long long range) | 148 | unsigned long long time, unsigned long long range) |
| 149 | { | 149 | { |
| 150 | int eid, ignored, match, cpu; | ||
| 151 | struct record *prev, *next, *res = NULL; | ||
| 152 | struct prev_display_args args = {rt_info, NULL, 0}; | 150 | struct prev_display_args args = {rt_info, NULL, 0}; |
| 153 | 151 | ||
| 154 | if (range) { | 152 | if (range) { |
| @@ -342,98 +340,64 @@ rt_plot_match_time(struct graph_info *ginfo, struct graph_plot *plot, | |||
| 342 | return ret; | 340 | return ret; |
| 343 | } | 341 | } |
| 344 | 342 | ||
| 345 | |||
| 346 | |||
| 347 | /** | 343 | /** |
| 348 | * next_rts - find a real-time timestamp AROUND an FTRACE time | 344 | * set_cpu_to_rts - seek CPU to a time closely preceding a real-time timestamp. |
| 349 | * @ginfo: Current state of the graph | ||
| 350 | * @cpu: CPU to search | ||
| 351 | * @ft_target: FTRACE time to seek towards | ||
| 352 | * | ||
| 353 | * Returns the RT time of a record CLOSELY BEFORE @ft_time. | ||
| 354 | */ | ||
| 355 | unsigned long long | ||
| 356 | next_rts(struct graph_info *ginfo, int cpu, unsigned long long ft_target) | ||
| 357 | { | ||
| 358 | struct record *record; | ||
| 359 | unsigned long long ts = 0ULL; | ||
| 360 | tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, ft_target); | ||
| 361 | record = tracecmd_read_data(ginfo->handle, cpu); | ||
| 362 | if (record) { | ||
| 363 | ts = get_rts(ginfo, record); | ||
| 364 | free_record(record); | ||
| 365 | return ts; | ||
| 366 | } else | ||
| 367 | return 0; | ||
| 368 | } | ||
| 369 | |||
| 370 | /** | ||
| 371 | * set_cpu_to_rts - seek CPU to a time closely preceding a real-time timestamp | ||
| 372 | * @ginfo: Current state o the graph | ||
| 373 | * @cpu: The CPU to seek | 345 | * @cpu: The CPU to seek |
| 374 | * @rt_target: RT time to seek towards | 346 | * @rt_target: RT time to seek towards |
| 375 | * | 347 | * |
| 376 | * This seeks to a real-time timestamp, not the default ftrace timestamps. | 348 | * This seeks to a real-time timestamp, not the default ftrace timestamps. |
| 377 | * The @cpu seek location will be placed before the given time, but will | 349 | * The @cpu seek location will be placed on the last record whose timestamp |
| 378 | * not necessarily be placed _right_ before the time. | 350 | * is less than @rt_target. |
| 379 | */ | 351 | */ |
| 380 | unsigned long long | 352 | long long correction = 0; |
| 381 | set_cpu_to_rts(struct graph_info *ginfo, unsigned long long rt_target, int cpu) | 353 | unsigned long long set_cpu_to_rts(struct graph_info *ginfo, |
| 354 | unsigned long long rt_target, int cpu) | ||
| 382 | { | 355 | { |
| 383 | struct record *record; | 356 | struct record *record, *last_record; |
| 384 | unsigned long long last_rts, rts, seek_time, last_seek; | 357 | unsigned long long rts, seek_time; |
| 385 | long long diff; | 358 | long long next_diff; |
| 386 | 359 | ||
| 387 | rts = next_rts(ginfo, cpu, rt_target); | 360 | seek_time = rt_target + correction; |
| 388 | diff = rt_target - rts; | 361 | tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, seek_time); |
| 389 | 362 | ||
| 390 | /* "Guess" a new target based on difference */ | 363 | last_record = tracecmd_read_data(ginfo->handle, cpu); |
| 391 | seek_time = rt_target + diff; | 364 | rts = get_rts(ginfo, last_record); |
| 392 | rts = next_rts(ginfo, cpu, seek_time); | 365 | if (rts < rt_target) { |
| 393 | diff = rt_target - rts; | 366 | while ((record = tracecmd_read_data(ginfo->handle, cpu))) { |
| 394 | 367 | if (get_rts(ginfo, record) >= rt_target) { | |
| 395 | /* Zero in in 1.5x the difference increments */ | 368 | free_record(record); |
| 396 | if (rts && diff > 0) { | 369 | break; |
| 397 | /* rts rt_target | real-time time | 370 | } |
| 398 | * seek ? | trace-cmd time | 371 | free_record(last_record); |
| 399 | * ---|---->>----|-------- | 372 | last_record = record; |
| 400 | */ | 373 | } |
| 401 | do { | 374 | } else if (rts > rt_target) { |
| 402 | last_seek = seek_time; | 375 | while ((record = tracecmd_read_prev(ginfo->handle, last_record))) { |
| 403 | last_rts = rts; | 376 | if (get_rts(ginfo, record) <= rt_target) { |
| 404 | seek_time = seek_time + 1.5 * (rt_target - rts); | 377 | free_record(last_record); |
| 405 | rts = next_rts(ginfo, cpu, seek_time); | 378 | last_record = record; |
| 406 | } while (rts < rt_target && last_rts != rts); | 379 | break; |
| 407 | tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, last_seek); | 380 | } |
| 408 | seek_time = last_seek; | 381 | free_record(last_record); |
| 409 | } else if (rts && diff < 0) { | 382 | last_record = record; |
| 410 | /* rt_target rts | real-time time | 383 | } |
| 411 | * ? seek | trace-cmd time | ||
| 412 | * ---|----<<----|-------- | ||
| 413 | */ | ||
| 414 | do { | ||
| 415 | seek_time = seek_time - 1.5 * (rts - rt_target); | ||
| 416 | last_rts = rts; | ||
| 417 | rts = next_rts(ginfo, cpu, seek_time); | ||
| 418 | } while (rts > rt_target && rts != last_rts); | ||
| 419 | } | 384 | } |
| 420 | 385 | ||
| 421 | /* Get to first record at or after time */ | 386 | if (last_record) { |
| 422 | while ((record = tracecmd_read_data(ginfo->handle, cpu))) { | 387 | next_diff = (last_record->ts - rt_target); |
| 423 | if (get_rts(ginfo, record) >= rt_target) | 388 | if (correction) |
| 424 | break; | 389 | correction = correction *3/ 4 + (next_diff) / 4; |
| 425 | free_record(record); | 390 | else |
| 391 | correction = next_diff; | ||
| 392 | tracecmd_set_cursor(ginfo->handle, cpu, last_record->offset); | ||
| 393 | free_record(last_record); | ||
| 426 | } | 394 | } |
| 427 | if (record) { | 395 | |
| 428 | tracecmd_set_cursor(ginfo->handle, cpu, record->offset); | ||
| 429 | free_record(record); | ||
| 430 | } else | ||
| 431 | tracecmd_set_cpu_to_timestamp(ginfo->handle, cpu, seek_time); | ||
| 432 | return rts; | 396 | return rts; |
| 433 | } | 397 | } |
| 434 | 398 | ||
| 435 | /** | 399 | /** |
| 436 | * set_cpus_to_time - seek all cpus to real-time @rt_target | 400 | * set_cpus_to_time - seek all cpus to real-time @rt_target. |
| 437 | */ | 401 | */ |
| 438 | unsigned long long set_cpus_to_rts(struct graph_info *ginfo, unsigned long long rt_target) | 402 | unsigned long long set_cpus_to_rts(struct graph_info *ginfo, unsigned long long rt_target) |
| 439 | { | 403 | { |
| @@ -491,6 +455,9 @@ int is_task_running(struct graph_info *ginfo, | |||
| 491 | return running; | 455 | return running; |
| 492 | } | 456 | } |
| 493 | 457 | ||
| 458 | /** | ||
| 459 | * iterate - pass records in real-time timestamp order to @cb. | ||
| 460 | */ | ||
| 494 | void iterate(struct graph_info *ginfo, int reverse, iterate_cb cb, void *data) | 461 | void iterate(struct graph_info *ginfo, int reverse, iterate_cb cb, void *data) |
| 495 | { | 462 | { |
| 496 | int proceed, cpu; | 463 | int proceed, cpu; |
| @@ -502,47 +469,48 @@ void iterate(struct graph_info *ginfo, int reverse, iterate_cb cb, void *data) | |||
| 502 | memset(nodes, 0, sizeof(*nodes) * ginfo->cpus); | 469 | memset(nodes, 0, sizeof(*nodes) * ginfo->cpus); |
| 503 | memset(&list, 0, sizeof(list)); | 470 | memset(&list, 0, sizeof(list)); |
| 504 | 471 | ||
| 505 | /* Maintains a list of the next record on each cpu, sorted by | 472 | /* Start with the first record on each CPU */ |
| 506 | * timestamp. Start with the first record on each cpu. | ||
| 507 | */ | ||
| 508 | for (cpu = 0; cpu < ginfo->cpus; cpu++) { | 473 | for (cpu = 0; cpu < ginfo->cpus; cpu++) { |
| 509 | next = tracecmd_peek_data(ginfo->handle, cpu); | 474 | next = tracecmd_peek_data(ginfo->handle, cpu); |
| 510 | if (next) { | 475 | if (next) { |
| 511 | if (reverse) { | 476 | if (reverse) { |
| 477 | /* Reading backwards is clumsy...*/ | ||
| 512 | prev = next; | 478 | prev = next; |
| 513 | next = tracecmd_read_prev(ginfo->handle, prev); | 479 | next = tracecmd_read_prev(ginfo->handle, prev); |
| 514 | if (prev != next && prev->data) { | 480 | if (prev != next && prev->data) |
| 515 | free_record(prev); | 481 | free_record(prev); |
| 516 | } | 482 | } else { |
| 483 | next = tracecmd_read_data(ginfo->handle, cpu); | ||
| 517 | } | 484 | } |
| 518 | insert_record(ginfo, &list, next, &nodes[cpu], reverse); | 485 | insert_record(ginfo, &list, next, &nodes[cpu], reverse); |
| 519 | } | 486 | } |
| 520 | } | 487 | } |
| 521 | 488 | ||
| 522 | /* Read sequentially from all cpus */ | 489 | /* Read record with the next timestamp until the callback is finished |
| 490 | * consuming data | ||
| 491 | */ | ||
| 523 | while (pop_record(ginfo, &list, &node)) { | 492 | while (pop_record(ginfo, &list, &node)) { |
| 524 | next = node->record; | 493 | next = node->record; |
| 525 | 494 | ||
| 495 | /* Pass records into callback */ | ||
| 526 | proceed = cb(ginfo, next, data); | 496 | proceed = cb(ginfo, next, data); |
| 527 | |||
| 528 | if (!proceed) { | 497 | if (!proceed) { |
| 529 | free_record(next); | 498 | free_record(next); |
| 530 | break; | 499 | break; |
| 531 | } | 500 | } |
| 532 | 501 | ||
| 502 | /* Replace this record with the next record from the same CPU */ | ||
| 533 | prev = next; | 503 | prev = next; |
| 534 | 504 | if (!reverse) | |
| 535 | if (!reverse) { | ||
| 536 | next = tracecmd_read_data(ginfo->handle, next->cpu); | 505 | next = tracecmd_read_data(ginfo->handle, next->cpu); |
| 537 | } else { | 506 | else |
| 538 | next = tracecmd_read_prev(ginfo->handle, next); | 507 | next = tracecmd_read_prev(ginfo->handle, next); |
| 539 | } | ||
| 540 | |||
| 541 | free_record(prev); | 508 | free_record(prev); |
| 542 | 509 | if (prev != next) | |
| 543 | insert_record(ginfo, &list, next, node, reverse); | 510 | insert_record(ginfo, &list, next, node, reverse); |
| 544 | } | 511 | } |
| 545 | 512 | ||
| 513 | /* Free unused records */ | ||
| 546 | while (pop_record(ginfo, &list, &node)) { | 514 | while (pop_record(ginfo, &list, &node)) { |
| 547 | free_record(node->record); | 515 | free_record(node->record); |
| 548 | } | 516 | } |
| @@ -550,7 +518,7 @@ void iterate(struct graph_info *ginfo, int reverse, iterate_cb cb, void *data) | |||
| 550 | 518 | ||
| 551 | 519 | ||
| 552 | /** | 520 | /** |
| 553 | * Find the information for the last release of @match_tid on @cpu before @time. | 521 | * get_previous_release - return stats for the latest release of @match_tid |
| 554 | * | 522 | * |
| 555 | * This method will NOT re-seek the CPUs near time. The caller must have placed | 523 | * This method will NOT re-seek the CPUs near time. The caller must have placed |
| 556 | * the CPUs near the the CPUs themselves. | 524 | * the CPUs near the the CPUs themselves. |
| @@ -68,7 +68,7 @@ find_rt_display_record(struct graph_info *ginfo, | |||
| 68 | return __find_rt_record(ginfo, rt, time, 1, 0); | 68 | return __find_rt_record(ginfo, rt, time, 1, 0); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | unsigned long long next_rts(struct graph_info *ginfo, int cpu, | 71 | long long next_rts(struct graph_info *ginfo, int cpu, |
| 72 | unsigned long long ft_target); | 72 | unsigned long long ft_target); |
| 73 | unsigned long long set_cpu_to_rts(struct graph_info *ginfo, | 73 | unsigned long long set_cpu_to_rts(struct graph_info *ginfo, |
| 74 | unsigned long long rt_target, int cpu); | 74 | unsigned long long rt_target, int cpu); |
diff --git a/trace-dialog.c b/trace-dialog.c index 4e1d6e2..00ab269 100644 --- a/trace-dialog.c +++ b/trace-dialog.c | |||
| @@ -183,7 +183,6 @@ void warning(const char *fmt, ...) | |||
| 183 | { | 183 | { |
| 184 | GString *str; | 184 | GString *str; |
| 185 | va_list ap; | 185 | va_list ap; |
| 186 | int err; | ||
| 187 | 186 | ||
| 188 | if (alt_warning) { | 187 | if (alt_warning) { |
| 189 | va_start(ap, fmt); | 188 | va_start(ap, fmt); |
| @@ -199,7 +198,6 @@ void warning(const char *fmt, ...) | |||
| 199 | return; | 198 | return; |
| 200 | } | 199 | } |
| 201 | 200 | ||
| 202 | err = errno; | ||
| 203 | errno = 0; | 201 | errno = 0; |
| 204 | 202 | ||
| 205 | str = g_string_new(""); | 203 | str = g_string_new(""); |
diff --git a/trace-graph.c b/trace-graph.c index 69f5069..0aa8137 100644 --- a/trace-graph.c +++ b/trace-graph.c | |||
| @@ -1852,14 +1852,16 @@ static void draw_plot(struct graph_info *ginfo, struct graph_plot *plot, | |||
| 1852 | } | 1852 | } |
| 1853 | 1853 | ||
| 1854 | /* | 1854 | /* |
| 1855 | * TODO: this method needs refactoring and splitting | 1855 | * TODO: this method needs refactoring and splitting. |
| 1856 | * Containers currently aren't using hashing, which can significantly affect | ||
| 1857 | * performance if enough containers are being rendered. | ||
| 1856 | */ | 1858 | */ |
| 1857 | static void draw_hashed_plots(struct graph_info *ginfo) | 1859 | static void draw_hashed_plots(struct graph_info *ginfo) |
| 1858 | { | 1860 | { |
| 1859 | gint cpu, pid, clean; | 1861 | gint cpu, pid, clean; |
| 1860 | struct record *record; | 1862 | struct record *record; |
| 1861 | struct plot_hash *hash; | ||
| 1862 | struct plot_list *list; | 1863 | struct plot_list *list; |
| 1864 | struct plot_hash *hash; | ||
| 1863 | unsigned long long max_time, min_time; | 1865 | unsigned long long max_time, min_time; |
| 1864 | gdouble start, duration; | 1866 | gdouble start, duration; |
| 1865 | 1867 | ||
| @@ -1940,19 +1942,19 @@ static void draw_hashed_plots(struct graph_info *ginfo) | |||
| 1940 | } | 1942 | } |
| 1941 | 1943 | ||
| 1942 | 1944 | ||
| 1943 | /* hash = trace_graph_plot_find_cpu(ginfo, cpu); */ | 1945 | hash = trace_graph_plot_find_cpu(ginfo, cpu); |
| 1944 | /* if (hash) { */ | 1946 | if (hash) { |
| 1945 | /* for (list = hash->plots; list; list = list->next) { */ | 1947 | for (list = hash->plots; list; list = list->next) { |
| 1946 | /* draw_plot(ginfo, list->plot, record); */ | 1948 | draw_plot(ginfo, list->plot, record); |
| 1947 | /* } */ | 1949 | } |
| 1948 | /* } */ | 1950 | } |
| 1949 | /* pid = pevent_data_pid(ginfo->pevent, record); */ | 1951 | pid = pevent_data_pid(ginfo->pevent, record); |
| 1950 | /* hash = trace_graph_plot_find_task(ginfo, pid); */ | 1952 | hash = trace_graph_plot_find_task(ginfo, pid); |
| 1951 | /* if (hash) { */ | 1953 | if (hash) { |
| 1952 | /* for (list = hash->plots; list; list = list->next) { */ | 1954 | for (list = hash->plots; list; list = list->next) { |
| 1953 | /* draw_plot(ginfo, list->plot, record); */ | 1955 | draw_plot(ginfo, list->plot, record); |
| 1954 | /* } */ | 1956 | } |
| 1955 | /* } */ | 1957 | } |
| 1956 | for (list = ginfo->all_recs; list; list = list->next) { | 1958 | for (list = ginfo->all_recs; list; list = list->next) { |
| 1957 | /* TODO: hacky assumption that everything else can be | 1959 | /* TODO: hacky assumption that everything else can be |
| 1958 | * reached via previous hashes | 1960 | * reached via previous hashes |
| @@ -1960,10 +1962,10 @@ static void draw_hashed_plots(struct graph_info *ginfo) | |||
| 1960 | * added with arbitrary numbers, and a pevent_other_id | 1962 | * added with arbitrary numbers, and a pevent_other_id |
| 1961 | * which uses id ranges x < . < y to parse cids or lids | 1963 | * which uses id ranges x < . < y to parse cids or lids |
| 1962 | */ | 1964 | */ |
| 1963 | /* if (list->plot->type == PLOT_TYPE_SERVER_TASK || */ | 1965 | if (list->plot->type == PLOT_TYPE_SERVER_TASK || |
| 1964 | /* list->plot->type == PLOT_TYPE_SERVER_CPU) { */ | 1966 | list->plot->type == PLOT_TYPE_SERVER_CPU) { |
| 1965 | draw_plot(ginfo, list->plot, record); | 1967 | draw_plot(ginfo, list->plot, record); |
| 1966 | /* } */ | 1968 | } |
| 1967 | } | 1969 | } |
| 1968 | free_record(record); | 1970 | free_record(record); |
| 1969 | } | 1971 | } |
