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