xref: /aosp_15_r20/external/bcc/examples/cpp/FollyRequestContextSwitch.cc (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker  * FollyRequestContextSwitch Monitor RequestContext switch events for any binary
3*387f9dfdSAndroid Build Coastguard Worker  *                           uses the class from [folly](http://bit.ly/2h6S1yx).
4*387f9dfdSAndroid Build Coastguard Worker  *                           For Linux, uses BCC, eBPF. Embedded C.
5*387f9dfdSAndroid Build Coastguard Worker  *
6*387f9dfdSAndroid Build Coastguard Worker  * Basic example of using USDT with BCC.
7*387f9dfdSAndroid Build Coastguard Worker  *
8*387f9dfdSAndroid Build Coastguard Worker  * USAGE: FollyRequestContextSwitch PATH_TO_BINARY
9*387f9dfdSAndroid Build Coastguard Worker  *
10*387f9dfdSAndroid Build Coastguard Worker  * Copyright (c) Facebook, Inc.
11*387f9dfdSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License")
12*387f9dfdSAndroid Build Coastguard Worker  */
13*387f9dfdSAndroid Build Coastguard Worker 
14*387f9dfdSAndroid Build Coastguard Worker #include <signal.h>
15*387f9dfdSAndroid Build Coastguard Worker #include <functional>
16*387f9dfdSAndroid Build Coastguard Worker #include <iostream>
17*387f9dfdSAndroid Build Coastguard Worker #include <vector>
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 struct event_t {
26*387f9dfdSAndroid Build Coastguard Worker   int pid;
27*387f9dfdSAndroid Build Coastguard Worker   char name[16];
28*387f9dfdSAndroid Build Coastguard Worker   uint64_t old_addr;
29*387f9dfdSAndroid Build Coastguard Worker   uint64_t new_addr;
30*387f9dfdSAndroid Build Coastguard Worker };
31*387f9dfdSAndroid Build Coastguard Worker 
32*387f9dfdSAndroid Build Coastguard Worker BPF_PERF_OUTPUT(events);
33*387f9dfdSAndroid Build Coastguard Worker 
34*387f9dfdSAndroid Build Coastguard Worker int on_context_switch(struct pt_regs *ctx) {
35*387f9dfdSAndroid Build Coastguard Worker   struct event_t event = {};
36*387f9dfdSAndroid Build Coastguard Worker 
37*387f9dfdSAndroid Build Coastguard Worker   event.pid = bpf_get_current_pid_tgid();
38*387f9dfdSAndroid Build Coastguard Worker   bpf_get_current_comm(&event.name, sizeof(event.name));
39*387f9dfdSAndroid Build Coastguard Worker 
40*387f9dfdSAndroid Build Coastguard Worker   bpf_usdt_readarg(1, ctx, &event.old_addr);
41*387f9dfdSAndroid Build Coastguard Worker   bpf_usdt_readarg(2, ctx, &event.new_addr);
42*387f9dfdSAndroid Build Coastguard Worker 
43*387f9dfdSAndroid Build Coastguard Worker   events.perf_submit(ctx, &event, sizeof(event));
44*387f9dfdSAndroid Build Coastguard Worker   return 0;
45*387f9dfdSAndroid Build Coastguard Worker }
46*387f9dfdSAndroid Build Coastguard Worker )";
47*387f9dfdSAndroid Build Coastguard Worker 
48*387f9dfdSAndroid Build Coastguard Worker // Define the same struct to use in user space.
49*387f9dfdSAndroid Build Coastguard Worker struct event_t {
50*387f9dfdSAndroid Build Coastguard Worker   int pid;
51*387f9dfdSAndroid Build Coastguard Worker   char name[16];
52*387f9dfdSAndroid Build Coastguard Worker   uint64_t old_addr;
53*387f9dfdSAndroid Build Coastguard Worker   uint64_t new_addr;
54*387f9dfdSAndroid Build Coastguard Worker };
55*387f9dfdSAndroid Build Coastguard Worker 
handle_output(void * cb_cookie,void * data,int data_size)56*387f9dfdSAndroid Build Coastguard Worker void handle_output(void* cb_cookie, void* data, int data_size) {
57*387f9dfdSAndroid Build Coastguard Worker   auto event = static_cast<event_t*>(data);
58*387f9dfdSAndroid Build Coastguard Worker   std::cout << "PID " << event->pid << " (" << event->name << ") ";
59*387f9dfdSAndroid Build Coastguard Worker   std::cout << "folly::RequestContext switch from " << event->old_addr << " to "
60*387f9dfdSAndroid Build Coastguard Worker             << event->new_addr << std::endl;
61*387f9dfdSAndroid Build Coastguard Worker }
62*387f9dfdSAndroid Build Coastguard Worker 
63*387f9dfdSAndroid Build Coastguard Worker std::function<void(int)> shutdown_handler;
64*387f9dfdSAndroid Build Coastguard Worker 
signal_handler(int s)65*387f9dfdSAndroid Build Coastguard Worker void signal_handler(int s) { shutdown_handler(s); }
66*387f9dfdSAndroid Build Coastguard Worker 
main(int argc,char ** argv)67*387f9dfdSAndroid Build Coastguard Worker int main(int argc, char** argv) {
68*387f9dfdSAndroid Build Coastguard Worker   std::string binary;
69*387f9dfdSAndroid Build Coastguard Worker   pid_t pid = -1;
70*387f9dfdSAndroid Build Coastguard Worker   for (int i = 0; i < argc; i++) {
71*387f9dfdSAndroid Build Coastguard Worker     if (strncmp(argv[i], "--pid", 5) == 0) {
72*387f9dfdSAndroid Build Coastguard Worker       pid = std::stoi(argv[i + 1]);
73*387f9dfdSAndroid Build Coastguard Worker       i++;
74*387f9dfdSAndroid Build Coastguard Worker       continue;
75*387f9dfdSAndroid Build Coastguard Worker     }
76*387f9dfdSAndroid Build Coastguard Worker     if (strncmp(argv[i], "--binary", 8) == 0) {
77*387f9dfdSAndroid Build Coastguard Worker       binary = argv[i + 1];
78*387f9dfdSAndroid Build Coastguard Worker       i++;
79*387f9dfdSAndroid Build Coastguard Worker       continue;
80*387f9dfdSAndroid Build Coastguard Worker     }
81*387f9dfdSAndroid Build Coastguard Worker   }
82*387f9dfdSAndroid Build Coastguard Worker 
83*387f9dfdSAndroid Build Coastguard Worker   if (pid <= 0 && binary.empty()) {
84*387f9dfdSAndroid Build Coastguard Worker     std::cout << "Must specify at least one of binary or PID:" << std::endl
85*387f9dfdSAndroid Build Coastguard Worker               << "FollyRequestContextSwitch [--pid PID] [--binary BINARY]"
86*387f9dfdSAndroid Build Coastguard Worker               << std::endl;
87*387f9dfdSAndroid Build Coastguard Worker     exit(1);
88*387f9dfdSAndroid Build Coastguard Worker   }
89*387f9dfdSAndroid Build Coastguard Worker 
90*387f9dfdSAndroid Build Coastguard Worker   ebpf::USDT u(binary, pid, "folly", "request_context_switch_before",
91*387f9dfdSAndroid Build Coastguard Worker                "on_context_switch");
92*387f9dfdSAndroid Build Coastguard Worker 
93*387f9dfdSAndroid Build Coastguard Worker   ebpf::BPF* bpf = new ebpf::BPF();
94*387f9dfdSAndroid Build Coastguard Worker 
95*387f9dfdSAndroid Build Coastguard Worker   auto init_res = bpf->init(BPF_PROGRAM, {}, {u});
96*387f9dfdSAndroid Build Coastguard Worker   if (!init_res.ok()) {
97*387f9dfdSAndroid Build Coastguard Worker     std::cerr << init_res.msg() << std::endl;
98*387f9dfdSAndroid Build Coastguard Worker     return 1;
99*387f9dfdSAndroid Build Coastguard Worker   }
100*387f9dfdSAndroid Build Coastguard Worker 
101*387f9dfdSAndroid Build Coastguard Worker   auto attach_res = bpf->attach_usdt_all();
102*387f9dfdSAndroid Build Coastguard Worker   if (!attach_res.ok()) {
103*387f9dfdSAndroid Build Coastguard Worker     std::cerr << attach_res.msg() << std::endl;
104*387f9dfdSAndroid Build Coastguard Worker     return 1;
105*387f9dfdSAndroid Build Coastguard Worker   } else {
106*387f9dfdSAndroid Build Coastguard Worker     std::cout << "Attached to USDT " << u;
107*387f9dfdSAndroid Build Coastguard Worker   }
108*387f9dfdSAndroid Build Coastguard Worker 
109*387f9dfdSAndroid Build Coastguard Worker   auto open_res = bpf->open_perf_buffer("events", &handle_output);
110*387f9dfdSAndroid Build Coastguard Worker   if (!open_res.ok()) {
111*387f9dfdSAndroid Build Coastguard Worker     std::cerr << open_res.msg() << std::endl;
112*387f9dfdSAndroid Build Coastguard Worker     return 1;
113*387f9dfdSAndroid Build Coastguard Worker   }
114*387f9dfdSAndroid Build Coastguard Worker 
115*387f9dfdSAndroid Build Coastguard Worker   shutdown_handler = [&](int s) {
116*387f9dfdSAndroid Build Coastguard Worker     std::cerr << "Terminating..." << std::endl;
117*387f9dfdSAndroid Build Coastguard Worker     bpf->detach_usdt_all();
118*387f9dfdSAndroid Build Coastguard Worker     delete bpf;
119*387f9dfdSAndroid Build Coastguard Worker     exit(0);
120*387f9dfdSAndroid Build Coastguard Worker   };
121*387f9dfdSAndroid Build Coastguard Worker   signal(SIGINT, signal_handler);
122*387f9dfdSAndroid Build Coastguard Worker 
123*387f9dfdSAndroid Build Coastguard Worker   std::cout << "Started tracing, hit Ctrl-C to terminate." << std::endl;
124*387f9dfdSAndroid Build Coastguard Worker   auto perf_buffer = bpf->get_perf_buffer("events");
125*387f9dfdSAndroid Build Coastguard Worker   if (perf_buffer)
126*387f9dfdSAndroid Build Coastguard Worker     while (true)
127*387f9dfdSAndroid Build Coastguard Worker       // 100ms timeout
128*387f9dfdSAndroid Build Coastguard Worker       perf_buffer->poll(100);
129*387f9dfdSAndroid Build Coastguard Worker 
130*387f9dfdSAndroid Build Coastguard Worker   return 0;
131*387f9dfdSAndroid Build Coastguard Worker }
132