Linux Perf
Take a note of linux perf tool, more details will be added.
usermode part
tools/perf/builtin-record.c
\-- cmd_record
| \-- __cmd_record
| | \-- record__open
| | | \-- evsel__open
tools/perf/util/evsel.c
\-- evsel__open
| \-- evsel__open_cpu
| | \-- sys_perf_event_open
kernelmode part
kernel/events/core.c
\-- sys_perf_event_open
| \-- perf_event_alloc
| | \-- perf_init_event
| | | \-- perf_try_init_event
| | | | \-- pmu->event_init
pmu register
kernel/events/core.c
perf_pmu_register(&perf_swevent, "software", PERF_TYPE_SOFTWARE);
perf_pmu_register(&perf_cpu_clock, NULL, -1);
perf_pmu_register(&perf_task_clock, NULL, -1);
perf_tp_register();
static inline void perf_tp_register(void)
{
perf_pmu_register(&perf_tracepoint, "tracepoint", PERF_TYPE_TRACEPOINT);
#ifdef CONFIG_KPROBE_EVENTS
perf_pmu_register(&perf_kprobe, "kprobe", -1);
#endif
#ifdef CONFIG_UPROBE_EVENTS
perf_pmu_register(&perf_uprobe, "uprobe", -1);
#endif
}
take tracepoint as example
kernel/events/core.c
static struct pmu perf_tracepoint = {
.task_ctx_nr = perf_sw_context,
.event_init = perf_tp_event_init,
.add = perf_trace_add,
.del = perf_trace_del,
.start = perf_swevent_start,
.stop = perf_swevent_stop,
.read = perf_swevent_read,
};
\-- pmu->event_init
| \-- perf_tp_event_init
| | \-- perf_trace_init
kernel/trace/trace_event_perf.c
\-- perf_trace_init
| \-- perf_trace_event_init
| | \-- perf_trace_event_reg
| | | \-- tp_event->class->reg
tp_event is a trace_event_call structure which is defined when we use the very complicated macro TRACE_EVENT for specific tracepoint, all trace_event_call structures will be linked to a global list ftrace_events.
for tracepoint, the tp_event->class->reg will be trace_event_reg, it will register the perf_event callback perf_trace_##call to the specific tracepoint, the callback perf_trace_##call which is also define by the very complicated macro TRACE_EVENT, will write collected data to the ring buffer
Written on July 10, 2022