Skip to content

Commit 9c01546

Browse files
anakryikoAlexei Starovoitov
authored andcommitted
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
1 parent 1cf5b23 commit 9c01546

File tree

6 files changed

+396
-5
lines changed

6 files changed

+396
-5
lines changed

tools/bpf/Makefile

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ FEATURE_TESTS = libbfd disassembler-four-args
3838
FEATURE_DISPLAY = libbfd disassembler-four-args
3939

4040
check_feat := 1
41-
NON_CHECK_FEAT_TARGETS := clean bpftool_clean
41+
NON_CHECK_FEAT_TARGETS := clean bpftool_clean runqslower_clean
4242
ifdef MAKECMDGOALS
4343
ifeq ($(filter-out $(NON_CHECK_FEAT_TARGETS),$(MAKECMDGOALS)),)
4444
check_feat := 0
@@ -73,7 +73,7 @@ $(OUTPUT)%.lex.o: $(OUTPUT)%.lex.c
7373

7474
PROGS = $(OUTPUT)bpf_jit_disasm $(OUTPUT)bpf_dbg $(OUTPUT)bpf_asm
7575

76-
all: $(PROGS) bpftool
76+
all: $(PROGS) bpftool runqslower
7777

7878
$(OUTPUT)bpf_jit_disasm: CFLAGS += -DPACKAGE='bpf_jit_disasm'
7979
$(OUTPUT)bpf_jit_disasm: $(OUTPUT)bpf_jit_disasm.o
@@ -89,15 +89,15 @@ $(OUTPUT)bpf_exp.lex.c: $(OUTPUT)bpf_exp.yacc.c
8989
$(OUTPUT)bpf_exp.yacc.o: $(OUTPUT)bpf_exp.yacc.c
9090
$(OUTPUT)bpf_exp.lex.o: $(OUTPUT)bpf_exp.lex.c
9191

92-
clean: bpftool_clean
92+
clean: bpftool_clean runqslower_clean
9393
$(call QUIET_CLEAN, bpf-progs)
9494
$(Q)$(RM) -r -- $(OUTPUT)*.o $(OUTPUT)bpf_jit_disasm $(OUTPUT)bpf_dbg \
9595
$(OUTPUT)bpf_asm $(OUTPUT)bpf_exp.yacc.* $(OUTPUT)bpf_exp.lex.*
9696
$(call QUIET_CLEAN, core-gen)
9797
$(Q)$(RM) -- $(OUTPUT)FEATURE-DUMP.bpf
9898
$(Q)$(RM) -r -- $(OUTPUT)feature
9999

100-
install: $(PROGS) bpftool_install
100+
install: $(PROGS) bpftool_install runqslower_install
101101
$(call QUIET_INSTALL, bpf_jit_disasm)
102102
$(Q)$(INSTALL) -m 0755 -d $(DESTDIR)$(prefix)/bin
103103
$(Q)$(INSTALL) $(OUTPUT)bpf_jit_disasm $(DESTDIR)$(prefix)/bin/bpf_jit_disasm
@@ -115,4 +115,14 @@ bpftool_install:
115115
bpftool_clean:
116116
$(call descend,bpftool,clean)
117117

118-
.PHONY: all install clean bpftool bpftool_install bpftool_clean
118+
runqslower:
119+
$(call descend,runqslower)
120+
121+
runqslower_install:
122+
$(call descend,runqslower,install)
123+
124+
runqslower_clean:
125+
$(call descend,runqslower,clean)
126+
127+
.PHONY: all install clean bpftool bpftool_install bpftool_clean \
128+
runqslower runqslower_install runqslower_clean

tools/bpf/runqslower/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/.output

tools/bpf/runqslower/Makefile

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2+
OUTPUT := .output
3+
CLANG := clang
4+
LLC := llc
5+
LLVM_STRIP := llvm-strip
6+
DEFAULT_BPFTOOL := $(OUTPUT)/sbin/bpftool
7+
BPFTOOL ?= $(DEFAULT_BPFTOOL)
8+
LIBBPF_SRC := $(abspath ../../lib/bpf)
9+
CFLAGS := -g -Wall
10+
11+
# Try to detect best kernel BTF source
12+
KERNEL_REL := $(shell uname -r)
13+
ifneq ("$(wildcard /sys/kenerl/btf/vmlinux)","")
14+
VMLINUX_BTF := /sys/kernel/btf/vmlinux
15+
else ifneq ("$(wildcard /boot/vmlinux-$(KERNEL_REL))","")
16+
VMLINUX_BTF := /boot/vmlinux-$(KERNEL_REL)
17+
else
18+
$(error "Can't detect kernel BTF, use VMLINUX_BTF to specify it explicitly")
19+
endif
20+
21+
abs_out := $(abspath $(OUTPUT))
22+
ifeq ($(V),1)
23+
Q =
24+
msg =
25+
else
26+
Q = @
27+
msg = @printf ' %-8s %s%s\n' "$(1)" "$(notdir $(2))" "$(if $(3), $(3))";
28+
MAKEFLAGS += --no-print-directory
29+
submake_extras := feature_display=0
30+
endif
31+
32+
.DELETE_ON_ERROR:
33+
34+
.PHONY: all clean runqslower
35+
all: runqslower
36+
37+
runqslower: $(OUTPUT)/runqslower
38+
39+
clean:
40+
$(call msg,CLEAN)
41+
$(Q)rm -rf $(OUTPUT) runqslower
42+
43+
$(OUTPUT)/runqslower: $(OUTPUT)/runqslower.o $(OUTPUT)/libbpf.a
44+
$(call msg,BINARY,$@)
45+
$(Q)$(CC) $(CFLAGS) -lelf -lz $^ -o $@
46+
47+
$(OUTPUT)/runqslower.o: runqslower.h $(OUTPUT)/runqslower.skel.h \
48+
$(OUTPUT)/runqslower.bpf.o
49+
50+
$(OUTPUT)/runqslower.bpf.o: $(OUTPUT)/vmlinux.h runqslower.h
51+
52+
$(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(BPFTOOL)
53+
$(call msg,GEN-SKEL,$@)
54+
$(Q)$(BPFTOOL) gen skeleton $< > $@
55+
56+
$(OUTPUT)/%.bpf.o: %.bpf.c $(OUTPUT)/libbpf.a | $(OUTPUT)
57+
$(call msg,BPF,$@)
58+
$(Q)$(CLANG) -g -O2 -target bpf -I$(OUTPUT) -I$(LIBBPF_SRC) \
59+
-c $(filter %.c,$^) -o $@ && \
60+
$(LLVM_STRIP) -g $@
61+
62+
$(OUTPUT)/%.o: %.c | $(OUTPUT)
63+
$(call msg,CC,$@)
64+
$(Q)$(CC) $(CFLAGS) -I$(LIBBPF_SRC) -I$(OUTPUT) -c $(filter %.c,$^) -o $@
65+
66+
$(OUTPUT):
67+
$(call msg,MKDIR,$@)
68+
$(Q)mkdir -p $(OUTPUT)
69+
70+
$(OUTPUT)/vmlinux.h: $(VMLINUX_BTF) | $(OUTPUT) $(BPFTOOL)
71+
$(call msg,GEN,$@)
72+
$(Q)$(BPFTOOL) btf dump file $(VMLINUX_BTF) format c > $@
73+
74+
$(OUTPUT)/libbpf.a: | $(OUTPUT)
75+
$(Q)$(MAKE) $(submake_extras) -C $(LIBBPF_SRC) \
76+
OUTPUT=$(abs_out)/ $(abs_out)/libbpf.a
77+
78+
$(DEFAULT_BPFTOOL):
79+
$(Q)$(MAKE) $(submake_extras) -C ../bpftool \
80+
prefix= OUTPUT=$(abs_out)/ DESTDIR=$(abs_out) install
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (c) 2019 Facebook
3+
#include "vmlinux.h"
4+
#include <bpf_helpers.h>
5+
#include "runqslower.h"
6+
7+
#define TASK_RUNNING 0
8+
9+
#define BPF_F_INDEX_MASK 0xffffffffULL
10+
#define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK
11+
12+
const volatile __u64 min_us = 0;
13+
const volatile pid_t targ_pid = 0;
14+
15+
struct {
16+
__uint(type, BPF_MAP_TYPE_HASH);
17+
__uint(max_entries, 10240);
18+
__type(key, u32);
19+
__type(value, u64);
20+
} start SEC(".maps");
21+
22+
struct {
23+
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
24+
__uint(key_size, sizeof(u32));
25+
__uint(value_size, sizeof(u32));
26+
} events SEC(".maps");
27+
28+
/* record enqueue timestamp */
29+
__always_inline
30+
static int trace_enqueue(u32 tgid, u32 pid)
31+
{
32+
u64 ts;
33+
34+
if (!pid || (targ_pid && targ_pid != pid))
35+
return 0;
36+
37+
ts = bpf_ktime_get_ns();
38+
bpf_map_update_elem(&start, &pid, &ts, 0);
39+
return 0;
40+
}
41+
42+
SEC("tp_btf/sched_wakeup")
43+
int handle__sched_wakeup(u64 *ctx)
44+
{
45+
/* TP_PROTO(struct task_struct *p) */
46+
struct task_struct *p = (void *)ctx[0];
47+
48+
return trace_enqueue(p->tgid, p->pid);
49+
}
50+
51+
SEC("tp_btf/sched_wakeup_new")
52+
int handle__sched_wakeup_new(u64 *ctx)
53+
{
54+
/* TP_PROTO(struct task_struct *p) */
55+
struct task_struct *p = (void *)ctx[0];
56+
57+
return trace_enqueue(p->tgid, p->pid);
58+
}
59+
60+
SEC("tp_btf/sched_switch")
61+
int handle__sched_switch(u64 *ctx)
62+
{
63+
/* TP_PROTO(bool preempt, struct task_struct *prev,
64+
* struct task_struct *next)
65+
*/
66+
struct task_struct *prev = (struct task_struct *)ctx[1];
67+
struct task_struct *next = (struct task_struct *)ctx[2];
68+
struct event event = {};
69+
u64 *tsp, delta_us;
70+
long state;
71+
u32 pid;
72+
73+
/* ivcsw: treat like an enqueue event and store timestamp */
74+
if (prev->state == TASK_RUNNING)
75+
trace_enqueue(prev->tgid, prev->pid);
76+
77+
pid = next->pid;
78+
79+
/* fetch timestamp and calculate delta */
80+
tsp = bpf_map_lookup_elem(&start, &pid);
81+
if (!tsp)
82+
return 0; /* missed enqueue */
83+
84+
delta_us = (bpf_ktime_get_ns() - *tsp) / 1000;
85+
if (min_us && delta_us <= min_us)
86+
return 0;
87+
88+
event.pid = pid;
89+
event.delta_us = delta_us;
90+
bpf_get_current_comm(&event.task, sizeof(event.task));
91+
92+
/* output */
93+
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU,
94+
&event, sizeof(event));
95+
96+
bpf_map_delete_elem(&start, &pid);
97+
return 0;
98+
}
99+
100+
char LICENSE[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)