-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tools/bpf: Add runqslower tool to tools/bpf
Convert one of BCC tools (runqslower [0]) to BPF CO-RE + libbpf. It matches its BCC-based counterpart 1-to-1, supporting all the same parameters and functionality. runqslower tool utilizes BPF skeleton, auto-generated from BPF object file, as well as memory-mapped interface to global (read-only, in this case) data. Its Makefile also ensures auto-generation of "relocatable" vmlinux.h, which is necessary for BTF-typed raw tracepoints with direct memory access. [0] https://github.com/iovisor/bcc/blob/11bf5d02c895df9646c117c713082eb192825293/tools/runqslower.py Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20200113073143.1779940-6-andriin@fb.com
- Loading branch information
Andrii Nakryiko
authored and
Alexei Starovoitov
committed
Jan 14, 2020
1 parent
1cf5b23
commit 9c01546
Showing
6 changed files
with
396 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/.output |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) | ||
OUTPUT := .output | ||
CLANG := clang | ||
LLC := llc | ||
LLVM_STRIP := llvm-strip | ||
DEFAULT_BPFTOOL := $(OUTPUT)/sbin/bpftool | ||
BPFTOOL ?= $(DEFAULT_BPFTOOL) | ||
LIBBPF_SRC := $(abspath ../../lib/bpf) | ||
CFLAGS := -g -Wall | ||
|
||
# Try to detect best kernel BTF source | ||
KERNEL_REL := $(shell uname -r) | ||
ifneq ("$(wildcard /sys/kenerl/btf/vmlinux)","") | ||
VMLINUX_BTF := /sys/kernel/btf/vmlinux | ||
else ifneq ("$(wildcard /boot/vmlinux-$(KERNEL_REL))","") | ||
VMLINUX_BTF := /boot/vmlinux-$(KERNEL_REL) | ||
else | ||
$(error "Can't detect kernel BTF, use VMLINUX_BTF to specify it explicitly") | ||
endif | ||
|
||
abs_out := $(abspath $(OUTPUT)) | ||
ifeq ($(V),1) | ||
Q = | ||
msg = | ||
else | ||
Q = @ | ||
msg = @printf ' %-8s %s%s\n' "$(1)" "$(notdir $(2))" "$(if $(3), $(3))"; | ||
MAKEFLAGS += --no-print-directory | ||
submake_extras := feature_display=0 | ||
endif | ||
|
||
.DELETE_ON_ERROR: | ||
|
||
.PHONY: all clean runqslower | ||
all: runqslower | ||
|
||
runqslower: $(OUTPUT)/runqslower | ||
|
||
clean: | ||
$(call msg,CLEAN) | ||
$(Q)rm -rf $(OUTPUT) runqslower | ||
|
||
$(OUTPUT)/runqslower: $(OUTPUT)/runqslower.o $(OUTPUT)/libbpf.a | ||
$(call msg,BINARY,$@) | ||
$(Q)$(CC) $(CFLAGS) -lelf -lz $^ -o $@ | ||
|
||
$(OUTPUT)/runqslower.o: runqslower.h $(OUTPUT)/runqslower.skel.h \ | ||
$(OUTPUT)/runqslower.bpf.o | ||
|
||
$(OUTPUT)/runqslower.bpf.o: $(OUTPUT)/vmlinux.h runqslower.h | ||
|
||
$(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(BPFTOOL) | ||
$(call msg,GEN-SKEL,$@) | ||
$(Q)$(BPFTOOL) gen skeleton $< > $@ | ||
|
||
$(OUTPUT)/%.bpf.o: %.bpf.c $(OUTPUT)/libbpf.a | $(OUTPUT) | ||
$(call msg,BPF,$@) | ||
$(Q)$(CLANG) -g -O2 -target bpf -I$(OUTPUT) -I$(LIBBPF_SRC) \ | ||
-c $(filter %.c,$^) -o $@ && \ | ||
$(LLVM_STRIP) -g $@ | ||
|
||
$(OUTPUT)/%.o: %.c | $(OUTPUT) | ||
$(call msg,CC,$@) | ||
$(Q)$(CC) $(CFLAGS) -I$(LIBBPF_SRC) -I$(OUTPUT) -c $(filter %.c,$^) -o $@ | ||
|
||
$(OUTPUT): | ||
$(call msg,MKDIR,$@) | ||
$(Q)mkdir -p $(OUTPUT) | ||
|
||
$(OUTPUT)/vmlinux.h: $(VMLINUX_BTF) | $(OUTPUT) $(BPFTOOL) | ||
$(call msg,GEN,$@) | ||
$(Q)$(BPFTOOL) btf dump file $(VMLINUX_BTF) format c > $@ | ||
|
||
$(OUTPUT)/libbpf.a: | $(OUTPUT) | ||
$(Q)$(MAKE) $(submake_extras) -C $(LIBBPF_SRC) \ | ||
OUTPUT=$(abs_out)/ $(abs_out)/libbpf.a | ||
|
||
$(DEFAULT_BPFTOOL): | ||
$(Q)$(MAKE) $(submake_extras) -C ../bpftool \ | ||
prefix= OUTPUT=$(abs_out)/ DESTDIR=$(abs_out) install |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
// Copyright (c) 2019 Facebook | ||
#include "vmlinux.h" | ||
#include <bpf_helpers.h> | ||
#include "runqslower.h" | ||
|
||
#define TASK_RUNNING 0 | ||
|
||
#define BPF_F_INDEX_MASK 0xffffffffULL | ||
#define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK | ||
|
||
const volatile __u64 min_us = 0; | ||
const volatile pid_t targ_pid = 0; | ||
|
||
struct { | ||
__uint(type, BPF_MAP_TYPE_HASH); | ||
__uint(max_entries, 10240); | ||
__type(key, u32); | ||
__type(value, u64); | ||
} start SEC(".maps"); | ||
|
||
struct { | ||
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); | ||
__uint(key_size, sizeof(u32)); | ||
__uint(value_size, sizeof(u32)); | ||
} events SEC(".maps"); | ||
|
||
/* record enqueue timestamp */ | ||
__always_inline | ||
static int trace_enqueue(u32 tgid, u32 pid) | ||
{ | ||
u64 ts; | ||
|
||
if (!pid || (targ_pid && targ_pid != pid)) | ||
return 0; | ||
|
||
ts = bpf_ktime_get_ns(); | ||
bpf_map_update_elem(&start, &pid, &ts, 0); | ||
return 0; | ||
} | ||
|
||
SEC("tp_btf/sched_wakeup") | ||
int handle__sched_wakeup(u64 *ctx) | ||
{ | ||
/* TP_PROTO(struct task_struct *p) */ | ||
struct task_struct *p = (void *)ctx[0]; | ||
|
||
return trace_enqueue(p->tgid, p->pid); | ||
} | ||
|
||
SEC("tp_btf/sched_wakeup_new") | ||
int handle__sched_wakeup_new(u64 *ctx) | ||
{ | ||
/* TP_PROTO(struct task_struct *p) */ | ||
struct task_struct *p = (void *)ctx[0]; | ||
|
||
return trace_enqueue(p->tgid, p->pid); | ||
} | ||
|
||
SEC("tp_btf/sched_switch") | ||
int handle__sched_switch(u64 *ctx) | ||
{ | ||
/* TP_PROTO(bool preempt, struct task_struct *prev, | ||
* struct task_struct *next) | ||
*/ | ||
struct task_struct *prev = (struct task_struct *)ctx[1]; | ||
struct task_struct *next = (struct task_struct *)ctx[2]; | ||
struct event event = {}; | ||
u64 *tsp, delta_us; | ||
long state; | ||
u32 pid; | ||
|
||
/* ivcsw: treat like an enqueue event and store timestamp */ | ||
if (prev->state == TASK_RUNNING) | ||
trace_enqueue(prev->tgid, prev->pid); | ||
|
||
pid = next->pid; | ||
|
||
/* fetch timestamp and calculate delta */ | ||
tsp = bpf_map_lookup_elem(&start, &pid); | ||
if (!tsp) | ||
return 0; /* missed enqueue */ | ||
|
||
delta_us = (bpf_ktime_get_ns() - *tsp) / 1000; | ||
if (min_us && delta_us <= min_us) | ||
return 0; | ||
|
||
event.pid = pid; | ||
event.delta_us = delta_us; | ||
bpf_get_current_comm(&event.task, sizeof(event.task)); | ||
|
||
/* output */ | ||
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, | ||
&event, sizeof(event)); | ||
|
||
bpf_map_delete_elem(&start, &pid); | ||
return 0; | ||
} | ||
|
||
char LICENSE[] SEC("license") = "GPL"; |
Oops, something went wrong.