1use std::os::raw::c_void;
9
10#[cfg(not(feature = "allocation-tracking"))]
11#[global_allocator]
12static ALLOC: Allocator = Allocator;
13
14#[cfg(feature = "allocation-tracking")]
15#[global_allocator]
16static ALLOC: crate::tracking::AccountingAlloc<Allocator> =
17 crate::tracking::AccountingAlloc::with_allocator(Allocator);
18
19#[cfg(feature = "allocation-tracking")]
20mod tracking;
21
22pub fn is_tracking_unmeasured() -> bool {
23 cfg!(feature = "allocation-tracking")
24}
25
26pub fn dump_unmeasured(_writer: impl std::io::Write) {
27 #[cfg(feature = "allocation-tracking")]
28 ALLOC.dump_unmeasured_allocations(_writer);
29}
30
31pub use crate::platform::*;
32
33type EnclosingSizeFn = unsafe extern "C" fn(*const c_void) -> usize;
34
35#[cfg(feature = "allocation-tracking")]
40unsafe extern "C" fn enclosing_size_impl(ptr: *const c_void) -> usize {
41 let (adjusted, size) = crate::ALLOC.enclosing_size(ptr);
42 if size != 0 {
43 crate::ALLOC.note_allocation(adjusted, size);
44 }
45 size
46}
47
48#[expect(non_upper_case_globals)]
49#[cfg(feature = "allocation-tracking")]
50pub static enclosing_size: Option<EnclosingSizeFn> = Some(crate::enclosing_size_impl);
51
52#[expect(non_upper_case_globals)]
53#[cfg(not(feature = "allocation-tracking"))]
54pub static enclosing_size: Option<EnclosingSizeFn> = None;
55
56#[cfg(not(any(windows, feature = "use-system-allocator", target_env = "ohos")))]
57mod platform {
58 use std::os::raw::c_void;
59
60 pub use tikv_jemallocator::Jemalloc as Allocator;
61
62 pub unsafe extern "C" fn usable_size(ptr: *const c_void) -> usize {
68 let size = unsafe { tikv_jemallocator::usable_size(ptr) };
69 #[cfg(feature = "allocation-tracking")]
70 crate::ALLOC.note_allocation(ptr, size);
71 size
72 }
73
74 pub mod libc_compat {
76 pub use tikv_jemalloc_sys::{free, malloc, realloc};
77 }
78}
79
80#[cfg(all(
81 not(windows),
82 any(feature = "use-system-allocator", target_env = "ohos")
83))]
84mod platform {
85 pub use std::alloc::System as Allocator;
86 use std::os::raw::c_void;
87
88 pub unsafe extern "C" fn usable_size(ptr: *const c_void) -> usize {
94 #[cfg(target_vendor = "apple")]
95 unsafe {
96 let size = libc::malloc_size(ptr);
97 #[cfg(feature = "allocation-tracking")]
98 crate::ALLOC.note_allocation(ptr, size);
99 size
100 }
101
102 #[cfg(not(target_vendor = "apple"))]
103 unsafe {
104 let size = libc::malloc_usable_size(ptr as *mut _);
105 #[cfg(feature = "allocation-tracking")]
106 crate::ALLOC.note_allocation(ptr, size);
107 size
108 }
109 }
110
111 pub mod libc_compat {
112 pub use libc::{free, malloc, realloc};
113 }
114}
115
116#[cfg(windows)]
117mod platform {
118 pub use std::alloc::System as Allocator;
119 use std::os::raw::c_void;
120
121 use windows_sys::Win32::Foundation::FALSE;
122 use windows_sys::Win32::System::Memory::{GetProcessHeap, HeapSize, HeapValidate};
123
124 pub unsafe extern "C" fn usable_size(mut ptr: *const c_void) -> usize {
130 unsafe {
131 let heap = GetProcessHeap();
132
133 if HeapValidate(heap, 0, ptr) == FALSE {
134 ptr = *(ptr as *const *const c_void).offset(-1)
135 }
136
137 let size = HeapSize(heap, 0, ptr) as usize;
138 #[cfg(feature = "allocation-tracking")]
139 crate::ALLOC.note_allocation(ptr, size);
140 size
141 }
142 }
143}