Skip to main content

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::{Event, MonotonicDuration, NullableHandle, ObjectQuery, Status, Topic, ok};
10use bitflags::bitflags;
11use zx_sys::{self as sys, ZX_MAX_NAME_LEN, zx_duration_mono_t, zx_duration_t};
12
13/// An object representing a Zircon resource.
14///
15/// As essentially a subtype of `NullableHandle`, it can be freely interconverted.
16#[derive(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
17#[repr(transparent)]
18pub struct Resource(NullableHandle);
19impl_handle_based!(Resource);
20
21sys::zx_info_kmem_stats_t!(MemStats);
22sys::zx_info_kmem_stats_extended_t!(MemStatsExtended);
23sys::zx_info_kmem_stats_compression_t!(MemStatsCompression);
24sys::zx_info_cpu_stats_t!(PerCpuStats);
25sys::zx_info_resource_t!(ResourceInfo);
26sys::zx_info_memory_stall_t!(MemoryStall);
27
28impl From<sys::zx_info_kmem_stats_t> for MemStats {
29    fn from(info: sys::zx_info_kmem_stats_t) -> MemStats {
30        let sys::zx_info_kmem_stats_t {
31            total_bytes,
32            free_bytes,
33            free_loaned_bytes,
34            wired_bytes,
35            total_heap_bytes,
36            free_heap_bytes,
37            vmo_bytes,
38            mmu_overhead_bytes,
39            ipc_bytes,
40            cache_bytes,
41            slab_bytes,
42            zram_bytes,
43            other_bytes,
44            vmo_reclaim_total_bytes,
45            vmo_reclaim_newest_bytes,
46            vmo_reclaim_oldest_bytes,
47            vmo_reclaim_disabled_bytes,
48            vmo_discardable_locked_bytes,
49            vmo_discardable_unlocked_bytes,
50        } = info;
51        MemStats {
52            total_bytes,
53            free_bytes,
54            free_loaned_bytes,
55            wired_bytes,
56            total_heap_bytes,
57            free_heap_bytes,
58            vmo_bytes,
59            mmu_overhead_bytes,
60            ipc_bytes,
61            cache_bytes,
62            slab_bytes,
63            zram_bytes,
64            other_bytes,
65            vmo_reclaim_total_bytes,
66            vmo_reclaim_newest_bytes,
67            vmo_reclaim_oldest_bytes,
68            vmo_reclaim_disabled_bytes,
69            vmo_discardable_locked_bytes,
70            vmo_discardable_unlocked_bytes,
71        }
72    }
73}
74
75impl From<sys::zx_info_kmem_stats_extended_t> for MemStatsExtended {
76    fn from(info: sys::zx_info_kmem_stats_extended_t) -> MemStatsExtended {
77        let sys::zx_info_kmem_stats_extended_t {
78            total_bytes,
79            free_bytes,
80            wired_bytes,
81            total_heap_bytes,
82            free_heap_bytes,
83            vmo_bytes,
84            vmo_pager_total_bytes,
85            vmo_pager_newest_bytes,
86            vmo_pager_oldest_bytes,
87            vmo_discardable_locked_bytes,
88            vmo_discardable_unlocked_bytes,
89            mmu_overhead_bytes,
90            ipc_bytes,
91            other_bytes,
92            vmo_reclaim_disable_bytes,
93        } = info;
94        MemStatsExtended {
95            total_bytes,
96            free_bytes,
97            wired_bytes,
98            total_heap_bytes,
99            free_heap_bytes,
100            vmo_bytes,
101            vmo_pager_total_bytes,
102            vmo_pager_newest_bytes,
103            vmo_pager_oldest_bytes,
104            vmo_discardable_locked_bytes,
105            vmo_discardable_unlocked_bytes,
106            mmu_overhead_bytes,
107            ipc_bytes,
108            other_bytes,
109            vmo_reclaim_disable_bytes,
110        }
111    }
112}
113
114impl From<sys::zx_info_kmem_stats_compression_t> for MemStatsCompression {
115    fn from(info: sys::zx_info_kmem_stats_compression_t) -> MemStatsCompression {
116        let sys::zx_info_kmem_stats_compression_t {
117            uncompressed_storage_bytes,
118            compressed_storage_bytes,
119            compressed_fragmentation_bytes,
120            compression_time,
121            decompression_time,
122            total_page_compression_attempts,
123            failed_page_compression_attempts,
124            total_page_decompressions,
125            compressed_page_evictions,
126            eager_page_compressions,
127            memory_pressure_page_compressions,
128            critical_memory_page_compressions,
129            pages_decompressed_unit_ns,
130            pages_decompressed_within_log_time,
131        } = info;
132        MemStatsCompression {
133            uncompressed_storage_bytes,
134            compressed_storage_bytes,
135            compressed_fragmentation_bytes,
136            compression_time,
137            decompression_time,
138            total_page_compression_attempts,
139            failed_page_compression_attempts,
140            total_page_decompressions,
141            compressed_page_evictions,
142            eager_page_compressions,
143            memory_pressure_page_compressions,
144            critical_memory_page_compressions,
145            pages_decompressed_unit_ns,
146            pages_decompressed_within_log_time,
147        }
148    }
149}
150
151impl From<sys::zx_info_cpu_stats_t> for PerCpuStats {
152    fn from(info: sys::zx_info_cpu_stats_t) -> PerCpuStats {
153        let sys::zx_info_cpu_stats_t {
154            cpu_number,
155            flags,
156            idle_time,
157            normalized_busy_time,
158            reschedules,
159            context_switches,
160            irq_preempts,
161            preempts,
162            yields,
163            ints,
164            timer_ints,
165            timers,
166            page_faults,
167            exceptions,
168            syscalls,
169            reschedule_ipis,
170            generic_ipis,
171            active_energy_consumption_nj,
172            idle_energy_consumption_nj,
173        } = info;
174        PerCpuStats {
175            cpu_number,
176            flags,
177            idle_time,
178            normalized_busy_time,
179            reschedules,
180            context_switches,
181            irq_preempts,
182            preempts,
183            yields,
184            ints,
185            timer_ints,
186            timers,
187            page_faults,
188            exceptions,
189            syscalls,
190            reschedule_ipis,
191            generic_ipis,
192            active_energy_consumption_nj,
193            idle_energy_consumption_nj,
194        }
195    }
196}
197
198impl From<sys::zx_info_resource_t> for ResourceInfo {
199    fn from(info: sys::zx_info_resource_t) -> ResourceInfo {
200        let sys::zx_info_resource_t { kind, flags, base, size, name } = info;
201        ResourceInfo { kind, flags, base, size, name }
202    }
203}
204
205impl From<sys::zx_info_memory_stall_t> for MemoryStall {
206    fn from(info: sys::zx_info_memory_stall_t) -> MemoryStall {
207        let sys::zx_info_memory_stall_t { stall_time_some, stall_time_full } = info;
208        MemoryStall { stall_time_some, stall_time_full }
209    }
210}
211
212unsafe impl ObjectQuery for MemStats {
213    const TOPIC: Topic = Topic::KMEM_STATS;
214    type InfoTy = MemStats;
215}
216
217unsafe impl ObjectQuery for MemStatsExtended {
218    const TOPIC: Topic = Topic::KMEM_STATS_EXTENDED;
219    type InfoTy = MemStatsExtended;
220}
221
222unsafe impl ObjectQuery for MemStatsCompression {
223    const TOPIC: Topic = Topic::KMEM_STATS_COMPRESSION;
224    type InfoTy = MemStatsCompression;
225}
226
227unsafe impl ObjectQuery for PerCpuStats {
228    const TOPIC: Topic = Topic::CPU_STATS;
229    type InfoTy = PerCpuStats;
230}
231
232unsafe impl ObjectQuery for ResourceInfo {
233    const TOPIC: Topic = Topic::RESOURCE;
234    type InfoTy = ResourceInfo;
235}
236
237unsafe impl ObjectQuery for MemoryStall {
238    const TOPIC: Topic = Topic::MEMORY_STALL;
239    type InfoTy = MemoryStall;
240}
241
242bitflags! {
243    #[repr(transparent)]
244    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
245    pub struct ResourceKind: sys::zx_rsrc_kind_t {
246       const MMIO       = sys::ZX_RSRC_KIND_MMIO;
247       const IRQ        = sys::ZX_RSRC_KIND_IRQ;
248       const IOPORT     = sys::ZX_RSRC_KIND_IOPORT;
249       const ROOT       = sys::ZX_RSRC_KIND_ROOT;
250       const SMC        = sys::ZX_RSRC_KIND_SMC;
251       const SYSTEM     = sys::ZX_RSRC_KIND_SYSTEM;
252    }
253}
254
255bitflags! {
256    #[repr(transparent)]
257    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
258    pub struct ResourceFlag: sys::zx_rsrc_flags_t {
259       const EXCLUSIVE = sys::ZX_RSRC_FLAG_EXCLUSIVE;
260    }
261}
262
263bitflags! {
264    #[repr(transparent)]
265    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
266    pub struct MemoryStallKind: sys::zx_system_memory_stall_type_t {
267       const SOME       = sys::ZX_SYSTEM_MEMORY_STALL_SOME;
268       const FULL       = sys::ZX_SYSTEM_MEMORY_STALL_FULL;
269    }
270}
271
272impl Resource {
273    /// Create a child resource object.
274    ///
275    /// Wraps the
276    /// [zx_resource_create](https://fuchsia.dev/fuchsia-src/reference/syscalls/resource_create.md)
277    /// syscall
278    pub fn create_child(
279        &self,
280        kind: ResourceKind,
281        flags: Option<ResourceFlag>,
282        base: u64,
283        size: usize,
284        name: &[u8],
285    ) -> Result<Resource, Status> {
286        let mut resource_out = 0;
287        let name_ptr = name.as_ptr();
288        let name_len = name.len();
289        let flag_bits: u32 = match flags {
290            Some(flag) => flag.bits(),
291            None => 0,
292        };
293        let option_bits: u32 = kind.bits() | flag_bits;
294
295        let status = unsafe {
296            sys::zx_resource_create(
297                self.raw_handle(),
298                option_bits,
299                base,
300                size,
301                name_ptr,
302                name_len,
303                &mut resource_out,
304            )
305        };
306        ok(status)?;
307        unsafe { Ok(Resource::from(NullableHandle::from_raw(resource_out))) }
308    }
309
310    /// Wraps the
311    /// [zx_object_get_info](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_get_info.md)
312    /// syscall for the ZX_INFO_RESOURCE topic.
313    pub fn info(&self) -> Result<ResourceInfo, Status> {
314        self.0.get_info_single::<ResourceInfo>()
315    }
316
317    /// Wraps the
318    /// [zx_object_get_info](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_get_info.md)
319    /// syscall for the ZX_INFO_CPU_STATS topic.
320    pub fn cpu_stats(&self) -> Result<Vec<PerCpuStats>, Status> {
321        self.0.get_info_vec::<PerCpuStats>()
322    }
323
324    /// Wraps the
325    /// [zx_object_get_info](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_get_info.md)
326    /// syscall for the ZX_INFO_KMEM_STATS topic.
327    pub fn mem_stats(&self) -> Result<MemStats, Status> {
328        self.0.get_info_single::<MemStats>()
329    }
330
331    /// Wraps the
332    /// [zx_object_get_info](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_get_info.md)
333    /// syscall for the ZX_INFO_KMEM_STATS_EXTENDED topic.
334    pub fn mem_stats_extended(&self) -> Result<MemStatsExtended, Status> {
335        self.0.get_info_single::<MemStatsExtended>()
336    }
337
338    /// Wraps the
339    /// [zx_object_get_info](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_get_info.md)
340    /// syscall for the ZX_INFO_KMEM_STATS_COMPRESSION topic.
341    pub fn mem_stats_compression(&self) -> Result<MemStatsCompression, Status> {
342        self.0.get_info_single::<MemStatsCompression>()
343    }
344
345    /// Wraps the
346    /// [zx_object_get_info](https://fuchsia.dev/fuchsia-src/reference/syscalls/object_get_info.md)
347    /// syscall for the ZX_INFO_MEMORY_STALL topic.
348    pub fn memory_stall(&self) -> Result<MemoryStall, Status> {
349        self.0.get_info_single::<MemoryStall>()
350    }
351
352    /// Retrieve an event that becomes signaled if the memory stall level exceeds a given threshold
353    /// over a time window.
354    ///
355    /// Wraps the
356    /// [zx_system_watch_memory_stall](https://fuchsia.dev/fuchsia-src/reference/syscalls/system_watch_memory_stall.md)
357    /// syscall
358    pub fn watch_memory_stall(
359        &self,
360        kind: MemoryStallKind,
361        threshold: MonotonicDuration,
362        window: MonotonicDuration,
363    ) -> Result<Event, Status> {
364        let mut event_out = 0;
365        let status = unsafe {
366            sys::zx_system_watch_memory_stall(
367                self.raw_handle(),
368                kind.bits(),
369                threshold.into_nanos(),
370                window.into_nanos(),
371                &mut event_out,
372            )
373        };
374        ok(status)?;
375        unsafe { Ok(Event::from(NullableHandle::from_raw(event_out))) }
376    }
377}