1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright (c) 2018 Facebook |
3 | |
4 | #include <vmlinux.h> |
5 | #include <bpf/bpf_helpers.h> |
6 | |
7 | #ifndef PERF_MAX_STACK_DEPTH |
8 | #define PERF_MAX_STACK_DEPTH 127 |
9 | #endif |
10 | |
11 | struct { |
12 | __uint(type, BPF_MAP_TYPE_ARRAY); |
13 | __uint(max_entries, 1); |
14 | __type(key, __u32); |
15 | __type(value, __u32); |
16 | } control_map SEC(".maps" ); |
17 | |
18 | struct { |
19 | __uint(type, BPF_MAP_TYPE_HASH); |
20 | __uint(max_entries, 16384); |
21 | __type(key, __u32); |
22 | __type(value, __u32); |
23 | } stackid_hmap SEC(".maps" ); |
24 | |
25 | typedef __u64 stack_trace_t[PERF_MAX_STACK_DEPTH]; |
26 | |
27 | struct { |
28 | __uint(type, BPF_MAP_TYPE_STACK_TRACE); |
29 | __uint(max_entries, 16384); |
30 | __type(key, __u32); |
31 | __type(value, stack_trace_t); |
32 | } stackmap SEC(".maps" ); |
33 | |
34 | struct { |
35 | __uint(type, BPF_MAP_TYPE_ARRAY); |
36 | __uint(max_entries, 16384); |
37 | __type(key, __u32); |
38 | __type(value, stack_trace_t); |
39 | } stack_amap SEC(".maps" ); |
40 | |
41 | /* taken from /sys/kernel/tracing/events/sched/sched_switch/format */ |
42 | struct sched_switch_args { |
43 | unsigned long long pad; |
44 | char prev_comm[TASK_COMM_LEN]; |
45 | int prev_pid; |
46 | int prev_prio; |
47 | long long prev_state; |
48 | char next_comm[TASK_COMM_LEN]; |
49 | int next_pid; |
50 | int next_prio; |
51 | }; |
52 | |
53 | SEC("tracepoint/sched/sched_switch" ) |
54 | int oncpu(struct sched_switch_args *ctx) |
55 | { |
56 | __u32 max_len = PERF_MAX_STACK_DEPTH * sizeof(__u64); |
57 | __u32 key = 0, val = 0, *value_p; |
58 | void *stack_p; |
59 | |
60 | value_p = bpf_map_lookup_elem(&control_map, &key); |
61 | if (value_p && *value_p) |
62 | return 0; /* skip if non-zero *value_p */ |
63 | |
64 | /* The size of stackmap and stackid_hmap should be the same */ |
65 | key = bpf_get_stackid(ctx, &stackmap, 0); |
66 | if ((int)key >= 0) { |
67 | bpf_map_update_elem(&stackid_hmap, &key, &val, 0); |
68 | stack_p = bpf_map_lookup_elem(&stack_amap, &key); |
69 | if (stack_p) |
70 | bpf_get_stack(ctx, stack_p, max_len, 0); |
71 | } |
72 | |
73 | return 0; |
74 | } |
75 | |
76 | char _license[] SEC("license" ) = "GPL" ; |
77 | |