xref: /aosp_15_r20/external/bcc/examples/lua/offcputime.lua (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env bcc-lua
2*387f9dfdSAndroid Build Coastguard Worker--[[
3*387f9dfdSAndroid Build Coastguard WorkerCopyright 2016 GitHub, Inc
4*387f9dfdSAndroid Build Coastguard Worker
5*387f9dfdSAndroid Build Coastguard WorkerLicensed under the Apache License, Version 2.0 (the "License");
6*387f9dfdSAndroid Build Coastguard Workeryou may not use this file except in compliance with the License.
7*387f9dfdSAndroid Build Coastguard WorkerYou may obtain a copy of the License at
8*387f9dfdSAndroid Build Coastguard Worker
9*387f9dfdSAndroid Build Coastguard Workerhttp://www.apache.org/licenses/LICENSE-2.0
10*387f9dfdSAndroid Build Coastguard Worker
11*387f9dfdSAndroid Build Coastguard WorkerUnless required by applicable law or agreed to in writing, software
12*387f9dfdSAndroid Build Coastguard Workerdistributed under the License is distributed on an "AS IS" BASIS,
13*387f9dfdSAndroid Build Coastguard WorkerWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*387f9dfdSAndroid Build Coastguard WorkerSee the License for the specific language governing permissions and
15*387f9dfdSAndroid Build Coastguard Workerlimitations under the License.
16*387f9dfdSAndroid Build Coastguard Worker]]
17*387f9dfdSAndroid Build Coastguard Worker
18*387f9dfdSAndroid Build Coastguard Workerlocal program = [[
19*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
20*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h>
21*387f9dfdSAndroid Build Coastguard Worker
22*387f9dfdSAndroid Build Coastguard Worker#define MINBLOCK_US	1
23*387f9dfdSAndroid Build Coastguard Worker
24*387f9dfdSAndroid Build Coastguard Workerstruct key_t {
25*387f9dfdSAndroid Build Coastguard Worker    char name[TASK_COMM_LEN];
26*387f9dfdSAndroid Build Coastguard Worker    int stack_id;
27*387f9dfdSAndroid Build Coastguard Worker};
28*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(counts, struct key_t);
29*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(start, u32);
30*387f9dfdSAndroid Build Coastguard WorkerBPF_STACK_TRACE(stack_traces, 10240);
31*387f9dfdSAndroid Build Coastguard Worker
32*387f9dfdSAndroid Build Coastguard Workerint oncpu(struct pt_regs *ctx, struct task_struct *prev) {
33*387f9dfdSAndroid Build Coastguard Worker    u32 pid;
34*387f9dfdSAndroid Build Coastguard Worker    u64 ts, *tsp;
35*387f9dfdSAndroid Build Coastguard Worker
36*387f9dfdSAndroid Build Coastguard Worker    // record previous thread sleep time
37*387f9dfdSAndroid Build Coastguard Worker    if (FILTER) {
38*387f9dfdSAndroid Build Coastguard Worker        pid = prev->pid;
39*387f9dfdSAndroid Build Coastguard Worker        ts = bpf_ktime_get_ns();
40*387f9dfdSAndroid Build Coastguard Worker        start.update(&pid, &ts);
41*387f9dfdSAndroid Build Coastguard Worker    }
42*387f9dfdSAndroid Build Coastguard Worker
43*387f9dfdSAndroid Build Coastguard Worker    // calculate current thread's delta time
44*387f9dfdSAndroid Build Coastguard Worker    pid = bpf_get_current_pid_tgid();
45*387f9dfdSAndroid Build Coastguard Worker    tsp = start.lookup(&pid);
46*387f9dfdSAndroid Build Coastguard Worker    if (tsp == 0)
47*387f9dfdSAndroid Build Coastguard Worker        return 0;        // missed start or filtered
48*387f9dfdSAndroid Build Coastguard Worker    u64 delta = bpf_ktime_get_ns() - *tsp;
49*387f9dfdSAndroid Build Coastguard Worker    start.delete(&pid);
50*387f9dfdSAndroid Build Coastguard Worker    delta = delta / 1000;
51*387f9dfdSAndroid Build Coastguard Worker    if (delta < MINBLOCK_US)
52*387f9dfdSAndroid Build Coastguard Worker        return 0;
53*387f9dfdSAndroid Build Coastguard Worker
54*387f9dfdSAndroid Build Coastguard Worker    // create map key
55*387f9dfdSAndroid Build Coastguard Worker    u64 zero = 0, *val;
56*387f9dfdSAndroid Build Coastguard Worker    struct key_t key = {};
57*387f9dfdSAndroid Build Coastguard Worker    int stack_flags = 0;
58*387f9dfdSAndroid Build Coastguard Worker
59*387f9dfdSAndroid Build Coastguard Worker    /*
60*387f9dfdSAndroid Build Coastguard Worker    if (!(prev->flags & PF_KTHREAD))
61*387f9dfdSAndroid Build Coastguard Worker      stack_flags |= BPF_F_USER_STACK;
62*387f9dfdSAndroid Build Coastguard Worker    */
63*387f9dfdSAndroid Build Coastguard Worker
64*387f9dfdSAndroid Build Coastguard Worker    bpf_get_current_comm(&key.name, sizeof(key.name));
65*387f9dfdSAndroid Build Coastguard Worker    key.stack_id = stack_traces.get_stackid(ctx, stack_flags);
66*387f9dfdSAndroid Build Coastguard Worker
67*387f9dfdSAndroid Build Coastguard Worker    val = counts.lookup_or_try_init(&key, &zero);
68*387f9dfdSAndroid Build Coastguard Worker    if (val) {
69*387f9dfdSAndroid Build Coastguard Worker        (*val) += delta;
70*387f9dfdSAndroid Build Coastguard Worker    }
71*387f9dfdSAndroid Build Coastguard Worker    return 0;
72*387f9dfdSAndroid Build Coastguard Worker}
73*387f9dfdSAndroid Build Coastguard Worker]]
74*387f9dfdSAndroid Build Coastguard Worker
75*387f9dfdSAndroid Build Coastguard Workerreturn function(BPF, utils)
76*387f9dfdSAndroid Build Coastguard Worker  local ffi = require("ffi")
77*387f9dfdSAndroid Build Coastguard Worker
78*387f9dfdSAndroid Build Coastguard Worker  local parser = utils.argparse("offcputime", "Summarize off-cpu time")
79*387f9dfdSAndroid Build Coastguard Worker  parser:flag("-u --user-only")
80*387f9dfdSAndroid Build Coastguard Worker  parser:option("-p --pid"):convert(tonumber)
81*387f9dfdSAndroid Build Coastguard Worker  parser:flag("-f --folded")
82*387f9dfdSAndroid Build Coastguard Worker  parser:option("-d --duration", "duration to trace for", 9999999):convert(tonumber)
83*387f9dfdSAndroid Build Coastguard Worker
84*387f9dfdSAndroid Build Coastguard Worker  local args = parser:parse()
85*387f9dfdSAndroid Build Coastguard Worker  local ksym = BPF.SymbolCache()
86*387f9dfdSAndroid Build Coastguard Worker  local filter = "1"
87*387f9dfdSAndroid Build Coastguard Worker  local MAXDEPTH = 20
88*387f9dfdSAndroid Build Coastguard Worker
89*387f9dfdSAndroid Build Coastguard Worker  if args.pid then
90*387f9dfdSAndroid Build Coastguard Worker    filter = "pid == %d" % args.pid
91*387f9dfdSAndroid Build Coastguard Worker  elseif args.user_only then
92*387f9dfdSAndroid Build Coastguard Worker    filter = "!(prev->flags & PF_KTHREAD)"
93*387f9dfdSAndroid Build Coastguard Worker  end
94*387f9dfdSAndroid Build Coastguard Worker
95*387f9dfdSAndroid Build Coastguard Worker  local text = program:gsub("FILTER", filter)
96*387f9dfdSAndroid Build Coastguard Worker  local b = BPF:new{text=text}
97*387f9dfdSAndroid Build Coastguard Worker  b:attach_kprobe{event="finish_task_switch", fn_name="oncpu"}
98*387f9dfdSAndroid Build Coastguard Worker
99*387f9dfdSAndroid Build Coastguard Worker  if BPF.num_open_kprobes() == 0 then
100*387f9dfdSAndroid Build Coastguard Worker    print("no functions matched. quitting...")
101*387f9dfdSAndroid Build Coastguard Worker    return
102*387f9dfdSAndroid Build Coastguard Worker  end
103*387f9dfdSAndroid Build Coastguard Worker
104*387f9dfdSAndroid Build Coastguard Worker  print("Sleeping for %d seconds..." % args.duration)
105*387f9dfdSAndroid Build Coastguard Worker  pcall(utils.posix.sleep, args.duration)
106*387f9dfdSAndroid Build Coastguard Worker  print("Tracing...")
107*387f9dfdSAndroid Build Coastguard Worker
108*387f9dfdSAndroid Build Coastguard Worker  local counts = b:get_table("counts")
109*387f9dfdSAndroid Build Coastguard Worker  local stack_traces = b:get_table("stack_traces")
110*387f9dfdSAndroid Build Coastguard Worker
111*387f9dfdSAndroid Build Coastguard Worker  for k, v in counts:items() do
112*387f9dfdSAndroid Build Coastguard Worker    for addr in stack_traces:walk(tonumber(k.stack_id)) do
113*387f9dfdSAndroid Build Coastguard Worker      print("    %-16p %s" % {addr, ksym:resolve(addr)})
114*387f9dfdSAndroid Build Coastguard Worker    end
115*387f9dfdSAndroid Build Coastguard Worker    print("    %-16s %s" % {"-", ffi.string(k.name)})
116*387f9dfdSAndroid Build Coastguard Worker    print("        %d\n" % tonumber(v))
117*387f9dfdSAndroid Build Coastguard Worker  end
118*387f9dfdSAndroid Build Coastguard Workerend
119