zx/
resource.rs

1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Type-safe bindings for Zircon resources.
6
7#![allow(clippy::bad_bit_mask)] // TODO(https://fxbug.dev/42080521): stop using bitflags for ResourceKind
8
9use crate::{
10    AsHandleRef, Event, HandleBased, HandleRef, MonotonicDuration, NullableHandle, ObjectQuery,
11    Status, Topic, ok,
12};
13use bitflags::bitflags;
14use zx_sys::{self as sys, ZX_MAX_NAME_LEN, zx_duration_mono_t, zx_duration_t};
15
16/// An object representing a Zircon resource.
17///
18/// As essentially a subtype of `NullableHandle`, it can be freely interconverted.
19#[derive(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
20#[repr(transparent)]
21pub struct Resource(NullableHandle);
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            normalized_busy_time,
161            reschedules,
162            context_switches,
163            irq_preempts,
164            preempts,
165            yields,
166            ints,
167            timer_ints,
168            timers,
169            page_faults,
170            exceptions,
171            syscalls,
172            reschedule_ipis,
173            generic_ipis,
174            active_energy_consumption_nj,
175            idle_energy_consumption_nj,
176        } = info;
177        PerCpuStats {
178            cpu_number,
179            flags,
180            idle_time,
181            normalized_busy_time,
182            reschedules,
183            context_switches,
184            irq_preempts,
185            preempts,
186            yields,
187            ints,
188            timer_ints,
189            timers,
190            page_faults,
191            exceptions,
192            syscalls,
193            reschedule_ipis,
194            generic_ipis,
195            active_energy_consumption_nj,
196            idle_energy_consumption_nj,
197        }
198    }
199}
200
201impl From<sys::zx_info_resource_t> for ResourceInfo {
202    fn from(info: sys::zx_info_resource_t) -> ResourceInfo {
203        let sys::zx_info_resource_t { kind, flags, base, size, name } = info;
204        ResourceInfo { kind, flags, base, size, name }
205    }
206}
207
208impl From<sys::zx_info_memory_stall_t> for MemoryStall {
209    fn from(info: sys::zx_info_memory_stall_t) -> MemoryStall {
210        let sys::zx_info_memory_stall_t { stall_time_some, stall_time_full } = info;
211        MemoryStall { stall_time_some, stall_time_full }
212    }
213}
214
215unsafe impl ObjectQuery for MemStats {
216    const TOPIC: Topic = Topic::KMEM_STATS;
217    type InfoTy = MemStats;
218}
219
220unsafe impl ObjectQuery for MemStatsExtended {
221    const TOPIC: Topic = Topic::KMEM_STATS_EXTENDED;
222    type InfoTy = MemStatsExtended;
223}
224
225unsafe impl ObjectQuery for MemStatsCompression {
226    const TOPIC: Topic = Topic::KMEM_STATS_COMPRESSION;
227    type InfoTy = MemStatsCompression;
228}
229
230unsafe impl ObjectQuery for PerCpuStats {
231    const TOPIC: Topic = Topic::CPU_STATS;
232    type InfoTy = PerCpuStats;
233}
234
235unsafe impl ObjectQuery for ResourceInfo {
236    const TOPIC: Topic = Topic::RESOURCE;
237    type InfoTy = ResourceInfo;
238}
239
240unsafe impl ObjectQuery for MemoryStall {
241    const TOPIC: Topic = Topic::MEMORY_STALL;
242    type InfoTy = MemoryStall;
243}
244
245bitflags! {
246    #[repr(transparent)]
247    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
248    pub struct ResourceKind: sys::zx_rsrc_kind_t {
249       const MMIO       = sys::ZX_RSRC_KIND_MMIO;
250       const IRQ        = sys::ZX_RSRC_KIND_IRQ;
251       const IOPORT     = sys::ZX_RSRC_KIND_IOPORT;
252       const ROOT       = sys::ZX_RSRC_KIND_ROOT;
253       const SMC        = sys::ZX_RSRC_KIND_SMC;
254       const SYSTEM     = sys::ZX_RSRC_KIND_SYSTEM;
255    }
256}
257
258bitflags! {
259    #[repr(transparent)]
260    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
261    pub struct ResourceFlag: sys::zx_rsrc_flags_t {
262       const EXCLUSIVE = sys::ZX_RSRC_FLAG_EXCLUSIVE;
263    }
264}
265
266bitflags! {
267    #[repr(transparent)]
268    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
269    pub struct MemoryStallKind: sys::zx_system_memory_stall_type_t {
270       const SOME       = sys::ZX_SYSTEM_MEMORY_STALL_SOME;
271       const FULL       = sys::ZX_SYSTEM_MEMORY_STALL_FULL;
272    }
273}
274
275impl Resource {
276    /// Create a child resource object.
277    ///
278    /// Wraps the
279    /// [zx_resource_create](https://fuchsia.dev/fuchsia-src/reference/syscalls/resource_create.md)
280    /// syscall
281    pub fn create_child(
282        &self,
283        kind: ResourceKind,
284        flags: Option<ResourceFlag>,
285        base: u64,
286        size: usize,
287        name: &[u8],
288    ) -> Result<Resource, Status> {
289        let mut resource_out = 0;
290        let name_ptr = name.as_ptr();
291        let name_len = name.len();
292        let flag_bits: u32 = match flags {
293            Some(flag) => flag.bits(),
294            None => 0,
295        };
296        let option_bits: u32 = kind.bits() | flag_bits;
297
298        let status = unsafe {
299            sys::zx_resource_create(
300                self.raw_handle(),
301                option_bits,
302                base,
303                size,
304                name_ptr,
305                name_len,
306                &mut resource_out,
307            )
308        };
309        ok(status)?;
310        unsafe { Ok(Resource::from(NullableHandle::from_raw(resource_out))) }
311    }
312
313    /// Wraps the
314    /// [zx_object_get_info](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_get_info.md)
315    /// syscall for the ZX_INFO_RESOURCE topic.
316    pub fn info(&self) -> Result<ResourceInfo, Status> {
317        self.0.get_info_single::<ResourceInfo>()
318    }
319
320    /// Wraps the
321    /// [zx_object_get_info](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_get_info.md)
322    /// syscall for the ZX_INFO_CPU_STATS topic.
323    pub fn cpu_stats(&self) -> Result<Vec<PerCpuStats>, Status> {
324        self.0.get_info_vec::<PerCpuStats>()
325    }
326
327    /// Wraps the
328    /// [zx_object_get_info](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_get_info.md)
329    /// syscall for the ZX_INFO_KMEM_STATS topic.
330    pub fn mem_stats(&self) -> Result<MemStats, Status> {
331        self.0.get_info_single::<MemStats>()
332    }
333
334    /// Wraps the
335    /// [zx_object_get_info](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_get_info.md)
336    /// syscall for the ZX_INFO_KMEM_STATS_EXTENDED topic.
337    pub fn mem_stats_extended(&self) -> Result<MemStatsExtended, Status> {
338        self.0.get_info_single::<MemStatsExtended>()
339    }
340
341    /// Wraps the
342    /// [zx_object_get_info](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_get_info.md)
343    /// syscall for the ZX_INFO_KMEM_STATS_COMPRESSION topic.
344    pub fn mem_stats_compression(&self) -> Result<MemStatsCompression, Status> {
345        self.0.get_info_single::<MemStatsCompression>()
346    }
347
348    /// Wraps the
349    /// [zx_object_get_info](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_get_info.md)
350    /// syscall for the ZX_INFO_MEMORY_STALL topic.
351    pub fn memory_stall(&self) -> Result<MemoryStall, Status> {
352        self.0.get_info_single::<MemoryStall>()
353    }
354
355    /// Retrieve an event that becomes signaled if the memory stall level exceeds a given threshold
356    /// over a time window.
357    ///
358    /// Wraps the
359    /// [zx_system_watch_memory_stall](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_watch_memory_stall.md)
360    /// syscall
361    pub fn watch_memory_stall(
362        &self,
363        kind: MemoryStallKind,
364        threshold: MonotonicDuration,
365        window: MonotonicDuration,
366    ) -> Result<Event, Status> {
367        let mut event_out = 0;
368        let status = unsafe {
369            sys::zx_system_watch_memory_stall(
370                self.raw_handle(),
371                kind.bits(),
372                threshold.into_nanos(),
373                window.into_nanos(),
374                &mut event_out,
375            )
376        };
377        ok(status)?;
378        unsafe { Ok(Event::from(NullableHandle::from_raw(event_out))) }
379    }
380}