1*eafedbc7SAlice Ryhl // SPDX-License-Identifier: GPL-2.0 2*eafedbc7SAlice Ryhl 3*eafedbc7SAlice Ryhl // Copyright (C) 2025 Google LLC. 4*eafedbc7SAlice Ryhl 5*eafedbc7SAlice Ryhl //! Keep track of statistics for binder_logs. 6*eafedbc7SAlice Ryhl 7*eafedbc7SAlice Ryhl use crate::defs::*; 8*eafedbc7SAlice Ryhl use core::sync::atomic::{AtomicU32, Ordering::Relaxed}; 9*eafedbc7SAlice Ryhl use kernel::{ioctl::_IOC_NR, seq_file::SeqFile, seq_print}; 10*eafedbc7SAlice Ryhl 11*eafedbc7SAlice Ryhl const BC_COUNT: usize = _IOC_NR(BC_REPLY_SG) as usize + 1; 12*eafedbc7SAlice Ryhl const BR_COUNT: usize = _IOC_NR(BR_TRANSACTION_PENDING_FROZEN) as usize + 1; 13*eafedbc7SAlice Ryhl 14*eafedbc7SAlice Ryhl pub(crate) static GLOBAL_STATS: BinderStats = BinderStats::new(); 15*eafedbc7SAlice Ryhl 16*eafedbc7SAlice Ryhl pub(crate) struct BinderStats { 17*eafedbc7SAlice Ryhl bc: [AtomicU32; BC_COUNT], 18*eafedbc7SAlice Ryhl br: [AtomicU32; BR_COUNT], 19*eafedbc7SAlice Ryhl } 20*eafedbc7SAlice Ryhl 21*eafedbc7SAlice Ryhl impl BinderStats { 22*eafedbc7SAlice Ryhl pub(crate) const fn new() -> Self { 23*eafedbc7SAlice Ryhl #[expect(clippy::declare_interior_mutable_const)] 24*eafedbc7SAlice Ryhl const ZERO: AtomicU32 = AtomicU32::new(0); 25*eafedbc7SAlice Ryhl 26*eafedbc7SAlice Ryhl Self { 27*eafedbc7SAlice Ryhl bc: [ZERO; BC_COUNT], 28*eafedbc7SAlice Ryhl br: [ZERO; BR_COUNT], 29*eafedbc7SAlice Ryhl } 30*eafedbc7SAlice Ryhl } 31*eafedbc7SAlice Ryhl 32*eafedbc7SAlice Ryhl pub(crate) fn inc_bc(&self, bc: u32) { 33*eafedbc7SAlice Ryhl let idx = _IOC_NR(bc) as usize; 34*eafedbc7SAlice Ryhl if let Some(bc_ref) = self.bc.get(idx) { 35*eafedbc7SAlice Ryhl bc_ref.fetch_add(1, Relaxed); 36*eafedbc7SAlice Ryhl } 37*eafedbc7SAlice Ryhl } 38*eafedbc7SAlice Ryhl 39*eafedbc7SAlice Ryhl pub(crate) fn inc_br(&self, br: u32) { 40*eafedbc7SAlice Ryhl let idx = _IOC_NR(br) as usize; 41*eafedbc7SAlice Ryhl if let Some(br_ref) = self.br.get(idx) { 42*eafedbc7SAlice Ryhl br_ref.fetch_add(1, Relaxed); 43*eafedbc7SAlice Ryhl } 44*eafedbc7SAlice Ryhl } 45*eafedbc7SAlice Ryhl 46*eafedbc7SAlice Ryhl pub(crate) fn debug_print(&self, prefix: &str, m: &SeqFile) { 47*eafedbc7SAlice Ryhl for (i, cnt) in self.bc.iter().enumerate() { 48*eafedbc7SAlice Ryhl let cnt = cnt.load(Relaxed); 49*eafedbc7SAlice Ryhl if cnt > 0 { 50*eafedbc7SAlice Ryhl seq_print!(m, "{}{}: {}\n", prefix, command_string(i), cnt); 51*eafedbc7SAlice Ryhl } 52*eafedbc7SAlice Ryhl } 53*eafedbc7SAlice Ryhl for (i, cnt) in self.br.iter().enumerate() { 54*eafedbc7SAlice Ryhl let cnt = cnt.load(Relaxed); 55*eafedbc7SAlice Ryhl if cnt > 0 { 56*eafedbc7SAlice Ryhl seq_print!(m, "{}{}: {}\n", prefix, return_string(i), cnt); 57*eafedbc7SAlice Ryhl } 58*eafedbc7SAlice Ryhl } 59*eafedbc7SAlice Ryhl } 60*eafedbc7SAlice Ryhl } 61*eafedbc7SAlice Ryhl 62*eafedbc7SAlice Ryhl mod strings { 63*eafedbc7SAlice Ryhl use core::str::from_utf8_unchecked; 64*eafedbc7SAlice Ryhl use kernel::str::CStr; 65*eafedbc7SAlice Ryhl 66*eafedbc7SAlice Ryhl extern "C" { 67*eafedbc7SAlice Ryhl static binder_command_strings: [*const u8; super::BC_COUNT]; 68*eafedbc7SAlice Ryhl static binder_return_strings: [*const u8; super::BR_COUNT]; 69*eafedbc7SAlice Ryhl } 70*eafedbc7SAlice Ryhl 71*eafedbc7SAlice Ryhl pub(super) fn command_string(i: usize) -> &'static str { 72*eafedbc7SAlice Ryhl // SAFETY: Accessing `binder_command_strings` is always safe. 73*eafedbc7SAlice Ryhl let c_str_ptr = unsafe { binder_command_strings[i] }; 74*eafedbc7SAlice Ryhl // SAFETY: The `binder_command_strings` array only contains nul-terminated strings. 75*eafedbc7SAlice Ryhl let bytes = unsafe { CStr::from_char_ptr(c_str_ptr) }.as_bytes(); 76*eafedbc7SAlice Ryhl // SAFETY: The `binder_command_strings` array only contains strings with ascii-chars. 77*eafedbc7SAlice Ryhl unsafe { from_utf8_unchecked(bytes) } 78*eafedbc7SAlice Ryhl } 79*eafedbc7SAlice Ryhl 80*eafedbc7SAlice Ryhl pub(super) fn return_string(i: usize) -> &'static str { 81*eafedbc7SAlice Ryhl // SAFETY: Accessing `binder_return_strings` is always safe. 82*eafedbc7SAlice Ryhl let c_str_ptr = unsafe { binder_return_strings[i] }; 83*eafedbc7SAlice Ryhl // SAFETY: The `binder_command_strings` array only contains nul-terminated strings. 84*eafedbc7SAlice Ryhl let bytes = unsafe { CStr::from_char_ptr(c_str_ptr) }.as_bytes(); 85*eafedbc7SAlice Ryhl // SAFETY: The `binder_command_strings` array only contains strings with ascii-chars. 86*eafedbc7SAlice Ryhl unsafe { from_utf8_unchecked(bytes) } 87*eafedbc7SAlice Ryhl } 88*eafedbc7SAlice Ryhl } 89*eafedbc7SAlice Ryhl use strings::{command_string, return_string}; 90