0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/version.h>
0009 #include <linux/ptrace.h>
0010 #include <uapi/linux/bpf.h>
0011 #include <bpf/bpf_helpers.h>
0012
0013 #define MAX_ENTRIES 20
0014 #define MAX_CPU 4
0015
0016
0017
0018
0019
0020
0021 struct {
0022 __uint(type, BPF_MAP_TYPE_ARRAY);
0023 __type(key, int);
0024 __type(value, u64);
0025 __uint(max_entries, MAX_CPU);
0026 } my_map SEC(".maps");
0027
0028 SEC("kprobe/trace_preempt_off")
0029 int bpf_prog1(struct pt_regs *ctx)
0030 {
0031 int cpu = bpf_get_smp_processor_id();
0032 u64 *ts = bpf_map_lookup_elem(&my_map, &cpu);
0033
0034 if (ts)
0035 *ts = bpf_ktime_get_ns();
0036
0037 return 0;
0038 }
0039
0040 static unsigned int log2(unsigned int v)
0041 {
0042 unsigned int r;
0043 unsigned int shift;
0044
0045 r = (v > 0xFFFF) << 4; v >>= r;
0046 shift = (v > 0xFF) << 3; v >>= shift; r |= shift;
0047 shift = (v > 0xF) << 2; v >>= shift; r |= shift;
0048 shift = (v > 0x3) << 1; v >>= shift; r |= shift;
0049 r |= (v >> 1);
0050
0051 return r;
0052 }
0053
0054 static unsigned int log2l(unsigned long v)
0055 {
0056 unsigned int hi = v >> 32;
0057
0058 if (hi)
0059 return log2(hi) + 32;
0060 else
0061 return log2(v);
0062 }
0063
0064 struct {
0065 __uint(type, BPF_MAP_TYPE_ARRAY);
0066 __type(key, int);
0067 __type(value, long);
0068 __uint(max_entries, MAX_CPU * MAX_ENTRIES);
0069 } my_lat SEC(".maps");
0070
0071 SEC("kprobe/trace_preempt_on")
0072 int bpf_prog2(struct pt_regs *ctx)
0073 {
0074 u64 *ts, cur_ts, delta;
0075 int key, cpu;
0076 long *val;
0077
0078 cpu = bpf_get_smp_processor_id();
0079 ts = bpf_map_lookup_elem(&my_map, &cpu);
0080 if (!ts)
0081 return 0;
0082
0083 cur_ts = bpf_ktime_get_ns();
0084 delta = log2l(cur_ts - *ts);
0085
0086 if (delta > MAX_ENTRIES - 1)
0087 delta = MAX_ENTRIES - 1;
0088
0089 key = cpu * MAX_ENTRIES + delta;
0090 val = bpf_map_lookup_elem(&my_lat, &key);
0091 if (val)
0092 __sync_fetch_and_add((long *)val, 1);
0093
0094 return 0;
0095
0096 }
0097
0098 char _license[] SEC("license") = "GPL";
0099 u32 _version SEC("version") = LINUX_VERSION_CODE;