xref: /aosp_15_r20/external/bcc/examples/cpp/TaskIterator.cc (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker  * Copyright (c) Facebook, Inc.
3*387f9dfdSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License")
4*387f9dfdSAndroid Build Coastguard Worker  *
5*387f9dfdSAndroid Build Coastguard Worker  * Usage:
6*387f9dfdSAndroid Build Coastguard Worker  *   ./TaskIterator
7*387f9dfdSAndroid Build Coastguard Worker  *
8*387f9dfdSAndroid Build Coastguard Worker  * BPF task iterator is available since linux 5.8.
9*387f9dfdSAndroid Build Coastguard Worker  * This example shows how to dump all threads in the system with
10*387f9dfdSAndroid Build Coastguard Worker  * bpf iterator. An example output likes below:
11*387f9dfdSAndroid Build Coastguard Worker  *   tid     comm
12*387f9dfdSAndroid Build Coastguard Worker  *   1       systemd
13*387f9dfdSAndroid Build Coastguard Worker  *   2       kthreadd
14*387f9dfdSAndroid Build Coastguard Worker  *   3       rcu_gp
15*387f9dfdSAndroid Build Coastguard Worker  *   4       rcu_par_gp
16*387f9dfdSAndroid Build Coastguard Worker  *   6       kworker/0:0H
17*387f9dfdSAndroid Build Coastguard Worker  *   ...
18*387f9dfdSAndroid Build Coastguard Worker  *   2613386 sleep
19*387f9dfdSAndroid Build Coastguard Worker  *   2613474 GetCountersCPU6
20*387f9dfdSAndroid Build Coastguard Worker  *   2613587 GetCountersCPU7
21*387f9dfdSAndroid Build Coastguard Worker  *   2613621 CPUThreadPool69
22*387f9dfdSAndroid Build Coastguard Worker  *   2613906 GetCountersCPU5
23*387f9dfdSAndroid Build Coastguard Worker  *   2614140 GetCountersCPU2
24*387f9dfdSAndroid Build Coastguard Worker  *   2614193 CfgrExtension56
25*387f9dfdSAndroid Build Coastguard Worker  *   2614449 ruby-timer-thr
26*387f9dfdSAndroid Build Coastguard Worker  *   2614529 chef-client
27*387f9dfdSAndroid Build Coastguard Worker  *   2615122 systemd-hostnam
28*387f9dfdSAndroid Build Coastguard Worker  *   ...
29*387f9dfdSAndroid Build Coastguard Worker  *   2608477 sudo
30*387f9dfdSAndroid Build Coastguard Worker  *   2608478 TaskIterator
31*387f9dfdSAndroid Build Coastguard Worker  */
32*387f9dfdSAndroid Build Coastguard Worker 
33*387f9dfdSAndroid Build Coastguard Worker #include <unistd.h>
34*387f9dfdSAndroid Build Coastguard Worker #include <fstream>
35*387f9dfdSAndroid Build Coastguard Worker #include <iostream>
36*387f9dfdSAndroid Build Coastguard Worker #include <string>
37*387f9dfdSAndroid Build Coastguard Worker 
38*387f9dfdSAndroid Build Coastguard Worker #include "bcc_version.h"
39*387f9dfdSAndroid Build Coastguard Worker #include "BPF.h"
40*387f9dfdSAndroid Build Coastguard Worker 
41*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"(
42*387f9dfdSAndroid Build Coastguard Worker #include <linux/bpf.h>
43*387f9dfdSAndroid Build Coastguard Worker #include <linux/seq_file.h>
44*387f9dfdSAndroid Build Coastguard Worker #include <linux/sched.h>
45*387f9dfdSAndroid Build Coastguard Worker 
46*387f9dfdSAndroid Build Coastguard Worker /* the structure is defined in .c file, so explicitly define
47*387f9dfdSAndroid Build Coastguard Worker  * the structure here.
48*387f9dfdSAndroid Build Coastguard Worker  */
49*387f9dfdSAndroid Build Coastguard Worker struct bpf_iter__task {
50*387f9dfdSAndroid Build Coastguard Worker   union {
51*387f9dfdSAndroid Build Coastguard Worker     struct bpf_iter_meta *meta;
52*387f9dfdSAndroid Build Coastguard Worker   };
53*387f9dfdSAndroid Build Coastguard Worker   union {
54*387f9dfdSAndroid Build Coastguard Worker     struct task_struct *task;
55*387f9dfdSAndroid Build Coastguard Worker   };
56*387f9dfdSAndroid Build Coastguard Worker };
57*387f9dfdSAndroid Build Coastguard Worker 
58*387f9dfdSAndroid Build Coastguard Worker struct info_t {
59*387f9dfdSAndroid Build Coastguard Worker   int tid;
60*387f9dfdSAndroid Build Coastguard Worker   char comm[TASK_COMM_LEN];
61*387f9dfdSAndroid Build Coastguard Worker };
62*387f9dfdSAndroid Build Coastguard Worker 
63*387f9dfdSAndroid Build Coastguard Worker BPF_ITER(task) {
64*387f9dfdSAndroid Build Coastguard Worker   struct seq_file *seq = ctx->meta->seq;
65*387f9dfdSAndroid Build Coastguard Worker   struct task_struct *task = ctx->task;
66*387f9dfdSAndroid Build Coastguard Worker   struct info_t info = {};
67*387f9dfdSAndroid Build Coastguard Worker 
68*387f9dfdSAndroid Build Coastguard Worker   if (task == (void *)0)
69*387f9dfdSAndroid Build Coastguard Worker     return 0;
70*387f9dfdSAndroid Build Coastguard Worker 
71*387f9dfdSAndroid Build Coastguard Worker   info.tid = task->pid;
72*387f9dfdSAndroid Build Coastguard Worker   __builtin_memcpy(&info.comm, task->comm, sizeof(info.comm));
73*387f9dfdSAndroid Build Coastguard Worker   bpf_seq_write(seq, &info, sizeof(info));
74*387f9dfdSAndroid Build Coastguard Worker 
75*387f9dfdSAndroid Build Coastguard Worker   return 0;
76*387f9dfdSAndroid Build Coastguard Worker }
77*387f9dfdSAndroid Build Coastguard Worker )";
78*387f9dfdSAndroid Build Coastguard Worker 
79*387f9dfdSAndroid Build Coastguard Worker // linux/sched.h
80*387f9dfdSAndroid Build Coastguard Worker #define TASK_COMM_LEN	16
81*387f9dfdSAndroid Build Coastguard Worker 
82*387f9dfdSAndroid Build Coastguard Worker struct info_t {
83*387f9dfdSAndroid Build Coastguard Worker   int tid;
84*387f9dfdSAndroid Build Coastguard Worker   char comm[TASK_COMM_LEN];
85*387f9dfdSAndroid Build Coastguard Worker };
86*387f9dfdSAndroid Build Coastguard Worker 
main()87*387f9dfdSAndroid Build Coastguard Worker int main() {
88*387f9dfdSAndroid Build Coastguard Worker   ebpf::BPF bpf;
89*387f9dfdSAndroid Build Coastguard Worker   auto res = bpf.init(BPF_PROGRAM);
90*387f9dfdSAndroid Build Coastguard Worker   if (!res.ok()) {
91*387f9dfdSAndroid Build Coastguard Worker     std::cerr << res.msg() << std::endl;
92*387f9dfdSAndroid Build Coastguard Worker     return 1;
93*387f9dfdSAndroid Build Coastguard Worker   }
94*387f9dfdSAndroid Build Coastguard Worker 
95*387f9dfdSAndroid Build Coastguard Worker   int prog_fd;
96*387f9dfdSAndroid Build Coastguard Worker   res = bpf.load_func("bpf_iter__task", BPF_PROG_TYPE_TRACING, prog_fd);
97*387f9dfdSAndroid Build Coastguard Worker   if (!res.ok()) {
98*387f9dfdSAndroid Build Coastguard Worker     std::cerr << res.msg() << std::endl;
99*387f9dfdSAndroid Build Coastguard Worker     return 1;
100*387f9dfdSAndroid Build Coastguard Worker   }
101*387f9dfdSAndroid Build Coastguard Worker 
102*387f9dfdSAndroid Build Coastguard Worker   int link_fd = bcc_iter_attach(prog_fd, NULL, 0);
103*387f9dfdSAndroid Build Coastguard Worker   if (link_fd < 0) {
104*387f9dfdSAndroid Build Coastguard Worker     std::cerr << "bcc_iter_attach failed: " << link_fd << std::endl;
105*387f9dfdSAndroid Build Coastguard Worker     return 1;
106*387f9dfdSAndroid Build Coastguard Worker   }
107*387f9dfdSAndroid Build Coastguard Worker 
108*387f9dfdSAndroid Build Coastguard Worker   int iter_fd = bcc_iter_create(link_fd);
109*387f9dfdSAndroid Build Coastguard Worker   if (iter_fd < 0) {
110*387f9dfdSAndroid Build Coastguard Worker     std::cerr << "bcc_iter_create failed: " << iter_fd << std::endl;
111*387f9dfdSAndroid Build Coastguard Worker     close(link_fd);
112*387f9dfdSAndroid Build Coastguard Worker     return 1;
113*387f9dfdSAndroid Build Coastguard Worker   }
114*387f9dfdSAndroid Build Coastguard Worker 
115*387f9dfdSAndroid Build Coastguard Worker   // Header.
116*387f9dfdSAndroid Build Coastguard Worker   printf("tid\tcomm\n");
117*387f9dfdSAndroid Build Coastguard Worker 
118*387f9dfdSAndroid Build Coastguard Worker   struct info_t info[20];
119*387f9dfdSAndroid Build Coastguard Worker   int len, leftover = 0, info_size = 20 * sizeof(struct info_t);
120*387f9dfdSAndroid Build Coastguard Worker   while ((len = read(iter_fd, (char *)info + leftover, info_size - leftover))) {
121*387f9dfdSAndroid Build Coastguard Worker     if (len < 0) {
122*387f9dfdSAndroid Build Coastguard Worker       if (len == -EAGAIN)
123*387f9dfdSAndroid Build Coastguard Worker 	continue;
124*387f9dfdSAndroid Build Coastguard Worker       std::cerr << "read failed: " << len << std::endl;
125*387f9dfdSAndroid Build Coastguard Worker       break;
126*387f9dfdSAndroid Build Coastguard Worker     }
127*387f9dfdSAndroid Build Coastguard Worker 
128*387f9dfdSAndroid Build Coastguard Worker     int num_info = len / sizeof(struct info_t);
129*387f9dfdSAndroid Build Coastguard Worker     for (int i = 0; i < num_info; i++) {
130*387f9dfdSAndroid Build Coastguard Worker       printf("%d\t%s\n", info[i].tid, info[i].comm);
131*387f9dfdSAndroid Build Coastguard Worker     }
132*387f9dfdSAndroid Build Coastguard Worker 
133*387f9dfdSAndroid Build Coastguard Worker     leftover = len % sizeof(struct info_t);
134*387f9dfdSAndroid Build Coastguard Worker     if (num_info > 0)
135*387f9dfdSAndroid Build Coastguard Worker       memcpy(info, (void *)&info[num_info], leftover);
136*387f9dfdSAndroid Build Coastguard Worker   }
137*387f9dfdSAndroid Build Coastguard Worker 
138*387f9dfdSAndroid Build Coastguard Worker   close(iter_fd);
139*387f9dfdSAndroid Build Coastguard Worker   close(link_fd);
140*387f9dfdSAndroid Build Coastguard Worker   return 0;
141*387f9dfdSAndroid Build Coastguard Worker }
142