1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 // Copyright (c) 2021 Google
4 #include <bpf/bpf_helpers.h>
5 #include <bpf/bpf_tracing.h>
7 // This should be in sync with "util/ftrace.h"
11 __uint(type, BPF_MAP_TYPE_HASH);
12 __uint(key_size, sizeof(__u64));
13 __uint(value_size, sizeof(__u64));
14 __uint(max_entries, 10000);
15 } functime SEC(".maps");
18 __uint(type, BPF_MAP_TYPE_HASH);
19 __uint(key_size, sizeof(__u32));
20 __uint(value_size, sizeof(__u8));
21 __uint(max_entries, 1);
22 } cpu_filter SEC(".maps");
25 __uint(type, BPF_MAP_TYPE_HASH);
26 __uint(key_size, sizeof(__u32));
27 __uint(value_size, sizeof(__u8));
28 __uint(max_entries, 1);
29 } task_filter SEC(".maps");
32 __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
33 __uint(key_size, sizeof(__u32));
34 __uint(value_size, sizeof(__u64));
35 __uint(max_entries, NUM_BUCKET);
36 } latency SEC(".maps");
47 const volatile int has_cpu = 0;
48 const volatile int has_task = 0;
49 const volatile int use_nsec = 0;
50 const volatile unsigned int bucket_range;
51 const volatile unsigned int min_latency;
52 const volatile unsigned int max_latency;
55 int BPF_PROG(func_begin)
62 key = bpf_get_current_pid_tgid();
65 __u32 cpu = bpf_get_smp_processor_id();
68 ok = bpf_map_lookup_elem(&cpu_filter, &cpu);
74 __u32 pid = key & 0xffffffff;
77 ok = bpf_map_lookup_elem(&task_filter, &pid);
82 now = bpf_ktime_get_ns();
84 // overwrite timestamp for nested functions
85 bpf_map_update_elem(&functime, &key, &now, BPF_ANY);
90 int BPF_PROG(func_end)
94 __u64 cmp_base = use_nsec ? 1 : 1000;
99 tid = bpf_get_current_pid_tgid();
101 start = bpf_map_lookup_elem(&functime, &tid);
103 __s64 delta = bpf_ktime_get_ns() - *start;
107 bpf_map_delete_elem(&functime, &tid);
112 if (bucket_range != 0) {
115 if (min_latency > 0) {
116 if (delta > min_latency)
117 delta -= min_latency;
122 // Less than 1 unit (ms or ns), or, in the future,
123 // than the min latency desired.
124 if (delta > 0) { // 1st entry: [ 1 unit .. bucket_range units )
125 // clang 12 doesn't like s64 / u32 division
126 key = (__u64)delta / bucket_range + 1;
127 if (key >= NUM_BUCKET ||
128 delta >= max_latency - min_latency)
129 key = NUM_BUCKET - 1;
132 delta += min_latency;
135 // calculate index using delta
136 for (key = 0; key < (NUM_BUCKET - 1); key++) {
137 if (delta < (cmp_base << key))
142 hist = bpf_map_lookup_elem(&latency, &key);
148 if (bucket_range == 0)
151 __sync_fetch_and_add(&total, delta);
152 __sync_fetch_and_add(&count, 1);