xref: /linux/rust/kernel/cpumask.rs (revision f688b599d711d169b22e99f2d055847d66c4e0d3)
18961b8cbSViresh Kumar // SPDX-License-Identifier: GPL-2.0
28961b8cbSViresh Kumar 
38961b8cbSViresh Kumar //! CPU Mask abstractions.
48961b8cbSViresh Kumar //!
58961b8cbSViresh Kumar //! C header: [`include/linux/cpumask.h`](srctree/include/linux/cpumask.h)
68961b8cbSViresh Kumar 
78961b8cbSViresh Kumar use crate::{
88961b8cbSViresh Kumar     alloc::{AllocError, Flags},
9*33db8c97SViresh Kumar     cpu::CpuId,
108961b8cbSViresh Kumar     prelude::*,
118961b8cbSViresh Kumar     types::Opaque,
128961b8cbSViresh Kumar };
138961b8cbSViresh Kumar 
148961b8cbSViresh Kumar #[cfg(CONFIG_CPUMASK_OFFSTACK)]
158961b8cbSViresh Kumar use core::ptr::{self, NonNull};
168961b8cbSViresh Kumar 
178961b8cbSViresh Kumar #[cfg(not(CONFIG_CPUMASK_OFFSTACK))]
188961b8cbSViresh Kumar use core::mem::MaybeUninit;
198961b8cbSViresh Kumar 
208961b8cbSViresh Kumar use core::ops::{Deref, DerefMut};
218961b8cbSViresh Kumar 
228961b8cbSViresh Kumar /// A CPU Mask.
238961b8cbSViresh Kumar ///
248961b8cbSViresh Kumar /// Rust abstraction for the C `struct cpumask`.
258961b8cbSViresh Kumar ///
268961b8cbSViresh Kumar /// # Invariants
278961b8cbSViresh Kumar ///
288961b8cbSViresh Kumar /// A [`Cpumask`] instance always corresponds to a valid C `struct cpumask`.
298961b8cbSViresh Kumar ///
308961b8cbSViresh Kumar /// The callers must ensure that the `struct cpumask` is valid for access and
318961b8cbSViresh Kumar /// remains valid for the lifetime of the returned reference.
328961b8cbSViresh Kumar ///
338961b8cbSViresh Kumar /// ## Examples
348961b8cbSViresh Kumar ///
358961b8cbSViresh Kumar /// The following example demonstrates how to update a [`Cpumask`].
368961b8cbSViresh Kumar ///
378961b8cbSViresh Kumar /// ```
388961b8cbSViresh Kumar /// use kernel::bindings;
39*33db8c97SViresh Kumar /// use kernel::cpu::CpuId;
408961b8cbSViresh Kumar /// use kernel::cpumask::Cpumask;
418961b8cbSViresh Kumar ///
42*33db8c97SViresh Kumar /// fn set_clear_cpu(ptr: *mut bindings::cpumask, set_cpu: CpuId, clear_cpu: CpuId) {
438961b8cbSViresh Kumar ///     // SAFETY: The `ptr` is valid for writing and remains valid for the lifetime of the
448961b8cbSViresh Kumar ///     // returned reference.
458961b8cbSViresh Kumar ///     let mask = unsafe { Cpumask::as_mut_ref(ptr) };
468961b8cbSViresh Kumar ///
478961b8cbSViresh Kumar ///     mask.set(set_cpu);
488961b8cbSViresh Kumar ///     mask.clear(clear_cpu);
498961b8cbSViresh Kumar /// }
508961b8cbSViresh Kumar /// ```
518961b8cbSViresh Kumar #[repr(transparent)]
528961b8cbSViresh Kumar pub struct Cpumask(Opaque<bindings::cpumask>);
538961b8cbSViresh Kumar 
548961b8cbSViresh Kumar impl Cpumask {
558961b8cbSViresh Kumar     /// Creates a mutable reference to an existing `struct cpumask` pointer.
568961b8cbSViresh Kumar     ///
578961b8cbSViresh Kumar     /// # Safety
588961b8cbSViresh Kumar     ///
598961b8cbSViresh Kumar     /// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime
608961b8cbSViresh Kumar     /// of the returned reference.
as_mut_ref<'a>(ptr: *mut bindings::cpumask) -> &'a mut Self618961b8cbSViresh Kumar     pub unsafe fn as_mut_ref<'a>(ptr: *mut bindings::cpumask) -> &'a mut Self {
628961b8cbSViresh Kumar         // SAFETY: Guaranteed by the safety requirements of the function.
638961b8cbSViresh Kumar         //
648961b8cbSViresh Kumar         // INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the
658961b8cbSViresh Kumar         // lifetime of the returned reference.
668961b8cbSViresh Kumar         unsafe { &mut *ptr.cast() }
678961b8cbSViresh Kumar     }
688961b8cbSViresh Kumar 
698961b8cbSViresh Kumar     /// Creates a reference to an existing `struct cpumask` pointer.
708961b8cbSViresh Kumar     ///
718961b8cbSViresh Kumar     /// # Safety
728961b8cbSViresh Kumar     ///
738961b8cbSViresh Kumar     /// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime
748961b8cbSViresh Kumar     /// of the returned reference.
as_ref<'a>(ptr: *const bindings::cpumask) -> &'a Self758961b8cbSViresh Kumar     pub unsafe fn as_ref<'a>(ptr: *const bindings::cpumask) -> &'a Self {
768961b8cbSViresh Kumar         // SAFETY: Guaranteed by the safety requirements of the function.
778961b8cbSViresh Kumar         //
788961b8cbSViresh Kumar         // INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the
798961b8cbSViresh Kumar         // lifetime of the returned reference.
808961b8cbSViresh Kumar         unsafe { &*ptr.cast() }
818961b8cbSViresh Kumar     }
828961b8cbSViresh Kumar 
838961b8cbSViresh Kumar     /// Obtain the raw `struct cpumask` pointer.
as_raw(&self) -> *mut bindings::cpumask848961b8cbSViresh Kumar     pub fn as_raw(&self) -> *mut bindings::cpumask {
858961b8cbSViresh Kumar         let this: *const Self = self;
868961b8cbSViresh Kumar         this.cast_mut().cast()
878961b8cbSViresh Kumar     }
888961b8cbSViresh Kumar 
898961b8cbSViresh Kumar     /// Set `cpu` in the cpumask.
908961b8cbSViresh Kumar     ///
918961b8cbSViresh Kumar     /// ATTENTION: Contrary to C, this Rust `set()` method is non-atomic.
928961b8cbSViresh Kumar     /// This mismatches kernel naming convention and corresponds to the C
938961b8cbSViresh Kumar     /// function `__cpumask_set_cpu()`.
948961b8cbSViresh Kumar     #[inline]
set(&mut self, cpu: CpuId)95*33db8c97SViresh Kumar     pub fn set(&mut self, cpu: CpuId) {
968961b8cbSViresh Kumar         // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `__cpumask_set_cpu`.
97*33db8c97SViresh Kumar         unsafe { bindings::__cpumask_set_cpu(u32::from(cpu), self.as_raw()) };
988961b8cbSViresh Kumar     }
998961b8cbSViresh Kumar 
1008961b8cbSViresh Kumar     /// Clear `cpu` in the cpumask.
1018961b8cbSViresh Kumar     ///
1028961b8cbSViresh Kumar     /// ATTENTION: Contrary to C, this Rust `clear()` method is non-atomic.
1038961b8cbSViresh Kumar     /// This mismatches kernel naming convention and corresponds to the C
1048961b8cbSViresh Kumar     /// function `__cpumask_clear_cpu()`.
1058961b8cbSViresh Kumar     #[inline]
clear(&mut self, cpu: CpuId)106*33db8c97SViresh Kumar     pub fn clear(&mut self, cpu: CpuId) {
1078961b8cbSViresh Kumar         // SAFETY: By the type invariant, `self.as_raw` is a valid argument to
1088961b8cbSViresh Kumar         // `__cpumask_clear_cpu`.
109*33db8c97SViresh Kumar         unsafe { bindings::__cpumask_clear_cpu(i32::from(cpu), self.as_raw()) };
1108961b8cbSViresh Kumar     }
1118961b8cbSViresh Kumar 
1128961b8cbSViresh Kumar     /// Test `cpu` in the cpumask.
1138961b8cbSViresh Kumar     ///
1148961b8cbSViresh Kumar     /// Equivalent to the kernel's `cpumask_test_cpu` API.
1158961b8cbSViresh Kumar     #[inline]
test(&self, cpu: CpuId) -> bool116*33db8c97SViresh Kumar     pub fn test(&self, cpu: CpuId) -> bool {
1178961b8cbSViresh Kumar         // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `cpumask_test_cpu`.
118*33db8c97SViresh Kumar         unsafe { bindings::cpumask_test_cpu(i32::from(cpu), self.as_raw()) }
1198961b8cbSViresh Kumar     }
1208961b8cbSViresh Kumar 
1218961b8cbSViresh Kumar     /// Set all CPUs in the cpumask.
1228961b8cbSViresh Kumar     ///
1238961b8cbSViresh Kumar     /// Equivalent to the kernel's `cpumask_setall` API.
1248961b8cbSViresh Kumar     #[inline]
setall(&mut self)1258961b8cbSViresh Kumar     pub fn setall(&mut self) {
1268961b8cbSViresh Kumar         // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `cpumask_setall`.
1278961b8cbSViresh Kumar         unsafe { bindings::cpumask_setall(self.as_raw()) };
1288961b8cbSViresh Kumar     }
1298961b8cbSViresh Kumar 
1308961b8cbSViresh Kumar     /// Checks if cpumask is empty.
1318961b8cbSViresh Kumar     ///
1328961b8cbSViresh Kumar     /// Equivalent to the kernel's `cpumask_empty` API.
1338961b8cbSViresh Kumar     #[inline]
empty(&self) -> bool1348961b8cbSViresh Kumar     pub fn empty(&self) -> bool {
1358961b8cbSViresh Kumar         // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `cpumask_empty`.
1368961b8cbSViresh Kumar         unsafe { bindings::cpumask_empty(self.as_raw()) }
1378961b8cbSViresh Kumar     }
1388961b8cbSViresh Kumar 
1398961b8cbSViresh Kumar     /// Checks if cpumask is full.
1408961b8cbSViresh Kumar     ///
1418961b8cbSViresh Kumar     /// Equivalent to the kernel's `cpumask_full` API.
1428961b8cbSViresh Kumar     #[inline]
full(&self) -> bool1438961b8cbSViresh Kumar     pub fn full(&self) -> bool {
1448961b8cbSViresh Kumar         // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `cpumask_full`.
1458961b8cbSViresh Kumar         unsafe { bindings::cpumask_full(self.as_raw()) }
1468961b8cbSViresh Kumar     }
1478961b8cbSViresh Kumar 
1488961b8cbSViresh Kumar     /// Get weight of the cpumask.
1498961b8cbSViresh Kumar     ///
1508961b8cbSViresh Kumar     /// Equivalent to the kernel's `cpumask_weight` API.
1518961b8cbSViresh Kumar     #[inline]
weight(&self) -> u321528961b8cbSViresh Kumar     pub fn weight(&self) -> u32 {
1538961b8cbSViresh Kumar         // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `cpumask_weight`.
1548961b8cbSViresh Kumar         unsafe { bindings::cpumask_weight(self.as_raw()) }
1558961b8cbSViresh Kumar     }
1568961b8cbSViresh Kumar 
1578961b8cbSViresh Kumar     /// Copy cpumask.
1588961b8cbSViresh Kumar     ///
1598961b8cbSViresh Kumar     /// Equivalent to the kernel's `cpumask_copy` API.
1608961b8cbSViresh Kumar     #[inline]
copy(&self, dstp: &mut Self)1618961b8cbSViresh Kumar     pub fn copy(&self, dstp: &mut Self) {
1628961b8cbSViresh Kumar         // SAFETY: By the type invariant, `Self::as_raw` is a valid argument to `cpumask_copy`.
1638961b8cbSViresh Kumar         unsafe { bindings::cpumask_copy(dstp.as_raw(), self.as_raw()) };
1648961b8cbSViresh Kumar     }
1658961b8cbSViresh Kumar }
1668961b8cbSViresh Kumar 
1678961b8cbSViresh Kumar /// A CPU Mask pointer.
1688961b8cbSViresh Kumar ///
1698961b8cbSViresh Kumar /// Rust abstraction for the C `struct cpumask_var_t`.
1708961b8cbSViresh Kumar ///
1718961b8cbSViresh Kumar /// # Invariants
1728961b8cbSViresh Kumar ///
1738961b8cbSViresh Kumar /// A [`CpumaskVar`] instance always corresponds to a valid C `struct cpumask_var_t`.
1748961b8cbSViresh Kumar ///
1758961b8cbSViresh Kumar /// The callers must ensure that the `struct cpumask_var_t` is valid for access and remains valid
1768961b8cbSViresh Kumar /// for the lifetime of [`CpumaskVar`].
1778961b8cbSViresh Kumar ///
1788961b8cbSViresh Kumar /// ## Examples
1798961b8cbSViresh Kumar ///
1808961b8cbSViresh Kumar /// The following example demonstrates how to create and update a [`CpumaskVar`].
1818961b8cbSViresh Kumar ///
1828961b8cbSViresh Kumar /// ```
183*33db8c97SViresh Kumar /// use kernel::cpu::CpuId;
1848961b8cbSViresh Kumar /// use kernel::cpumask::CpumaskVar;
1858961b8cbSViresh Kumar ///
1868961b8cbSViresh Kumar /// let mut mask = CpumaskVar::new_zero(GFP_KERNEL).unwrap();
1878961b8cbSViresh Kumar ///
1888961b8cbSViresh Kumar /// assert!(mask.empty());
189*33db8c97SViresh Kumar /// let mut count = 0;
190*33db8c97SViresh Kumar ///
191*33db8c97SViresh Kumar /// let cpu2 = CpuId::from_u32(2);
192*33db8c97SViresh Kumar /// if let Some(cpu) = cpu2 {
193*33db8c97SViresh Kumar ///     mask.set(cpu);
194*33db8c97SViresh Kumar ///     assert!(mask.test(cpu));
195*33db8c97SViresh Kumar ///     count += 1;
196*33db8c97SViresh Kumar /// }
197*33db8c97SViresh Kumar ///
198*33db8c97SViresh Kumar /// let cpu3 = CpuId::from_u32(3);
199*33db8c97SViresh Kumar /// if let Some(cpu) = cpu3 {
200*33db8c97SViresh Kumar ///     mask.set(cpu);
201*33db8c97SViresh Kumar ///     assert!(mask.test(cpu));
202*33db8c97SViresh Kumar ///     count += 1;
203*33db8c97SViresh Kumar /// }
204*33db8c97SViresh Kumar ///
205*33db8c97SViresh Kumar /// assert_eq!(mask.weight(), count);
2068961b8cbSViresh Kumar ///
2078961b8cbSViresh Kumar /// let mask2 = CpumaskVar::try_clone(&mask).unwrap();
208*33db8c97SViresh Kumar ///
209*33db8c97SViresh Kumar /// if let Some(cpu) = cpu2 {
210*33db8c97SViresh Kumar ///     assert!(mask2.test(cpu));
211*33db8c97SViresh Kumar /// }
212*33db8c97SViresh Kumar ///
213*33db8c97SViresh Kumar /// if let Some(cpu) = cpu3 {
214*33db8c97SViresh Kumar ///     assert!(mask2.test(cpu));
215*33db8c97SViresh Kumar /// }
216*33db8c97SViresh Kumar /// assert_eq!(mask2.weight(), count);
2178961b8cbSViresh Kumar /// ```
2188961b8cbSViresh Kumar pub struct CpumaskVar {
2198961b8cbSViresh Kumar     #[cfg(CONFIG_CPUMASK_OFFSTACK)]
2208961b8cbSViresh Kumar     ptr: NonNull<Cpumask>,
2218961b8cbSViresh Kumar     #[cfg(not(CONFIG_CPUMASK_OFFSTACK))]
2228961b8cbSViresh Kumar     mask: Cpumask,
2238961b8cbSViresh Kumar }
2248961b8cbSViresh Kumar 
2258961b8cbSViresh Kumar impl CpumaskVar {
2268961b8cbSViresh Kumar     /// Creates a zero-initialized instance of the [`CpumaskVar`].
new_zero(_flags: Flags) -> Result<Self, AllocError>2278961b8cbSViresh Kumar     pub fn new_zero(_flags: Flags) -> Result<Self, AllocError> {
2288961b8cbSViresh Kumar         Ok(Self {
2298961b8cbSViresh Kumar             #[cfg(CONFIG_CPUMASK_OFFSTACK)]
2308961b8cbSViresh Kumar             ptr: {
2318961b8cbSViresh Kumar                 let mut ptr: *mut bindings::cpumask = ptr::null_mut();
2328961b8cbSViresh Kumar 
2338961b8cbSViresh Kumar                 // SAFETY: It is safe to call this method as the reference to `ptr` is valid.
2348961b8cbSViresh Kumar                 //
2358961b8cbSViresh Kumar                 // INVARIANT: The associated memory is freed when the `CpumaskVar` goes out of
2368961b8cbSViresh Kumar                 // scope.
2378961b8cbSViresh Kumar                 unsafe { bindings::zalloc_cpumask_var(&mut ptr, _flags.as_raw()) };
2388961b8cbSViresh Kumar                 NonNull::new(ptr.cast()).ok_or(AllocError)?
2398961b8cbSViresh Kumar             },
2408961b8cbSViresh Kumar 
2418961b8cbSViresh Kumar             #[cfg(not(CONFIG_CPUMASK_OFFSTACK))]
2428961b8cbSViresh Kumar             // SAFETY: FFI type is valid to be zero-initialized.
2438961b8cbSViresh Kumar             //
2448961b8cbSViresh Kumar             // INVARIANT: The associated memory is freed when the `CpumaskVar` goes out of scope.
2458961b8cbSViresh Kumar             mask: unsafe { core::mem::zeroed() },
2468961b8cbSViresh Kumar         })
2478961b8cbSViresh Kumar     }
2488961b8cbSViresh Kumar 
2498961b8cbSViresh Kumar     /// Creates an instance of the [`CpumaskVar`].
2508961b8cbSViresh Kumar     ///
2518961b8cbSViresh Kumar     /// # Safety
2528961b8cbSViresh Kumar     ///
2538961b8cbSViresh Kumar     /// The caller must ensure that the returned [`CpumaskVar`] is properly initialized before
2548961b8cbSViresh Kumar     /// getting used.
new(_flags: Flags) -> Result<Self, AllocError>2558961b8cbSViresh Kumar     pub unsafe fn new(_flags: Flags) -> Result<Self, AllocError> {
2568961b8cbSViresh Kumar         Ok(Self {
2578961b8cbSViresh Kumar             #[cfg(CONFIG_CPUMASK_OFFSTACK)]
2588961b8cbSViresh Kumar             ptr: {
2598961b8cbSViresh Kumar                 let mut ptr: *mut bindings::cpumask = ptr::null_mut();
2608961b8cbSViresh Kumar 
2618961b8cbSViresh Kumar                 // SAFETY: It is safe to call this method as the reference to `ptr` is valid.
2628961b8cbSViresh Kumar                 //
2638961b8cbSViresh Kumar                 // INVARIANT: The associated memory is freed when the `CpumaskVar` goes out of
2648961b8cbSViresh Kumar                 // scope.
2658961b8cbSViresh Kumar                 unsafe { bindings::alloc_cpumask_var(&mut ptr, _flags.as_raw()) };
2668961b8cbSViresh Kumar                 NonNull::new(ptr.cast()).ok_or(AllocError)?
2678961b8cbSViresh Kumar             },
2688961b8cbSViresh Kumar             #[cfg(not(CONFIG_CPUMASK_OFFSTACK))]
2698961b8cbSViresh Kumar             // SAFETY: Guaranteed by the safety requirements of the function.
2708961b8cbSViresh Kumar             //
2718961b8cbSViresh Kumar             // INVARIANT: The associated memory is freed when the `CpumaskVar` goes out of scope.
2728961b8cbSViresh Kumar             mask: unsafe { MaybeUninit::uninit().assume_init() },
2738961b8cbSViresh Kumar         })
2748961b8cbSViresh Kumar     }
2758961b8cbSViresh Kumar 
2768961b8cbSViresh Kumar     /// Creates a mutable reference to an existing `struct cpumask_var_t` pointer.
2778961b8cbSViresh Kumar     ///
2788961b8cbSViresh Kumar     /// # Safety
2798961b8cbSViresh Kumar     ///
2808961b8cbSViresh Kumar     /// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime
2818961b8cbSViresh Kumar     /// of the returned reference.
as_mut_ref<'a>(ptr: *mut bindings::cpumask_var_t) -> &'a mut Self2828961b8cbSViresh Kumar     pub unsafe fn as_mut_ref<'a>(ptr: *mut bindings::cpumask_var_t) -> &'a mut Self {
2838961b8cbSViresh Kumar         // SAFETY: Guaranteed by the safety requirements of the function.
2848961b8cbSViresh Kumar         //
2858961b8cbSViresh Kumar         // INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the
2868961b8cbSViresh Kumar         // lifetime of the returned reference.
2878961b8cbSViresh Kumar         unsafe { &mut *ptr.cast() }
2888961b8cbSViresh Kumar     }
2898961b8cbSViresh Kumar 
2908961b8cbSViresh Kumar     /// Creates a reference to an existing `struct cpumask_var_t` pointer.
2918961b8cbSViresh Kumar     ///
2928961b8cbSViresh Kumar     /// # Safety
2938961b8cbSViresh Kumar     ///
2948961b8cbSViresh Kumar     /// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime
2958961b8cbSViresh Kumar     /// of the returned reference.
as_ref<'a>(ptr: *const bindings::cpumask_var_t) -> &'a Self2968961b8cbSViresh Kumar     pub unsafe fn as_ref<'a>(ptr: *const bindings::cpumask_var_t) -> &'a Self {
2978961b8cbSViresh Kumar         // SAFETY: Guaranteed by the safety requirements of the function.
2988961b8cbSViresh Kumar         //
2998961b8cbSViresh Kumar         // INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the
3008961b8cbSViresh Kumar         // lifetime of the returned reference.
3018961b8cbSViresh Kumar         unsafe { &*ptr.cast() }
3028961b8cbSViresh Kumar     }
3038961b8cbSViresh Kumar 
3048961b8cbSViresh Kumar     /// Clones cpumask.
try_clone(cpumask: &Cpumask) -> Result<Self>3058961b8cbSViresh Kumar     pub fn try_clone(cpumask: &Cpumask) -> Result<Self> {
3068961b8cbSViresh Kumar         // SAFETY: The returned cpumask_var is initialized right after this call.
3078961b8cbSViresh Kumar         let mut cpumask_var = unsafe { Self::new(GFP_KERNEL) }?;
3088961b8cbSViresh Kumar 
3098961b8cbSViresh Kumar         cpumask.copy(&mut cpumask_var);
3108961b8cbSViresh Kumar         Ok(cpumask_var)
3118961b8cbSViresh Kumar     }
3128961b8cbSViresh Kumar }
3138961b8cbSViresh Kumar 
3148961b8cbSViresh Kumar // Make [`CpumaskVar`] behave like a pointer to [`Cpumask`].
3158961b8cbSViresh Kumar impl Deref for CpumaskVar {
3168961b8cbSViresh Kumar     type Target = Cpumask;
3178961b8cbSViresh Kumar 
3188961b8cbSViresh Kumar     #[cfg(CONFIG_CPUMASK_OFFSTACK)]
deref(&self) -> &Self::Target3198961b8cbSViresh Kumar     fn deref(&self) -> &Self::Target {
3208961b8cbSViresh Kumar         // SAFETY: The caller owns CpumaskVar, so it is safe to deref the cpumask.
3218961b8cbSViresh Kumar         unsafe { &*self.ptr.as_ptr() }
3228961b8cbSViresh Kumar     }
3238961b8cbSViresh Kumar 
3248961b8cbSViresh Kumar     #[cfg(not(CONFIG_CPUMASK_OFFSTACK))]
deref(&self) -> &Self::Target3258961b8cbSViresh Kumar     fn deref(&self) -> &Self::Target {
3268961b8cbSViresh Kumar         &self.mask
3278961b8cbSViresh Kumar     }
3288961b8cbSViresh Kumar }
3298961b8cbSViresh Kumar 
3308961b8cbSViresh Kumar impl DerefMut for CpumaskVar {
3318961b8cbSViresh Kumar     #[cfg(CONFIG_CPUMASK_OFFSTACK)]
deref_mut(&mut self) -> &mut Cpumask3328961b8cbSViresh Kumar     fn deref_mut(&mut self) -> &mut Cpumask {
3338961b8cbSViresh Kumar         // SAFETY: The caller owns CpumaskVar, so it is safe to deref the cpumask.
3348961b8cbSViresh Kumar         unsafe { self.ptr.as_mut() }
3358961b8cbSViresh Kumar     }
3368961b8cbSViresh Kumar 
3378961b8cbSViresh Kumar     #[cfg(not(CONFIG_CPUMASK_OFFSTACK))]
deref_mut(&mut self) -> &mut Cpumask3388961b8cbSViresh Kumar     fn deref_mut(&mut self) -> &mut Cpumask {
3398961b8cbSViresh Kumar         &mut self.mask
3408961b8cbSViresh Kumar     }
3418961b8cbSViresh Kumar }
3428961b8cbSViresh Kumar 
3438961b8cbSViresh Kumar impl Drop for CpumaskVar {
drop(&mut self)3448961b8cbSViresh Kumar     fn drop(&mut self) {
3458961b8cbSViresh Kumar         #[cfg(CONFIG_CPUMASK_OFFSTACK)]
3468961b8cbSViresh Kumar         // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `free_cpumask_var`.
3478961b8cbSViresh Kumar         unsafe {
3488961b8cbSViresh Kumar             bindings::free_cpumask_var(self.as_raw())
3498961b8cbSViresh Kumar         };
3508961b8cbSViresh Kumar     }
3518961b8cbSViresh Kumar }
352