diff options
Diffstat (limited to 'trace-view-store.c')
-rw-r--r-- | trace-view-store.c | 221 |
1 files changed, 217 insertions, 4 deletions
diff --git a/trace-view-store.c b/trace-view-store.c index be86662..9ad2073 100644 --- a/trace-view-store.c +++ b/trace-view-store.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include "trace-view-store.h" | 1 | #include "trace-view-store.h" |
2 | #include <stdlib.h> | 2 | #include <stdlib.h> |
3 | #include <string.h> | ||
3 | 4 | ||
4 | #include "cpu.h" | 5 | #include "cpu.h" |
5 | 6 | ||
@@ -207,6 +208,8 @@ trace_view_store_finalize (GObject *object) | |||
207 | g_free(store->rows); | 208 | g_free(store->rows); |
208 | g_free(store->cpu_items); | 209 | g_free(store->cpu_items); |
209 | 210 | ||
211 | filter_task_hash_free(store->task_filter); | ||
212 | |||
210 | if (store->spin) { | 213 | if (store->spin) { |
211 | gtk_widget_destroy(store->spin); | 214 | gtk_widget_destroy(store->spin); |
212 | store->spin = NULL; | 215 | store->spin = NULL; |
@@ -490,6 +493,183 @@ trace_view_store_get_value (GtkTreeModel *tree_model, | |||
490 | } | 493 | } |
491 | } | 494 | } |
492 | 495 | ||
496 | int str_cmp(const void *a, const void *b) | ||
497 | { | ||
498 | char * const * sa = a; | ||
499 | char * const * sb = b; | ||
500 | |||
501 | return strcmp(*sa, *sb); | ||
502 | } | ||
503 | |||
504 | int id_cmp(const void *a, const void *b) | ||
505 | { | ||
506 | const gint *ia = a; | ||
507 | const gint *ib = b; | ||
508 | |||
509 | if (*ia > *ib) | ||
510 | return 1; | ||
511 | if (*ia < *ib) | ||
512 | return -1; | ||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | gboolean trace_view_store_system_enabled(TraceViewStore *store, const gchar *system) | ||
517 | { | ||
518 | const gchar **sys = &system; | ||
519 | |||
520 | g_return_val_if_fail (TRACE_VIEW_IS_LIST (store), FALSE); | ||
521 | |||
522 | if (store->all_events) | ||
523 | return TRUE; | ||
524 | |||
525 | if (!store->systems) | ||
526 | return FALSE; | ||
527 | |||
528 | sys = bsearch(sys, store->systems, store->systems_size, | ||
529 | sizeof(system), str_cmp); | ||
530 | |||
531 | return sys != NULL; | ||
532 | } | ||
533 | |||
534 | gboolean trace_view_store_event_enabled(TraceViewStore *store, gint event_id) | ||
535 | { | ||
536 | gint key = event_id; | ||
537 | gint *ret; | ||
538 | |||
539 | g_return_val_if_fail (TRACE_VIEW_IS_LIST (store), FALSE); | ||
540 | |||
541 | if (store->all_events) | ||
542 | return TRUE; | ||
543 | |||
544 | /* TODO: search for the system of the event? */ | ||
545 | |||
546 | if (!store->event_types) | ||
547 | return FALSE; | ||
548 | |||
549 | ret = bsearch(&key, store->event_types, store->event_types_size, | ||
550 | sizeof(gint), id_cmp); | ||
551 | |||
552 | return ret != NULL; | ||
553 | } | ||
554 | |||
555 | void trace_view_store_set_all_events_enabled(TraceViewStore *store) | ||
556 | { | ||
557 | gint i; | ||
558 | |||
559 | g_return_if_fail (TRACE_VIEW_IS_LIST (store)); | ||
560 | |||
561 | if (store->all_events) | ||
562 | return; | ||
563 | |||
564 | if (store->systems_size) { | ||
565 | for (i = 0; i < store->systems_size; i++) | ||
566 | g_free(store->systems[i]); | ||
567 | |||
568 | g_free(store->systems); | ||
569 | store->systems = NULL; | ||
570 | store->systems_size = 0; | ||
571 | } | ||
572 | |||
573 | g_free(store->event_types); | ||
574 | store->event_types = NULL; | ||
575 | store->event_types_size = 0; | ||
576 | |||
577 | store->all_events = 1; | ||
578 | } | ||
579 | |||
580 | static void remove_system(TraceViewStore *store, const gchar *system) | ||
581 | { | ||
582 | const gchar **sys = &system; | ||
583 | |||
584 | if (!store->systems) | ||
585 | return; | ||
586 | |||
587 | sys = bsearch(sys, store->systems, store->systems_size, | ||
588 | sizeof(system), str_cmp); | ||
589 | |||
590 | if (!sys) | ||
591 | return; | ||
592 | |||
593 | g_free(*((gchar **)sys)); | ||
594 | |||
595 | g_memmove(sys, sys+1, sizeof(*sys) * (store->systems_size - | ||
596 | ((gchar **)sys - store->systems))); | ||
597 | store->systems_size--; | ||
598 | store->systems[store->systems_size] = NULL; | ||
599 | } | ||
600 | |||
601 | void trace_view_store_set_system_enabled(TraceViewStore *store, const gchar *system) | ||
602 | { | ||
603 | g_return_if_fail (TRACE_VIEW_IS_LIST (store)); | ||
604 | |||
605 | if (store->all_events) | ||
606 | /* | ||
607 | * We are adding a new filter, so this is the | ||
608 | * only system enabled. | ||
609 | */ | ||
610 | store->all_events = 0; | ||
611 | |||
612 | if (trace_view_store_system_enabled(store, system)) | ||
613 | return; | ||
614 | |||
615 | if (!store->systems) { | ||
616 | store->systems = g_new0(gchar *, 2); | ||
617 | store->systems[0] = g_strdup(system); | ||
618 | store->systems_size++; | ||
619 | return; | ||
620 | } | ||
621 | |||
622 | store->systems_size++; | ||
623 | store->systems = g_realloc(store->systems, | ||
624 | sizeof(*store->systems) * (store->systems_size+1)); | ||
625 | store->systems[store->systems_size - 1] = g_strdup(system); | ||
626 | store->systems[store->systems_size] = NULL; | ||
627 | |||
628 | qsort(store->systems, store->systems_size, sizeof(gchar *), str_cmp); | ||
629 | } | ||
630 | |||
631 | |||
632 | void trace_view_store_set_event_enabled(TraceViewStore *store, gint event_id) | ||
633 | { | ||
634 | struct pevent *pevent; | ||
635 | struct event_format *event; | ||
636 | |||
637 | g_return_if_fail (TRACE_VIEW_IS_LIST (store)); | ||
638 | |||
639 | pevent = tracecmd_get_pevent(store->handle); | ||
640 | event = pevent_find_event(pevent, event_id); | ||
641 | if (!event) | ||
642 | return; | ||
643 | |||
644 | if (store->all_events) | ||
645 | /* | ||
646 | * We are adding a new filter, so this is the | ||
647 | * only system enabled. | ||
648 | */ | ||
649 | store->all_events = 0; | ||
650 | |||
651 | remove_system(store, event->system); | ||
652 | |||
653 | if (trace_view_store_event_enabled(store, event_id)) | ||
654 | return; | ||
655 | |||
656 | if (!store->event_types) { | ||
657 | store->event_types = g_new0(gint, 2); | ||
658 | store->event_types[0] = event_id; | ||
659 | store->event_types[1] = -1; | ||
660 | store->event_types_size++; | ||
661 | return; | ||
662 | } | ||
663 | |||
664 | store->event_types_size++; | ||
665 | store->event_types = g_realloc(store->event_types, | ||
666 | sizeof(*store->event_types) * (store->event_types_size+1)); | ||
667 | store->event_types[store->event_types_size - 1] = event_id; | ||
668 | store->event_types[store->event_types_size] = -1; | ||
669 | |||
670 | qsort(store->event_types, store->event_types_size, sizeof(gint), id_cmp); | ||
671 | } | ||
672 | |||
493 | 673 | ||
494 | /***************************************************************************** | 674 | /***************************************************************************** |
495 | * | 675 | * |
@@ -1059,7 +1239,7 @@ gint get_next_pid(TraceViewStore *store, struct pevent *pevent, struct record *r | |||
1059 | unsigned long long val; | 1239 | unsigned long long val; |
1060 | int ret; | 1240 | int ret; |
1061 | 1241 | ||
1062 | ret = pevent_read_number_field(store->sched_switch_next_field, record, &val); | 1242 | ret = pevent_read_number_field(store->sched_switch_next_field, record->data, &val); |
1063 | 1243 | ||
1064 | return val; | 1244 | return val; |
1065 | } | 1245 | } |
@@ -1067,14 +1247,23 @@ gint get_next_pid(TraceViewStore *store, struct pevent *pevent, struct record *r | |||
1067 | void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *filter) | 1247 | void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *filter) |
1068 | { | 1248 | { |
1069 | struct tracecmd_input *handle; | 1249 | struct tracecmd_input *handle; |
1250 | struct event_format *event; | ||
1070 | struct pevent *pevent; | 1251 | struct pevent *pevent; |
1071 | struct record *record; | 1252 | struct record *record; |
1253 | gint last_event_id = -1; | ||
1254 | gint event_id; | ||
1072 | gint pid; | 1255 | gint pid; |
1073 | gint cpu; | 1256 | gint cpu; |
1074 | gint i; | 1257 | gint i; |
1075 | 1258 | ||
1076 | g_return_if_fail (TRACE_VIEW_IS_LIST (store)); | 1259 | g_return_if_fail (TRACE_VIEW_IS_LIST (store)); |
1077 | 1260 | ||
1261 | /* We may pass in the store->task_filter. Don't free it if we do */ | ||
1262 | if (store->task_filter && store->task_filter != filter) | ||
1263 | filter_task_hash_free(store->task_filter); | ||
1264 | |||
1265 | store->task_filter = filter_task_hash_copy(filter); | ||
1266 | |||
1078 | handle = store->handle; | 1267 | handle = store->handle; |
1079 | pevent = tracecmd_get_pevent(store->handle); | 1268 | pevent = tracecmd_get_pevent(store->handle); |
1080 | 1269 | ||
@@ -1094,7 +1283,22 @@ void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *fi | |||
1094 | 1283 | ||
1095 | g_assert(record->offset == store->cpu_list[cpu][i].offset); | 1284 | g_assert(record->offset == store->cpu_list[cpu][i].offset); |
1096 | 1285 | ||
1097 | /* TODO: put event filter check here */ | 1286 | /* The record may be filtered by the events */ |
1287 | if (!store->all_events) { | ||
1288 | event_id = pevent_data_type(pevent, record); | ||
1289 | if (last_event_id != event_id) { | ||
1290 | /* optimize: only search event when new */ | ||
1291 | event = pevent_find_event(pevent, event_id); | ||
1292 | g_assert(event); | ||
1293 | } | ||
1294 | last_event_id = event_id; | ||
1295 | if (!trace_view_store_system_enabled(store, event->system) && | ||
1296 | !trace_view_store_event_enabled(store, event_id)) { | ||
1297 | store->cpu_list[cpu][i].visible = 0; | ||
1298 | goto skip; | ||
1299 | } | ||
1300 | } | ||
1301 | |||
1098 | pid = pevent_data_pid(pevent, record); | 1302 | pid = pevent_data_pid(pevent, record); |
1099 | if (!filter || filter_task_find_pid(filter, pid)) | 1303 | if (!filter || filter_task_find_pid(filter, pid)) |
1100 | store->cpu_list[cpu][i].visible = 1; | 1304 | store->cpu_list[cpu][i].visible = 1; |
@@ -1108,10 +1312,11 @@ void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *fi | |||
1108 | store->cpu_list[cpu][i].visible = 1; | 1312 | store->cpu_list[cpu][i].visible = 1; |
1109 | else | 1313 | else |
1110 | store->cpu_list[cpu][i].visible = 0; | 1314 | store->cpu_list[cpu][i].visible = 0; |
1111 | } | 1315 | } else |
1112 | store->cpu_list[cpu][i].visible = 0; | 1316 | store->cpu_list[cpu][i].visible = 0; |
1113 | } | 1317 | } |
1114 | 1318 | ||
1319 | skip: | ||
1115 | free_record(record); | 1320 | free_record(record); |
1116 | record = tracecmd_read_data(handle, cpu); | 1321 | record = tracecmd_read_data(handle, cpu); |
1117 | } | 1322 | } |
@@ -1121,6 +1326,14 @@ void trace_view_store_filter_tasks(TraceViewStore *store, struct filter_task *fi | |||
1121 | merge_sort_rows_ts(store); | 1326 | merge_sort_rows_ts(store); |
1122 | } | 1327 | } |
1123 | 1328 | ||
1329 | void trace_view_store_update_filter(TraceViewStore *store) | ||
1330 | { | ||
1331 | g_return_if_fail (TRACE_VIEW_IS_LIST (store)); | ||
1332 | |||
1333 | trace_view_store_filter_tasks(store, store->task_filter); | ||
1334 | } | ||
1335 | |||
1336 | |||
1124 | /***************************************************************************** | 1337 | /***************************************************************************** |
1125 | * | 1338 | * |
1126 | * trace_view_store_append_record: Empty lists are boring. This function can | 1339 | * trace_view_store_append_record: Empty lists are boring. This function can |