^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // Copyright (c) 2019 Facebook
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include "vmlinux.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <bpf/bpf_helpers.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include "runqslower.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #define TASK_RUNNING 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #define BPF_F_CURRENT_CPU 0xffffffffULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) const volatile __u64 min_us = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) const volatile pid_t targ_pid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) __uint(type, BPF_MAP_TYPE_HASH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) __uint(max_entries, 10240);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) __type(key, u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) __type(value, u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) } start SEC(".maps");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) __uint(key_size, sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) __uint(value_size, sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) } events SEC(".maps");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* record enqueue timestamp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) __always_inline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static int trace_enqueue(u32 tgid, u32 pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) u64 ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if (!pid || (targ_pid && targ_pid != pid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) ts = bpf_ktime_get_ns();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) bpf_map_update_elem(&start, &pid, &ts, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) SEC("tp_btf/sched_wakeup")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int handle__sched_wakeup(u64 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /* TP_PROTO(struct task_struct *p) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct task_struct *p = (void *)ctx[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return trace_enqueue(p->tgid, p->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) SEC("tp_btf/sched_wakeup_new")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int handle__sched_wakeup_new(u64 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /* TP_PROTO(struct task_struct *p) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct task_struct *p = (void *)ctx[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return trace_enqueue(p->tgid, p->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) SEC("tp_btf/sched_switch")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) int handle__sched_switch(u64 *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* TP_PROTO(bool preempt, struct task_struct *prev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * struct task_struct *next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct task_struct *prev = (struct task_struct *)ctx[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct task_struct *next = (struct task_struct *)ctx[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct event event = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) u64 *tsp, delta_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) long state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) u32 pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* ivcsw: treat like an enqueue event and store timestamp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (prev->state == TASK_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) trace_enqueue(prev->tgid, prev->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) pid = next->pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* fetch timestamp and calculate delta */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) tsp = bpf_map_lookup_elem(&start, &pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (!tsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return 0; /* missed enqueue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) delta_us = (bpf_ktime_get_ns() - *tsp) / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (min_us && delta_us <= min_us)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) event.pid = pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) event.delta_us = delta_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) bpf_get_current_comm(&event.task, sizeof(event.task));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) &event, sizeof(event));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) bpf_map_delete_elem(&start, &pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) char LICENSE[] SEC("license") = "GPL";