static void save_events(struct trace_capture *cap, struct tracecmd_xml_handle *handle) { struct pevent *pevent = cap->pevent; struct event_format *event; char **systems = cap->info->cap_systems; int *events = cap->info->cap_events; int i; tracecmd_xml_write_element(handle, "CaptureType", "Events"); for (i = 0; systems && systems[i]; i++) tracecmd_xml_write_element(handle, "System", systems[i]); if (!events || events[0] < 0) return; tracecmd_xml_start_sub_system(handle, "Events"); for (i = 0; events[i] > 0; i++) { event = pevent_find_event(pevent, events[i]); if (event) { tracecmd_xml_start_sub_system(handle, "Event"); tracecmd_xml_write_element(handle, "System", event->system); tracecmd_xml_write_element(handle, "Name", event->name); tracecmd_xml_end_sub_system(handle); } } tracecmd_xml_end_sub_system(handle); }
struct event_format *trace_event__tp_format_id(int id) { if (!tevent_initialized && trace_event__init2()) return ERR_PTR(-ENOMEM); return pevent_find_event(tevent.pevent, id); }
void print_trace_event(struct pevent *pevent, int cpu, void *data, int size) { int type = trace_parse_common_type(pevent, data); struct event_format *event = pevent_find_event(pevent, type); if (!event) { warning("ug! no event found for type %d", type); return; } event_format__print(event, cpu, data, size); }
static int add_trace_cmd_words(struct trace_capture *cap, char **args) { struct event_format *event; char **systems = cap->info->cap_systems; const gchar *output; int *events = cap->info->cap_events; int words = 0; int len; int i; output = gtk_entry_get_text(GTK_ENTRY(cap->file_entry)); args[words++] = find_tracecmd(); if (!args[0]) return -1; args[words++] = strdup("record"); args[words++] = strdup("-o"); args[words++] = strdup(output); if (cap->info->cap_plugin) { args[words++] = strdup("-p"); args[words++] = strdup(cap->info->cap_plugin); } if (cap->info->cap_all_events) { args[words++] = strdup("-e"); args[words++] = strdup("all"); } else { if (systems) { for (i = 0; systems[i]; i++) { args[words++] = strdup("-e"); args[words++] = strdup(systems[i]); } } if (events) { for (i = 0; events[i] >= 0; i++) { event = pevent_find_event(cap->pevent, events[i]); if (!event) continue; args[words++] = strdup("-e"); len = strlen(event->name) + strlen(event->system) + 2; args[words] = malloc_or_die(len); snprintf(args[words++], len, "%s:%s", event->system, event->name); } } } return words; }
static inline struct event_format *find_cache_event(struct pevent *pevent, int type) { static char ev_name[256]; struct event_format *event; if (events[type]) return events[type]; events[type] = event = pevent_find_event(pevent, type); if (!event) return NULL; sprintf(ev_name, "%s__%s", event->system, event->name); define_event_symbols(event, ev_name, event->print_fmt.args); return event; }
void print_trace_event(struct pevent *pevent, int cpu, void *data, int size) { struct event_format *event; struct pevent_record record; struct trace_seq s; int type; type = trace_parse_common_type(pevent, data); event = pevent_find_event(pevent, type); if (!event) { warning("ug! no event found for type %d", type); return; } memset(&record, 0, sizeof(record)); record.cpu = cpu; record.size = size; record.data = data; trace_seq_init(&s); pevent_event_info(&s, event, &record); trace_seq_do_printf(&s); }
static struct filter_type * add_filter_type(struct event_filter *filter, int id) { struct filter_type *filter_type; int i; filter_type = find_filter_type(filter, id); if (filter_type) return filter_type; filter->event_filters = realloc(filter->event_filters, sizeof(*filter->event_filters) * (filter->filters + 1)); if (!filter->event_filters) die("Could not allocate filter"); for (i = 0; i < filter->filters; i++) { if (filter->event_filters[i].event_id > id) break; } if (i < filter->filters) memmove(&filter->event_filters[i+1], &filter->event_filters[i], sizeof(*filter->event_filters) * (filter->filters - i)); filter_type = &filter->event_filters[i]; filter_type->event_id = id; filter_type->event = pevent_find_event(filter->pevent, id); filter_type->filter = NULL; filter->filters++; return filter_type; }
void perf_power_bundle::handle_trace_point(void *trace, int cpunr, uint64_t time) { struct event_format *event; struct pevent_record rec; /* holder */ class abstract_cpu *cpu; int type; rec.data = trace; type = pevent_data_type(perf_event::pevent, &rec); event = pevent_find_event(perf_event::pevent, type); if (!event) return; if (cpunr >= (int)all_cpus.size()) { cout << "INVALID cpu nr in handle_trace_point\n"; return; } cpu = all_cpus[cpunr]; #if 0 unsigned int i; printf("Time is %llu \n", time); for (i = 0; i < system_level.children.size(); i++) if (system_level.children[i]) system_level.children[i]->validate(); #endif unsigned long long val; int ret; if (strcmp(event->name, "cpu_idle")==0) { ret = pevent_get_field_val(NULL, event, "state", &rec, &val, 0); if (ret < 0) { fprintf(stderr, _("cpu_idle event returned no state?\n")); exit(-1); } if (val == 4294967295) cpu->go_unidle(time); else cpu->go_idle(time); } if (strcmp(event->name, "power_frequency") == 0 || strcmp(event->name, "cpu_frequency") == 0){ ret = pevent_get_field_val(NULL, event, "state", &rec, &val, 0); if (ret < 0) { fprintf(stderr, _("power or cpu_frequecny event returned no state?\n")); exit(-1); } cpu->change_freq(time, val); } if (strcmp(event->name, "power_start")==0) cpu->go_idle(time); if (strcmp(event->name, "power_end")==0) cpu->go_unidle(time); #if 0 unsigned int i; for (i = 0; i < system_level.children.size(); i++) if (system_level.children[i]) system_level.children[i]->validate(); #endif }
void perf_process_bundle::handle_trace_point(void *trace, int cpu, uint64_t time) { struct event_format *event; struct pevent_record rec; /* holder */ struct format_field *field; unsigned long long val; int type; int ret; rec.data = trace; type = pevent_data_type(perf_event::pevent, &rec); event = pevent_find_event(perf_event::pevent, type); if (!event) return; if (time < first_stamp) first_stamp = time; if (time > last_stamp) { last_stamp = time; measurement_time = (0.0001 + last_stamp - first_stamp) / 1000000000 ; } if (strcmp(event->name, "sched_switch") == 0) { class process *old_proc = NULL; class process *new_proc = NULL; const char *next_comm; int next_pid; int prev_pid; field = pevent_find_any_field(event, "next_comm"); if (!field || !(field->flags & FIELD_IS_STRING)) return; /* ?? */ next_comm = get_pevent_field_str(trace, event, field); ret = pevent_get_field_val(NULL, event, "next_pid", &rec, &val, 0); if (ret < 0) return; next_pid = (int)val; ret = pevent_get_field_val(NULL, event, "prev_pid", &rec, &val, 0); if (ret < 0) return; prev_pid = (int)val; /* find new process pointer */ new_proc = find_create_process(next_comm, next_pid); /* find the old process pointer */ while (consumer_depth(cpu) > 1) { pop_consumer(cpu); } if (consumer_depth(cpu) == 1) old_proc = (class process *)current_consumer(cpu); if (old_proc && strcmp(old_proc->name(), "process")) old_proc = NULL; /* retire the old process */ if (old_proc) { old_proc->deschedule_thread(time, prev_pid); old_proc->waker = NULL; } if (consumer_depth(cpu)) pop_consumer(cpu); push_consumer(cpu, new_proc); /* start new process */ new_proc->schedule_thread(time, next_pid); if (strncmp(next_comm,"migration/", 10) && strncmp(next_comm,"kworker/", 8) && strncmp(next_comm, "kondemand/",10)) { if (next_pid) { /* If someone woke us up.. blame him instead */ if (new_proc->waker) { change_blame(cpu, new_proc->waker, LEVEL_PROCESS); } else { change_blame(cpu, new_proc, LEVEL_PROCESS); } } consume_blame(cpu); } new_proc->waker = NULL; } else if (strcmp(event->name, "sched_wakeup") == 0) { class power_consumer *from = NULL; class process *dest_proc = NULL; class process *from_proc = NULL; const char *comm; int flags; int pid; ret = pevent_get_common_field_val(NULL, event, "common_flags", &rec, &val, 0); if (ret < 0) return; flags = (int)val; if ( (flags & TRACE_FLAG_HARDIRQ) || (flags & TRACE_FLAG_SOFTIRQ)) { class timer *timer; timer = (class timer *) current_consumer(cpu); if (timer && strcmp(timer->name(), "timer")==0) { if (strcmp(timer->handler, "delayed_work_timer_fn") && strcmp(timer->handler, "hrtimer_wakeup") && strcmp(timer->handler, "it_real_fn")) from = timer; } /* woken from interrupt */ /* TODO: find the current irq handler and set "from" to that */ } else { from = current_consumer(cpu); } field = pevent_find_any_field(event, "comm"); if (!field || !(field->flags & FIELD_IS_STRING)) return; comm = get_pevent_field_str(trace, event, field); ret = pevent_get_field_val(NULL, event, "pid", &rec, &val, 0); if (ret < 0) return; pid = (int)val; dest_proc = find_create_process(comm, pid); if (from && strcmp(from->name(), "process")!=0){ /* not a process doing the wakeup */ from = NULL; from_proc = NULL; } else { from_proc = (class process *) from; } if (from_proc && (dest_proc->running == 0) && (dest_proc->waker == NULL) && (pid != 0) && !dont_blame_me(from_proc->comm)) dest_proc->waker = from; if (from) dest_proc->last_waker = from; /* Account processes that wake up X specially */ if (from && dest_proc && comm_is_xorg(dest_proc->comm)) from->xwakes ++ ; } else if (strcmp(event->name, "irq_handler_entry") == 0) { class interrupt *irq = NULL; const char *handler; int nr; field = pevent_find_any_field(event, "name"); if (!field || !(field->flags & FIELD_IS_STRING)) return; /* ?? */ handler = get_pevent_field_str(trace, event, field); ret = pevent_get_field_val(NULL, event, "irq", &rec, &val, 0); if (ret < 0) return; nr = (int)val; irq = find_create_interrupt(handler, nr, cpu); push_consumer(cpu, irq); irq->start_interrupt(time); if (strstr(irq->handler, "timer") ==NULL) change_blame(cpu, irq, LEVEL_HARDIRQ); } else if (strcmp(event->name, "irq_handler_exit") == 0) { class interrupt *irq = NULL; uint64_t t; /* find interrupt (top of stack) */ irq = (class interrupt *)current_consumer(cpu); if (!irq || strcmp(irq->name(), "interrupt")) return; pop_consumer(cpu); /* retire interrupt */ t = irq->end_interrupt(time); consumer_child_time(cpu, t); } else if (strcmp(event->name, "softirq_entry") == 0) { class interrupt *irq = NULL; const char *handler = NULL; int vec; ret = pevent_get_field_val(NULL, event, "vec", &rec, &val, 0); if (ret < 0) { fprintf(stderr, "softirq_entry event returned no vector number?\n"); return; } vec = (int)val; if (vec <= 9) handler = softirqs[vec]; if (!handler) return; irq = find_create_interrupt(handler, vec, cpu); push_consumer(cpu, irq); irq->start_interrupt(time); change_blame(cpu, irq, LEVEL_SOFTIRQ); } else if (strcmp(event->name, "softirq_exit") == 0) { class interrupt *irq = NULL; uint64_t t; irq = (class interrupt *) current_consumer(cpu); if (!irq || strcmp(irq->name(), "interrupt")) return; pop_consumer(cpu); /* pop irq */ t = irq->end_interrupt(time); consumer_child_time(cpu, t); } else if (strcmp(event->name, "timer_expire_entry") == 0) { class timer *timer = NULL; uint64_t function; uint64_t tmr; ret = pevent_get_field_val(NULL, event, "function", &rec, &val, 0); if (ret < 0) { fprintf(stderr, "timer_expire_entry event returned no fucntion value?\n"); return; } function = (uint64_t)val; timer = find_create_timer(function); if (timer->is_deferred()) return; ret = pevent_get_field_val(NULL, event, "timer", &rec, &val, 0); if (ret < 0) { fprintf(stderr, "softirq_entry event returned no timer ?\n"); return; } tmr = (uint64_t)val; push_consumer(cpu, timer); timer->fire(time, tmr); if (strcmp(timer->handler, "delayed_work_timer_fn")) change_blame(cpu, timer, LEVEL_TIMER); } else if (strcmp(event->name, "timer_expire_exit") == 0) { class timer *timer = NULL; uint64_t tmr; uint64_t t; ret = pevent_get_field_val(NULL, event, "timer", &rec, &val, 0); if (ret < 0) return; tmr = (uint64_t)val; timer = (class timer *) current_consumer(cpu); if (!timer || strcmp(timer->name(), "timer")) { return; } pop_consumer(cpu); t = timer->done(time, tmr); consumer_child_time(cpu, t); } else if (strcmp(event->name, "hrtimer_expire_entry") == 0) { class timer *timer = NULL; uint64_t function; uint64_t tmr; ret = pevent_get_field_val(NULL, event, "function", &rec, &val, 0); if (ret < 0) return; function = (uint64_t)val; timer = find_create_timer(function); ret = pevent_get_field_val(NULL, event, "hrtimer", &rec, &val, 0); if (ret < 0) return; tmr = (uint64_t)val; push_consumer(cpu, timer); timer->fire(time, tmr); if (strcmp(timer->handler, "delayed_work_timer_fn")) change_blame(cpu, timer, LEVEL_TIMER); } else if (strcmp(event->name, "hrtimer_expire_exit") == 0) { class timer *timer = NULL; uint64_t tmr; uint64_t t; timer = (class timer *) current_consumer(cpu); if (!timer || strcmp(timer->name(), "timer")) { return; } ret = pevent_get_field_val(NULL, event, "hrtimer", &rec, &val, 0); if (ret < 0) return; tmr = (uint64_t)val; pop_consumer(cpu); t = timer->done(time, tmr); consumer_child_time(cpu, t); } else if (strcmp(event->name, "workqueue_execute_start") == 0) { class work *work = NULL; uint64_t function; uint64_t wk; ret = pevent_get_field_val(NULL, event, "function", &rec, &val, 0); if (ret < 0) return; function = (uint64_t)val; ret = pevent_get_field_val(NULL, event, "work", &rec, &val, 0); if (ret < 0) return; wk = (uint64_t)val; work = find_create_work(function); push_consumer(cpu, work); work->fire(time, wk); if (strcmp(work->handler, "do_dbs_timer") != 0 && strcmp(work->handler, "vmstat_update") != 0) change_blame(cpu, work, LEVEL_WORK); } else if (strcmp(event->name, "workqueue_execute_end") == 0) { class work *work = NULL; uint64_t t; uint64_t wk; ret = pevent_get_field_val(NULL, event, "work", &rec, &val, 0); if (ret < 0) return; wk = (uint64_t)val; work = (class work *) current_consumer(cpu); if (!work || strcmp(work->name(), "work")) { return; } pop_consumer(cpu); t = work->done(time, wk); consumer_child_time(cpu, t); } else if (strcmp(event->name, "cpu_idle") == 0) { ret = pevent_get_field_val(NULL, event, "state", &rec, &val, 0); if (val == 4294967295) consume_blame(cpu); else set_wakeup_pending(cpu); } else if (strcmp(event->name, "power_start") == 0) { set_wakeup_pending(cpu); } else if (strcmp(event->name, "power_end") == 0) { consume_blame(cpu); } else if (strcmp(event->name, "i915_gem_ring_dispatch") == 0 || strcmp(event->name, "i915_gem_request_submit") == 0) { /* any kernel contains only one of the these tracepoints, * the latter one got replaced by the former one */ class power_consumer *consumer = NULL; int flags; ret = pevent_get_common_field_val(NULL, event, "common_flags", &rec, &val, 0); if (ret < 0) return; flags = (int)val; consumer = current_consumer(cpu); /* currently we don't count graphic requests submitted from irq contect */ if ( (flags & TRACE_FLAG_HARDIRQ) || (flags & TRACE_FLAG_SOFTIRQ)) { consumer = NULL; } /* if we are X, and someone just woke us, account the GPU op to the guy waking us */ if (consumer && strcmp(consumer->name(), "process")==0) { class process *proc = NULL; proc = (class process *) consumer; if (comm_is_xorg(proc->comm) && proc->last_waker) { consumer = proc->last_waker; } } if (consumer) { consumer->gpu_ops++; } } else if (strcmp(event->name, "writeback_inode_dirty") == 0) { static uint64_t prev_time; class power_consumer *consumer = NULL; int dev; consumer = current_consumer(cpu); ret = pevent_get_field_val(NULL, event, "dev", &rec, &val, 0); if (ret < 0) return; dev = (int)val; if (consumer && strcmp(consumer->name(), "process")==0 && dev > 0) { consumer->disk_hits++; /* if the previous inode dirty was > 1 second ago, it becomes a hard hit */ if ((time - prev_time) > 1000000000) consumer->hard_disk_hits++; prev_time = time; } } }