1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker * CPUDistribution Show load distribution across CPU cores during a period of
3*387f9dfdSAndroid Build Coastguard Worker * time. For Linux, uses BCC, eBPF. Embedded C.
4*387f9dfdSAndroid Build Coastguard Worker *
5*387f9dfdSAndroid Build Coastguard Worker * Basic example of BCC and kprobes.
6*387f9dfdSAndroid Build Coastguard Worker *
7*387f9dfdSAndroid Build Coastguard Worker * USAGE: CPUDistribution [duration]
8*387f9dfdSAndroid Build Coastguard Worker *
9*387f9dfdSAndroid Build Coastguard Worker * Copyright (c) Facebook, Inc.
10*387f9dfdSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License")
11*387f9dfdSAndroid Build Coastguard Worker */
12*387f9dfdSAndroid Build Coastguard Worker
13*387f9dfdSAndroid Build Coastguard Worker #include <unistd.h>
14*387f9dfdSAndroid Build Coastguard Worker #include <cstdlib>
15*387f9dfdSAndroid Build Coastguard Worker #include <iomanip>
16*387f9dfdSAndroid Build Coastguard Worker #include <iostream>
17*387f9dfdSAndroid Build Coastguard Worker #include <string>
18*387f9dfdSAndroid Build Coastguard Worker
19*387f9dfdSAndroid Build Coastguard Worker #include "BPF.h"
20*387f9dfdSAndroid Build Coastguard Worker
21*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"(
22*387f9dfdSAndroid Build Coastguard Worker #include <linux/sched.h>
23*387f9dfdSAndroid Build Coastguard Worker #include <uapi/linux/ptrace.h>
24*387f9dfdSAndroid Build Coastguard Worker
25*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(pid_to_cpu, pid_t, int);
26*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(pid_to_ts, pid_t, uint64_t);
27*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(cpu_time, int, uint64_t);
28*387f9dfdSAndroid Build Coastguard Worker
29*387f9dfdSAndroid Build Coastguard Worker int task_switch_event(struct pt_regs *ctx, struct task_struct *prev) {
30*387f9dfdSAndroid Build Coastguard Worker pid_t prev_pid = prev->pid;
31*387f9dfdSAndroid Build Coastguard Worker int* prev_cpu = pid_to_cpu.lookup(&prev_pid);
32*387f9dfdSAndroid Build Coastguard Worker uint64_t* prev_ts = pid_to_ts.lookup(&prev_pid);
33*387f9dfdSAndroid Build Coastguard Worker
34*387f9dfdSAndroid Build Coastguard Worker pid_t cur_pid = bpf_get_current_pid_tgid();
35*387f9dfdSAndroid Build Coastguard Worker int cur_cpu = bpf_get_smp_processor_id();
36*387f9dfdSAndroid Build Coastguard Worker uint64_t cur_ts = bpf_ktime_get_ns();
37*387f9dfdSAndroid Build Coastguard Worker
38*387f9dfdSAndroid Build Coastguard Worker uint64_t this_cpu_time = 0;
39*387f9dfdSAndroid Build Coastguard Worker if (prev_ts) {
40*387f9dfdSAndroid Build Coastguard Worker pid_to_ts.delete(&prev_pid);
41*387f9dfdSAndroid Build Coastguard Worker this_cpu_time = (cur_ts - *prev_ts);
42*387f9dfdSAndroid Build Coastguard Worker }
43*387f9dfdSAndroid Build Coastguard Worker if (prev_cpu) {
44*387f9dfdSAndroid Build Coastguard Worker pid_to_cpu.delete(&prev_pid);
45*387f9dfdSAndroid Build Coastguard Worker if (this_cpu_time > 0) {
46*387f9dfdSAndroid Build Coastguard Worker int cpu_key = *prev_cpu;
47*387f9dfdSAndroid Build Coastguard Worker uint64_t* history_time = cpu_time.lookup(&cpu_key);
48*387f9dfdSAndroid Build Coastguard Worker if (history_time)
49*387f9dfdSAndroid Build Coastguard Worker this_cpu_time += *history_time;
50*387f9dfdSAndroid Build Coastguard Worker cpu_time.update(&cpu_key, &this_cpu_time);
51*387f9dfdSAndroid Build Coastguard Worker }
52*387f9dfdSAndroid Build Coastguard Worker }
53*387f9dfdSAndroid Build Coastguard Worker
54*387f9dfdSAndroid Build Coastguard Worker pid_to_cpu.update(&cur_pid, &cur_cpu);
55*387f9dfdSAndroid Build Coastguard Worker pid_to_ts.update(&cur_pid, &cur_ts);
56*387f9dfdSAndroid Build Coastguard Worker
57*387f9dfdSAndroid Build Coastguard Worker return 0;
58*387f9dfdSAndroid Build Coastguard Worker }
59*387f9dfdSAndroid Build Coastguard Worker )";
60*387f9dfdSAndroid Build Coastguard Worker
main(int argc,char ** argv)61*387f9dfdSAndroid Build Coastguard Worker int main(int argc, char** argv) {
62*387f9dfdSAndroid Build Coastguard Worker ebpf::BPF bpf;
63*387f9dfdSAndroid Build Coastguard Worker auto init_res = bpf.init(BPF_PROGRAM);
64*387f9dfdSAndroid Build Coastguard Worker if (!init_res.ok()) {
65*387f9dfdSAndroid Build Coastguard Worker std::cerr << init_res.msg() << std::endl;
66*387f9dfdSAndroid Build Coastguard Worker return 1;
67*387f9dfdSAndroid Build Coastguard Worker }
68*387f9dfdSAndroid Build Coastguard Worker
69*387f9dfdSAndroid Build Coastguard Worker auto attach_res =
70*387f9dfdSAndroid Build Coastguard Worker bpf.attach_kprobe("finish_task_switch", "task_switch_event");
71*387f9dfdSAndroid Build Coastguard Worker if (!attach_res.ok()) {
72*387f9dfdSAndroid Build Coastguard Worker std::cerr << attach_res.msg() << std::endl;
73*387f9dfdSAndroid Build Coastguard Worker return 1;
74*387f9dfdSAndroid Build Coastguard Worker }
75*387f9dfdSAndroid Build Coastguard Worker
76*387f9dfdSAndroid Build Coastguard Worker int probe_time = 10;
77*387f9dfdSAndroid Build Coastguard Worker if (argc == 2) {
78*387f9dfdSAndroid Build Coastguard Worker probe_time = atoi(argv[1]);
79*387f9dfdSAndroid Build Coastguard Worker }
80*387f9dfdSAndroid Build Coastguard Worker std::cout << "Probing for " << probe_time << " seconds" << std::endl;
81*387f9dfdSAndroid Build Coastguard Worker sleep(probe_time);
82*387f9dfdSAndroid Build Coastguard Worker
83*387f9dfdSAndroid Build Coastguard Worker auto table = bpf.get_hash_table<int, uint64_t>("cpu_time");
84*387f9dfdSAndroid Build Coastguard Worker auto num_cores = sysconf(_SC_NPROCESSORS_ONLN);
85*387f9dfdSAndroid Build Coastguard Worker for (int i = 0; i < num_cores; i++) {
86*387f9dfdSAndroid Build Coastguard Worker std::cout << "CPU " << std::setw(2) << i << " worked for ";
87*387f9dfdSAndroid Build Coastguard Worker std::cout << (table[i] / 1000000.0) << " ms." << std::endl;
88*387f9dfdSAndroid Build Coastguard Worker }
89*387f9dfdSAndroid Build Coastguard Worker
90*387f9dfdSAndroid Build Coastguard Worker auto detach_res = bpf.detach_kprobe("finish_task_switch");
91*387f9dfdSAndroid Build Coastguard Worker if (!detach_res.ok()) {
92*387f9dfdSAndroid Build Coastguard Worker std::cerr << detach_res.msg() << std::endl;
93*387f9dfdSAndroid Build Coastguard Worker return 1;
94*387f9dfdSAndroid Build Coastguard Worker }
95*387f9dfdSAndroid Build Coastguard Worker
96*387f9dfdSAndroid Build Coastguard Worker return 0;
97*387f9dfdSAndroid Build Coastguard Worker }
98