1#![allow(clippy::bad_bit_mask)] use crate::{
10 object_get_info_single, object_get_info_vec, ok, AsHandleRef, Event, Handle, HandleBased,
11 HandleRef, MonotonicDuration, ObjectQuery, Status, Topic,
12};
13use bitflags::bitflags;
14use zx_sys::{self as sys, zx_duration_mono_t, zx_duration_t, ZX_MAX_NAME_LEN};
15
16#[derive(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
20#[repr(transparent)]
21pub struct Resource(Handle);
22impl_handle_based!(Resource);
23
24sys::zx_info_kmem_stats_t!(MemStats);
25sys::zx_info_kmem_stats_extended_t!(MemStatsExtended);
26sys::zx_info_kmem_stats_compression_t!(MemStatsCompression);
27sys::zx_info_cpu_stats_t!(PerCpuStats);
28sys::zx_info_resource_t!(ResourceInfo);
29sys::zx_info_memory_stall_t!(MemoryStall);
30
31impl From<sys::zx_info_kmem_stats_t> for MemStats {
32 fn from(info: sys::zx_info_kmem_stats_t) -> MemStats {
33 let sys::zx_info_kmem_stats_t {
34 total_bytes,
35 free_bytes,
36 free_loaned_bytes,
37 wired_bytes,
38 total_heap_bytes,
39 free_heap_bytes,
40 vmo_bytes,
41 mmu_overhead_bytes,
42 ipc_bytes,
43 cache_bytes,
44 slab_bytes,
45 zram_bytes,
46 other_bytes,
47 vmo_reclaim_total_bytes,
48 vmo_reclaim_newest_bytes,
49 vmo_reclaim_oldest_bytes,
50 vmo_reclaim_disabled_bytes,
51 vmo_discardable_locked_bytes,
52 vmo_discardable_unlocked_bytes,
53 } = info;
54 MemStats {
55 total_bytes,
56 free_bytes,
57 free_loaned_bytes,
58 wired_bytes,
59 total_heap_bytes,
60 free_heap_bytes,
61 vmo_bytes,
62 mmu_overhead_bytes,
63 ipc_bytes,
64 cache_bytes,
65 slab_bytes,
66 zram_bytes,
67 other_bytes,
68 vmo_reclaim_total_bytes,
69 vmo_reclaim_newest_bytes,
70 vmo_reclaim_oldest_bytes,
71 vmo_reclaim_disabled_bytes,
72 vmo_discardable_locked_bytes,
73 vmo_discardable_unlocked_bytes,
74 }
75 }
76}
77
78impl From<sys::zx_info_kmem_stats_extended_t> for MemStatsExtended {
79 fn from(info: sys::zx_info_kmem_stats_extended_t) -> MemStatsExtended {
80 let sys::zx_info_kmem_stats_extended_t {
81 total_bytes,
82 free_bytes,
83 wired_bytes,
84 total_heap_bytes,
85 free_heap_bytes,
86 vmo_bytes,
87 vmo_pager_total_bytes,
88 vmo_pager_newest_bytes,
89 vmo_pager_oldest_bytes,
90 vmo_discardable_locked_bytes,
91 vmo_discardable_unlocked_bytes,
92 mmu_overhead_bytes,
93 ipc_bytes,
94 other_bytes,
95 vmo_reclaim_disable_bytes,
96 } = info;
97 MemStatsExtended {
98 total_bytes,
99 free_bytes,
100 wired_bytes,
101 total_heap_bytes,
102 free_heap_bytes,
103 vmo_bytes,
104 vmo_pager_total_bytes,
105 vmo_pager_newest_bytes,
106 vmo_pager_oldest_bytes,
107 vmo_discardable_locked_bytes,
108 vmo_discardable_unlocked_bytes,
109 mmu_overhead_bytes,
110 ipc_bytes,
111 other_bytes,
112 vmo_reclaim_disable_bytes,
113 }
114 }
115}
116
117impl From<sys::zx_info_kmem_stats_compression_t> for MemStatsCompression {
118 fn from(info: sys::zx_info_kmem_stats_compression_t) -> MemStatsCompression {
119 let sys::zx_info_kmem_stats_compression_t {
120 uncompressed_storage_bytes,
121 compressed_storage_bytes,
122 compressed_fragmentation_bytes,
123 compression_time,
124 decompression_time,
125 total_page_compression_attempts,
126 failed_page_compression_attempts,
127 total_page_decompressions,
128 compressed_page_evictions,
129 eager_page_compressions,
130 memory_pressure_page_compressions,
131 critical_memory_page_compressions,
132 pages_decompressed_unit_ns,
133 pages_decompressed_within_log_time,
134 } = info;
135 MemStatsCompression {
136 uncompressed_storage_bytes,
137 compressed_storage_bytes,
138 compressed_fragmentation_bytes,
139 compression_time,
140 decompression_time,
141 total_page_compression_attempts,
142 failed_page_compression_attempts,
143 total_page_decompressions,
144 compressed_page_evictions,
145 eager_page_compressions,
146 memory_pressure_page_compressions,
147 critical_memory_page_compressions,
148 pages_decompressed_unit_ns,
149 pages_decompressed_within_log_time,
150 }
151 }
152}
153
154impl From<sys::zx_info_cpu_stats_t> for PerCpuStats {
155 fn from(info: sys::zx_info_cpu_stats_t) -> PerCpuStats {
156 let sys::zx_info_cpu_stats_t {
157 cpu_number,
158 flags,
159 idle_time,
160 reschedules,
161 context_switches,
162 irq_preempts,
163 preempts,
164 yields,
165 ints,
166 timer_ints,
167 timers,
168 page_faults,
169 exceptions,
170 syscalls,
171 reschedule_ipis,
172 generic_ipis,
173 } = info;
174 PerCpuStats {
175 cpu_number,
176 flags,
177 idle_time,
178 reschedules,
179 context_switches,
180 irq_preempts,
181 preempts,
182 yields,
183 ints,
184 timer_ints,
185 timers,
186 page_faults,
187 exceptions,
188 syscalls,
189 reschedule_ipis,
190 generic_ipis,
191 }
192 }
193}
194
195impl From<sys::zx_info_resource_t> for ResourceInfo {
196 fn from(info: sys::zx_info_resource_t) -> ResourceInfo {
197 let sys::zx_info_resource_t { kind, flags, base, size, name } = info;
198 ResourceInfo { kind, flags, base, size, name }
199 }
200}
201
202impl From<sys::zx_info_memory_stall_t> for MemoryStall {
203 fn from(info: sys::zx_info_memory_stall_t) -> MemoryStall {
204 let sys::zx_info_memory_stall_t { stall_time_some, stall_time_full } = info;
205 MemoryStall { stall_time_some, stall_time_full }
206 }
207}
208
209unsafe impl ObjectQuery for MemStats {
210 const TOPIC: Topic = Topic::KMEM_STATS;
211 type InfoTy = MemStats;
212}
213
214unsafe impl ObjectQuery for MemStatsExtended {
215 const TOPIC: Topic = Topic::KMEM_STATS_EXTENDED;
216 type InfoTy = MemStatsExtended;
217}
218
219unsafe impl ObjectQuery for MemStatsCompression {
220 const TOPIC: Topic = Topic::KMEM_STATS_COMPRESSION;
221 type InfoTy = MemStatsCompression;
222}
223
224unsafe impl ObjectQuery for PerCpuStats {
225 const TOPIC: Topic = Topic::CPU_STATS;
226 type InfoTy = PerCpuStats;
227}
228
229unsafe impl ObjectQuery for ResourceInfo {
230 const TOPIC: Topic = Topic::RESOURCE;
231 type InfoTy = ResourceInfo;
232}
233
234unsafe impl ObjectQuery for MemoryStall {
235 const TOPIC: Topic = Topic::MEMORY_STALL;
236 type InfoTy = MemoryStall;
237}
238
239bitflags! {
240 #[repr(transparent)]
241 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
242 pub struct ResourceKind: sys::zx_rsrc_kind_t {
243 const MMIO = sys::ZX_RSRC_KIND_MMIO;
244 const IRQ = sys::ZX_RSRC_KIND_IRQ;
245 const IOPORT = sys::ZX_RSRC_KIND_IOPORT;
246 const ROOT = sys::ZX_RSRC_KIND_ROOT;
247 const SMC = sys::ZX_RSRC_KIND_SMC;
248 const SYSTEM = sys::ZX_RSRC_KIND_SYSTEM;
249 }
250}
251
252bitflags! {
253 #[repr(transparent)]
254 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
255 pub struct ResourceFlag: sys::zx_rsrc_flags_t {
256 const EXCLUSIVE = sys::ZX_RSRC_FLAG_EXCLUSIVE;
257 }
258}
259
260bitflags! {
261 #[repr(transparent)]
262 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
263 pub struct MemoryStallKind: sys::zx_system_memory_stall_type_t {
264 const SOME = sys::ZX_SYSTEM_MEMORY_STALL_SOME;
265 const FULL = sys::ZX_SYSTEM_MEMORY_STALL_FULL;
266 }
267}
268
269impl Resource {
270 pub fn create_child(
276 &self,
277 kind: ResourceKind,
278 flags: Option<ResourceFlag>,
279 base: u64,
280 size: usize,
281 name: &[u8],
282 ) -> Result<Resource, Status> {
283 let mut resource_out = 0;
284 let name_ptr = name.as_ptr();
285 let name_len = name.len();
286 let flag_bits: u32 = match flags {
287 Some(flag) => flag.bits(),
288 None => 0,
289 };
290 let option_bits: u32 = kind.bits() | flag_bits;
291
292 let status = unsafe {
293 sys::zx_resource_create(
294 self.raw_handle(),
295 option_bits,
296 base,
297 size,
298 name_ptr,
299 name_len,
300 &mut resource_out,
301 )
302 };
303 ok(status)?;
304 unsafe { Ok(Resource::from(Handle::from_raw(resource_out))) }
305 }
306
307 pub fn info(&self) -> Result<ResourceInfo, Status> {
311 object_get_info_single::<ResourceInfo>(self.as_handle_ref())
312 }
313
314 pub fn cpu_stats(&self) -> Result<Vec<PerCpuStats>, Status> {
318 object_get_info_vec::<PerCpuStats>(self.as_handle_ref())
319 }
320
321 pub fn mem_stats(&self) -> Result<MemStats, Status> {
325 object_get_info_single::<MemStats>(self.as_handle_ref())
326 }
327
328 pub fn mem_stats_extended(&self) -> Result<MemStatsExtended, Status> {
332 object_get_info_single::<MemStatsExtended>(self.as_handle_ref())
333 }
334
335 pub fn mem_stats_compression(&self) -> Result<MemStatsCompression, Status> {
339 object_get_info_single::<MemStatsCompression>(self.as_handle_ref())
340 }
341
342 pub fn memory_stall(&self) -> Result<MemoryStall, Status> {
346 object_get_info_single::<MemoryStall>(self.as_handle_ref())
347 }
348
349 pub fn watch_memory_stall(
356 &self,
357 kind: MemoryStallKind,
358 threshold: MonotonicDuration,
359 window: MonotonicDuration,
360 ) -> Result<Event, Status> {
361 let mut event_out = 0;
362 let status = unsafe {
363 sys::zx_system_watch_memory_stall(
364 self.raw_handle(),
365 kind.bits(),
366 threshold.into_nanos(),
367 window.into_nanos(),
368 &mut event_out,
369 )
370 };
371 ok(status)?;
372 unsafe { Ok(Event::from(Handle::from_raw(event_out))) }
373 }
374}
375
376#[cfg(test)]
377mod tests {
378 use super::*;
379
380 #[test]
381 fn create_child() {
382 let invalid_resource = Resource::from(Handle::invalid());
383 assert_eq!(
384 invalid_resource.create_child(ResourceKind::IRQ, None, 0, 0, b"irq"),
385 Err(Status::BAD_HANDLE)
386 );
387 }
388
389 #[test]
390 fn cpu_stats() {
391 let invalid_resource = Resource::from(Handle::invalid());
392 assert_eq!(invalid_resource.cpu_stats(), Err(Status::BAD_HANDLE));
393 }
394
395 #[test]
396 fn mem_stats() {
397 let invalid_resource = Resource::from(Handle::invalid());
398 assert_eq!(invalid_resource.mem_stats(), Err(Status::BAD_HANDLE));
399 }
400
401 #[test]
402 fn mem_stats_extended() {
403 let invalid_resource = Resource::from(Handle::invalid());
404 assert_eq!(invalid_resource.mem_stats_extended(), Err(Status::BAD_HANDLE));
405 }
406
407 #[test]
408 fn mem_stats_compression() {
409 let invalid_resource = Resource::from(Handle::invalid());
410 assert_eq!(invalid_resource.mem_stats_compression(), Err(Status::BAD_HANDLE));
411 }
412}