0001
0002
0003 #include "vmlinux.h"
0004 #include <bpf/bpf_helpers.h>
0005 #include <bpf/bpf_tracing.h>
0006
0007 struct {
0008 __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
0009 __uint(key_size, sizeof(__u32));
0010 __uint(value_size, sizeof(int));
0011 __uint(map_flags, BPF_F_PRESERVE_ELEMS);
0012 } events SEC(".maps");
0013
0014 struct {
0015 __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
0016 __uint(key_size, sizeof(__u32));
0017 __uint(value_size, sizeof(struct bpf_perf_event_value));
0018 __uint(max_entries, 1);
0019 } prev_readings SEC(".maps");
0020
0021 struct {
0022 __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
0023 __uint(key_size, sizeof(__u32));
0024 __uint(value_size, sizeof(struct bpf_perf_event_value));
0025 __uint(max_entries, 1);
0026 } diff_readings SEC(".maps");
0027
0028 SEC("raw_tp/sched_switch")
0029 int BPF_PROG(on_switch)
0030 {
0031 struct bpf_perf_event_value val, *prev_val, *diff_val;
0032 __u32 key = bpf_get_smp_processor_id();
0033 __u32 zero = 0;
0034 long err;
0035
0036 prev_val = bpf_map_lookup_elem(&prev_readings, &zero);
0037 if (!prev_val)
0038 return 0;
0039
0040 diff_val = bpf_map_lookup_elem(&diff_readings, &zero);
0041 if (!diff_val)
0042 return 0;
0043
0044 err = bpf_perf_event_read_value(&events, key, &val, sizeof(val));
0045 if (err)
0046 return 0;
0047
0048 diff_val->counter = val.counter - prev_val->counter;
0049 diff_val->enabled = val.enabled - prev_val->enabled;
0050 diff_val->running = val.running - prev_val->running;
0051 *prev_val = val;
0052 return 0;
0053 }
0054
0055 char LICENSE[] SEC("license") = "Dual BSD/GPL";