static inline struct event_format *find_cache_event(struct perf_evsel *evsel) { static char ev_name[256]; struct event_format *event; int type = evsel->attr.config; /* * XXX: Do we really need to cache this since now we have evsel->tp_format * cached already? Need to re-read this "cache" routine that as well calls * define_event_symbols() :-\ */ if (events[type]) return events[type]; events[type] = event = evsel->tp_format; 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; }
static void define_event_symbols(struct event *event, struct print_arg *args) { switch (args->type) { case PRINT_NULL: break; case PRINT_ATOM: define_value(PRINT_FLAGS, event->id, cur_field_name, "0", args->atom.atom); break; case PRINT_FIELD: cur_field_name = args->field.name; break; case PRINT_FLAGS: define_event_symbols(event, args->flags.field); define_field(PRINT_FLAGS, event->id, cur_field_name, args->flags.delim); define_values(PRINT_FLAGS, args->flags.flags, event->id, cur_field_name); break; case PRINT_SYMBOL: define_event_symbols(event, args->symbol.field); define_field(PRINT_SYMBOL, event->id, cur_field_name, NULL); define_values(PRINT_SYMBOL, args->symbol.symbols, event->id, cur_field_name); break; case PRINT_STRING: break; case PRINT_TYPE: define_event_symbols(event, args->typecast.item); break; case PRINT_OP: define_event_symbols(event, args->op.left); define_event_symbols(event, args->op.right); break; default: /* we should warn... */ return; } if (args->next) define_event_symbols(event, args->next); }
static void perl_process_tracepoint(struct perf_sample *sample, struct perf_evsel *evsel, struct thread *thread) { struct event_format *event = evsel->tp_format; struct format_field *field; static char handler[256]; unsigned long long val; unsigned long s, ns; int pid; int cpu = sample->cpu; void *data = sample->raw_data; unsigned long long nsecs = sample->time; const char *comm = thread__comm_str(thread); dSP; if (evsel->attr.type != PERF_TYPE_TRACEPOINT) return; if (!event) die("ug! no event found for type %" PRIu64, (u64)evsel->attr.config); pid = raw_field_value(event, "common_pid", data); sprintf(handler, "%s::%s", event->system, event->name); if (!test_and_set_bit(event->id, events_defined)) define_event_symbols(event, handler, event->print_fmt.args); s = nsecs / NSECS_PER_SEC; ns = nsecs - s * NSECS_PER_SEC; scripting_context->event_data = data; scripting_context->pevent = evsel->tp_format->pevent; ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newSVpv(handler, 0))); XPUSHs(sv_2mortal(newSViv(PTR2IV(scripting_context)))); XPUSHs(sv_2mortal(newSVuv(cpu))); XPUSHs(sv_2mortal(newSVuv(s))); XPUSHs(sv_2mortal(newSVuv(ns))); XPUSHs(sv_2mortal(newSViv(pid))); XPUSHs(sv_2mortal(newSVpv(comm, 0))); /* common fields other than pid can be accessed via xsub fns */ for (field = event->format.fields; field; field = field->next) { if (field->flags & FIELD_IS_STRING) { int offset; if (field->flags & FIELD_IS_DYNAMIC) { offset = *(int *)(data + field->offset); offset &= 0xffff; } else offset = field->offset; XPUSHs(sv_2mortal(newSVpv((char *)data + offset, 0))); } else { /* FIELD_IS_NUMERIC */ val = read_size(event, data + field->offset, field->size); if (field->flags & FIELD_IS_SIGNED) { XPUSHs(sv_2mortal(newSViv(val))); } else { XPUSHs(sv_2mortal(newSVuv(val))); } } } PUTBACK; if (get_cv(handler, 0)) call_pv(handler, G_SCALAR); else if (get_cv("main::trace_unhandled", 0)) { XPUSHs(sv_2mortal(newSVpv(handler, 0))); XPUSHs(sv_2mortal(newSViv(PTR2IV(scripting_context)))); XPUSHs(sv_2mortal(newSVuv(cpu))); XPUSHs(sv_2mortal(newSVuv(nsecs))); XPUSHs(sv_2mortal(newSViv(pid))); XPUSHs(sv_2mortal(newSVpv(comm, 0))); call_pv("main::trace_unhandled", G_SCALAR); } SPAGAIN; PUTBACK; FREETMPS; LEAVE; }
static void define_event_symbols(struct event_format *event, const char *ev_name, struct print_arg *args) { if (args == NULL) return; switch (args->type) { case PRINT_NULL: break; case PRINT_ATOM: define_flag_value(ev_name, cur_field_name, "0", args->atom.atom); zero_flag_atom = 0; break; case PRINT_FIELD: free(cur_field_name); cur_field_name = strdup(args->field.name); break; case PRINT_FLAGS: define_event_symbols(event, ev_name, args->flags.field); define_flag_field(ev_name, cur_field_name, args->flags.delim); define_flag_values(args->flags.flags, ev_name, cur_field_name); break; case PRINT_SYMBOL: define_event_symbols(event, ev_name, args->symbol.field); define_symbolic_field(ev_name, cur_field_name); define_symbolic_values(args->symbol.symbols, ev_name, cur_field_name); break; case PRINT_HEX: define_event_symbols(event, ev_name, args->hex.field); define_event_symbols(event, ev_name, args->hex.size); break; case PRINT_INT_ARRAY: define_event_symbols(event, ev_name, args->int_array.field); define_event_symbols(event, ev_name, args->int_array.count); define_event_symbols(event, ev_name, args->int_array.el_size); break; case PRINT_BSTRING: case PRINT_DYNAMIC_ARRAY: case PRINT_DYNAMIC_ARRAY_LEN: case PRINT_STRING: case PRINT_BITMASK: break; case PRINT_TYPE: define_event_symbols(event, ev_name, args->typecast.item); break; case PRINT_OP: if (strcmp(args->op.op, ":") == 0) zero_flag_atom = 1; define_event_symbols(event, ev_name, args->op.left); define_event_symbols(event, ev_name, args->op.right); break; case PRINT_FUNC: default: pr_err("Unsupported print arg type\n"); /* we should warn... */ return; } if (args->next) define_event_symbols(event, ev_name, args->next); }