_core_rustc_static/
lib.rs1use lazy_static::lazy_static;
6use std::cell::RefCell;
7use std::ffi::c_char;
8use zx::sys::zx_handle_t;
9use zx::{self as zx, AsHandleRef};
10
11mod allocations_table;
12mod profiler;
13mod recursion_guard;
14mod resources_table;
15mod waiter_list;
16
17#[cfg(not(test))]
19mod hooks;
20
21use crate::profiler::{PerThreadData, Profiler};
22use crate::recursion_guard::with_recursion_guard;
23
24lazy_static! {
27 static ref PROFILER: Profiler = with_recursion_guard(Default::default);
28}
29
30thread_local! {
31 static THREAD_DATA: RefCell<PerThreadData> = with_recursion_guard(Default::default);
32}
33
34#[derive(Clone, Copy, Default)]
35#[repr(C)]
36pub struct heapdump_global_stats {
37 pub total_allocated_bytes: u64,
38 pub total_deallocated_bytes: u64,
39}
40
41#[derive(Clone, Copy, Default)]
42#[repr(C)]
43pub struct heapdump_thread_local_stats {
44 pub total_allocated_bytes: u64,
45 pub total_deallocated_bytes: u64,
46}
47
48pub fn with_profiler(f: impl FnOnce(&Profiler, &mut PerThreadData)) {
51 let profiler = &*PROFILER;
52 THREAD_DATA.with(|thread_data| {
53 with_recursion_guard(|| {
54 f(profiler, &mut thread_data.borrow_mut());
55 })
56 })
57}
58
59#[no_mangle]
62pub unsafe extern "C" fn heapdump_bind_with_channel(registry_channel: zx_handle_t) {
63 let handle = zx::Handle::from_raw(registry_channel);
64 if !handle.is_invalid() {
65 assert_eq!(handle.basic_info().unwrap().object_type, zx::ObjectType::CHANNEL);
66 }
67
68 PROFILER.bind(handle.into());
69}
70
71#[no_mangle]
74pub unsafe extern "C" fn heapdump_get_stats(
75 global: *mut heapdump_global_stats,
76 local: *mut heapdump_thread_local_stats,
77) {
78 with_profiler(|profiler, thread_data| {
79 if global != std::ptr::null_mut() {
80 *global = profiler.get_global_stats();
81 }
82 if local != std::ptr::null_mut() {
83 *local = thread_data.get_local_stats();
84 }
85 });
86}
87
88#[no_mangle]
91pub unsafe extern "C" fn heapdump_take_named_snapshot(name: *const c_char) {
92 let name_cstr = std::ffi::CStr::from_ptr(name);
93 let name_str = name_cstr.to_str().expect("name contains invalid characters");
94 assert!(name_str.len() <= zx::sys::ZX_MAX_NAME_LEN, "name is too long");
95
96 PROFILER.publish_named_snapshot(name_str);
97}