cregit-Linux how code gets into the kernel

Release 4.10 tools/perf/util/evsel.c

Directory: tools/perf/util
/*
 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
 *
 * Parts came from builtin-{top,stat,record}.c, see those files for further
 * copyright notes.
 *
 * Released under the GPL v2. (and only v2, not any later version)
 */

#include <byteswap.h>
#include <linux/bitops.h>
#include <api/fs/tracing_path.h>
#include <traceevent/event-parse.h>
#include <linux/hw_breakpoint.h>
#include <linux/perf_event.h>
#include <linux/err.h>
#include <sys/resource.h>
#include "asm/bug.h"
#include "callchain.h"
#include "cgroup.h"
#include "evsel.h"
#include "evlist.h"
#include "util.h"
#include "cpumap.h"
#include "thread_map.h"
#include "target.h"
#include "perf_regs.h"
#include "debug.h"
#include "trace-event.h"
#include "stat.h"
#include "util/parse-branch-options.h"

static struct {
	
bool sample_id_all;
	
bool exclude_guest;
	
bool mmap2;
	
bool cloexec;
	
bool clockid;
	
bool clockid_wrong;
	
bool lbr_flags;
	
bool write_backward;
} 
perf_missing_features;


static clockid_t clockid;


static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo15100.00%1100.00%
Total15100.00%1100.00%


static void perf_evsel__no_extra_fini(struct perf_evsel *evsel __maybe_unused) { }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo11100.00%1100.00%
Total11100.00%1100.00%

static struct { size_t size; int (*init)(struct perf_evsel *evsel); void (*fini)(struct perf_evsel *evsel); } perf_evsel__object = { .size = sizeof(struct perf_evsel), .init = perf_evsel__no_extra_init, .fini = perf_evsel__no_extra_fini, };
int perf_evsel__object_config(size_t object_size, int (*init)(struct perf_evsel *evsel), void (*fini)(struct perf_evsel *evsel)) { if (object_size == 0) goto set_methods; if (perf_evsel__object.size > object_size) return -EINVAL; perf_evsel__object.size = object_size; set_methods: if (init != NULL) perf_evsel__object.init = init; if (fini != NULL) perf_evsel__object.fini = fini; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo88100.00%1100.00%
Total88100.00%1100.00%

#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
int __perf_evsel__sample_size(u64 sample_type) { u64 mask = sample_type & PERF_SAMPLE_MASK; int size = 0; int i; for (i = 0; i < 64; i++) { if (mask & (1ULL << i)) size++; } size *= sizeof(u64); return size; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo61100.00%1100.00%
Total61100.00%1100.00%

/** * __perf_evsel__calc_id_pos - calculate id_pos. * @sample_type: sample type * * This function returns the position of the event id (PERF_SAMPLE_ID or * PERF_SAMPLE_IDENTIFIER) in a sample event i.e. in the array of struct * sample_event. */
static int __perf_evsel__calc_id_pos(u64 sample_type) { int idx = 0; if (sample_type & PERF_SAMPLE_IDENTIFIER) return 0; if (!(sample_type & PERF_SAMPLE_ID)) return -1; if (sample_type & PERF_SAMPLE_IP) idx += 1; if (sample_type & PERF_SAMPLE_TID) idx += 1; if (sample_type & PERF_SAMPLE_TIME) idx += 1; if (sample_type & PERF_SAMPLE_ADDR) idx += 1; return idx; }

Contributors

PersonTokensPropCommitsCommitProp
adrian hunteradrian hunter79100.00%1100.00%
Total79100.00%1100.00%

/** * __perf_evsel__calc_is_pos - calculate is_pos. * @sample_type: sample type * * This function returns the position (counting backwards) of the event id * (PERF_SAMPLE_ID or PERF_SAMPLE_IDENTIFIER) in a non-sample event i.e. if * sample_id_all is used there is an id sample appended to non-sample events. */
static int __perf_evsel__calc_is_pos(u64 sample_type) { int idx = 1; if (sample_type & PERF_SAMPLE_IDENTIFIER) return 1; if (!(sample_type & PERF_SAMPLE_ID)) return -1; if (sample_type & PERF_SAMPLE_CPU) idx += 1; if (sample_type & PERF_SAMPLE_STREAM_ID) idx += 1; return idx; }

Contributors

PersonTokensPropCommitsCommitProp
adrian hunteradrian hunter59100.00%1100.00%
Total59100.00%1100.00%


void perf_evsel__calc_id_pos(struct perf_evsel *evsel) { evsel->id_pos = __perf_evsel__calc_id_pos(evsel->attr.sample_type); evsel->is_pos = __perf_evsel__calc_is_pos(evsel->attr.sample_type); }

Contributors

PersonTokensPropCommitsCommitProp
adrian hunteradrian hunter36100.00%1100.00%
Total36100.00%1100.00%


void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, enum perf_event_sample_format bit) { if (!(evsel->attr.sample_type & bit)) { evsel->attr.sample_type |= bit; evsel->sample_size += sizeof(u64); perf_evsel__calc_id_pos(evsel); } }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo4690.20%150.00%
adrian hunteradrian hunter59.80%150.00%
Total51100.00%2100.00%


void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel, enum perf_event_sample_format bit) { if (evsel->attr.sample_type & bit) { evsel->attr.sample_type &= ~bit; evsel->sample_size -= sizeof(u64); perf_evsel__calc_id_pos(evsel); } }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo4489.80%150.00%
adrian hunteradrian hunter510.20%150.00%
Total49100.00%2100.00%


void perf_evsel__set_sample_id(struct perf_evsel *evsel, bool can_sample_identifier) { if (can_sample_identifier) { perf_evsel__reset_sample_bit(evsel, ID); perf_evsel__set_sample_bit(evsel, IDENTIFIER); } else { perf_evsel__set_sample_bit(evsel, ID); } evsel->attr.read_format |= PERF_FORMAT_ID; }

Contributors

PersonTokensPropCommitsCommitProp
adrian hunteradrian hunter2650.98%150.00%
arnaldo carvalho de meloarnaldo carvalho de melo2549.02%150.00%
Total51100.00%2100.00%

/** * perf_evsel__is_function_event - Return whether given evsel is a function * trace event * * @evsel - evsel selector to be tested * * Return %true if event is function trace event */
bool perf_evsel__is_function_event(struct perf_evsel *evsel) { #define FUNCTION_EVENT "ftrace:function" return evsel->name && !strncmp(FUNCTION_EVENT, evsel->name, sizeof(FUNCTION_EVENT)); #undef FUNCTION_EVENT }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo37100.00%1100.00%
Total37100.00%1100.00%


void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr, int idx) { evsel->idx = idx; evsel->tracking = !idx; evsel->attr = *attr; evsel->leader = evsel; evsel->unit = ""; evsel->scale = 1.0; evsel->evlist = NULL; evsel->bpf_fd = -1; INIT_LIST_HEAD(&evsel->node); INIT_LIST_HEAD(&evsel->config_terms); perf_evsel__object.init(evsel); evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); perf_evsel__calc_id_pos(evsel); evsel->cmdline_group_boundary = false; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo6355.26%436.36%
wang nanwang nan1311.40%218.18%
adrian hunteradrian hunter1210.53%218.18%
stephane eranianstephane eranian1210.53%19.09%
jiri olsajiri olsa87.02%19.09%
namhyung kimnamhyung kim65.26%19.09%
Total114100.00%11100.00%


struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) { struct perf_evsel *evsel = zalloc(perf_evsel__object.size); if (evsel != NULL) perf_evsel__init(evsel, attr, idx); if (perf_evsel__is_bpf_output(evsel)) { evsel->attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD), evsel->attr.sample_period = 1; } return evsel; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo4152.56%457.14%
wang nanwang nan3342.31%228.57%
lin minglin ming45.13%114.29%
Total78100.00%7100.00%


struct perf_evsel *perf_evsel__new_cycles(void) { struct perf_event_attr attr = { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES, }; struct perf_evsel *evsel; event_attr_init(&attr); perf_event_attr__set_max_precise_ip(&attr); evsel = perf_evsel__new(&attr); if (evsel == NULL) goto out; /* use asprintf() because free(evsel) assumes name is allocated */ if (asprintf(&evsel->name, "cycles%.*s", attr.precise_ip ? attr.precise_ip + 1 : 0, ":ppp") < 0) goto error_free; out: return evsel; error_free: perf_evsel__delete(evsel); evsel = NULL; goto out; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo110100.00%1100.00%
Total110100.00%1100.00%

/* * Returns pointer with encoded error via <linux/err.h> interface. */
struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) { struct perf_evsel *evsel = zalloc(perf_evsel__object.size); int err = -ENOMEM; if (evsel == NULL) { goto out_err; } else { struct perf_event_attr attr = { .type = PERF_TYPE_TRACEPOINT, .sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD), }; if (asprintf(&evsel->name, "%s:%s", sys, name) < 0) goto out_free; evsel->tp_format = trace_event__tp_format(sys, name); if (IS_ERR(evsel->tp_format)) { err = PTR_ERR(evsel->tp_format); goto out_free; } event_attr_init(&attr); attr.config = evsel->tp_format->id; attr.sample_period = 1; perf_evsel__init(evsel, &attr, idx); } return evsel; out_free: zfree(&evsel->name); free(evsel); out_err: return ERR_PTR(err); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo15582.01%675.00%
jiri olsajiri olsa3417.99%225.00%
Total189100.00%8100.00%

const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { "cycles", "instructions", "cache-references", "cache-misses", "branches", "branch-misses", "bus-cycles", "stalled-cycles-frontend", "stalled-cycles-backend", "ref-cycles", };
static const char *__perf_evsel__hw_name(u64 config) { if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config]) return perf_evsel__hw_names[config]; return "unknown-hardware"; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo31100.00%2100.00%
Total31100.00%2100.00%


static int perf_evsel__add_modifiers(struct perf_evsel *evsel, char *bf, size_t size) { int colon = 0, r = 0; struct perf_event_attr *attr = &evsel->attr; bool exclude_guest_default = false; #define MOD_PRINT(context, mod) do { \ if (!attr->exclude_##context) { \ if (!colon) colon = ++r; \ r += scnprintf(bf + r, size - r, "%c", mod); \ } } while(0) if (attr->exclude_kernel || attr->exclude_user || attr->exclude_hv) { MOD_PRINT(kernel, 'k'); MOD_PRINT(user, 'u'); MOD_PRINT(hv, 'h'); exclude_guest_default = true; } if (attr->precise_ip) { if (!colon) colon = ++r; r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp"); exclude_guest_default = true; } if (attr->exclude_host || attr->exclude_guest == exclude_guest_default) { MOD_PRINT(host, 'H'); MOD_PRINT(guest, 'G'); } #undef MOD_PRINT if (colon) bf[colon - 1] = ':'; return r; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo182100.00%2100.00%
Total182100.00%2100.00%


static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size) { int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->attr.config)); return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo55100.00%1100.00%
Total55100.00%1100.00%

const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = { "cpu-clock", "task-clock", "page-faults", "context-switches", "cpu-migrations", "minor-faults", "major-faults", "alignment-faults", "emulation-faults", "dummy", };
static const char *__perf_evsel__sw_name(u64 config) { if (config < PERF_COUNT_SW_MAX && perf_evsel__sw_names[config]) return perf_evsel__sw_names[config]; return "unknown-software"; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo31100.00%2100.00%
Total31100.00%2100.00%


static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size) { int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->attr.config)); return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo55100.00%1100.00%
Total55100.00%1100.00%


static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type) { int r; r = scnprintf(bf, size, "mem:0x%" PRIx64 ":", addr); if (type & HW_BREAKPOINT_R) r += scnprintf(bf + r, size - r, "r"); if (type & HW_BREAKPOINT_W) r += scnprintf(bf + r, size - r, "w"); if (type & HW_BREAKPOINT_X) r += scnprintf(bf + r, size - r, "x"); return r; }

Contributors

PersonTokensPropCommitsCommitProp
jiri olsajiri olsa103100.00%1100.00%
Total103100.00%1100.00%


static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size) { struct perf_event_attr *attr = &evsel->attr; int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type); return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); }

Contributors

PersonTokensPropCommitsCommitProp
jiri olsajiri olsa62100.00%1100.00%
Total62100.00%1100.00%

const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX] [PERF_EVSEL__MAX_ALIASES] = { { "L1-dcache", "l1-d", "l1d", "L1-data", }, { "L1-icache", "l1-i", "l1i", "L1-instruction", }, { "LLC", "L2", }, { "dTLB", "d-tlb", "Data-TLB", }, { "iTLB", "i-tlb", "Instruction-TLB", }, { "branch", "branches", "bpu", "btb", "bpc", }, { "node", }, }; const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX] [PERF_EVSEL__MAX_ALIASES] = { { "load", "loads", "read", }, { "store", "stores", "write", }, { "prefetch", "prefetches", "speculative-read", "speculative-load", }, }; const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX] [PERF_EVSEL__MAX_ALIASES] = { { "refs", "Reference", "ops", "access", }, { "misses", "miss", }, }; #define C(x) PERF_COUNT_HW_CACHE_##x #define CACHE_READ (1 << C(OP_READ)) #define CACHE_WRITE (1 << C(OP_WRITE)) #define CACHE_PREFETCH (1 << C(OP_PREFETCH)) #define COP(x) (1 << x) /* * cache operartion stat * L1I : Read and prefetch only * ITLB and BPU : Read-only */ static unsigned long perf_evsel__hw_cache_stat[C(MAX)] = { [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), [C(L1I)] = (CACHE_READ | CACHE_PREFETCH), [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), [C(ITLB)] = (CACHE_READ), [C(BPU)] = (CACHE_READ), [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), };
bool perf_evsel__is_cache_op_valid(u8 type, u8 op) { if (perf_evsel__hw_cache_stat[type] & COP(op)) return true; /* valid */ else return false; /* invalid */ }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo32100.00%1100.00%
Total32100.00%1100.00%


int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, char *bf, size_t size) { if (result) { return scnprintf(bf, size, "%s-%s-%s", perf_evsel__hw_cache[type][0], perf_evsel__hw_cache_op[op][0], perf_evsel__hw_cache_result[result][0]); } return scnprintf(bf, size, "%s-%s", perf_evsel__hw_cache[type][0], perf_evsel__hw_cache_op[op][1]); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo87100.00%1100.00%
Total87100.00%1100.00%


static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size) { u8 op, result, type = (config >> 0) & 0xff; const char *err = "unknown-ext-hardware-cache-type"; if (type >= PERF_COUNT_HW_CACHE_MAX) goto out_err; op = (config >> 8) & 0xff; err = "unknown-ext-hardware-cache-op"; if (op >= PERF_COUNT_HW_CACHE_OP_MAX) goto out_err; result = (config >> 16) & 0xff; err = "unknown-ext-hardware-cache-result"; if (result >= PERF_COUNT_HW_CACHE_RESULT_MAX) goto out_err; err = "invalid-cache"; if (!perf_evsel__is_cache_op_valid(type, op)) goto out_err; return __perf_evsel__hw_cache_type_op_res_name(type, op, result, bf, size); out_err: return scnprintf(bf, size, "%s", err); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo138100.00%3100.00%
Total138100.00%3100.00%


static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t size) { int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size); return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo50100.00%1100.00%
Total50100.00%1100.00%


static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size) { int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config); return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret); }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo53100.00%1100.00%
Total53100.00%1100.00%


const char *perf_evsel__name(struct perf_evsel *evsel) { char bf[128]; if (evsel->name) return evsel->name; switch (evsel->attr.type) { case PERF_TYPE_RAW: perf_evsel__raw_name(evsel, bf, sizeof(bf)); break; case PERF_TYPE_HARDWARE: perf_evsel__hw_name(evsel, bf, sizeof(bf)); break; case PERF_TYPE_HW_CACHE: perf_evsel__hw_cache_name(evsel, bf, sizeof(bf)); break; case PERF_TYPE_SOFTWARE: perf_evsel__sw_name(evsel, bf, sizeof(bf)); break; case PERF_TYPE_TRACEPOINT: scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint"); break; case PERF_TYPE_BREAKPOINT: perf_evsel__bp_name(evsel, bf, sizeof(bf)); break; default: scnprintf(bf, sizeof(bf), "unknown attr type: %d", evsel->attr.type); break; } evsel->name = strdup(bf); return evsel->name ?: "unknown"; }

Contributors

PersonTokensPropCommitsCommitProp
arnaldo carvalho de meloarnaldo carvalho de melo15287.36%675.00%
jiri olsajiri olsa169.20%112.50%
robert richterrobert richter63.45%112.50%
Total174100.00%8100.00%


const char *perf_evsel__group_name(struct perf_evsel *evsel) { return evsel->group_name ?: "anon group"; }

Contributors

PersonTokensPropCommitsCommitProp
namhyung kimnamhyung kim20100.00%1100.00%
Total20100.00%1100.00%


int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size) { int ret; struct perf_evsel *pos; const char *group_name = perf_evsel__group_name(evsel); ret = scnprintf(buf, size, "%s", group_name); ret += scnprintf(buf + ret, size - ret, " { %s", perf_evsel__name(evsel)); for_each_group_member(pos, evsel) ret += scnprintf(buf + ret, size - ret, ", %s", perf_evsel__name(pos)); ret += scnprintf(buf + ret, size - ret, " }"); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
namhyung kimnamhyung kim112100.00%1100.00%
Total112100.00%1100.00%


void perf_evsel__config_callchain(struct perf_evsel *evsel, struct record_opts *opts