~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/rust/kernel/alloc/vec_ext.rs

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 
  3 //! Extensions to [`Vec`] for fallible allocations.
  4 
  5 use super::{AllocError, Flags};
  6 use alloc::vec::Vec;
  7 
  8 /// Extensions to [`Vec`].
  9 pub trait VecExt<T>: Sized {
 10     /// Creates a new [`Vec`] instance with at least the given capacity.
 11     ///
 12     /// # Examples
 13     ///
 14     /// ```
 15     /// let v = Vec::<u32>::with_capacity(20, GFP_KERNEL)?;
 16     ///
 17     /// assert!(v.capacity() >= 20);
 18     /// # Ok::<(), Error>(())
 19     /// ```
 20     fn with_capacity(capacity: usize, flags: Flags) -> Result<Self, AllocError>;
 21 
 22     /// Appends an element to the back of the [`Vec`] instance.
 23     ///
 24     /// # Examples
 25     ///
 26     /// ```
 27     /// let mut v = Vec::new();
 28     /// v.push(1, GFP_KERNEL)?;
 29     /// assert_eq!(&v, &[1]);
 30     ///
 31     /// v.push(2, GFP_KERNEL)?;
 32     /// assert_eq!(&v, &[1, 2]);
 33     /// # Ok::<(), Error>(())
 34     /// ```
 35     fn push(&mut self, v: T, flags: Flags) -> Result<(), AllocError>;
 36 
 37     /// Pushes clones of the elements of slice into the [`Vec`] instance.
 38     ///
 39     /// # Examples
 40     ///
 41     /// ```
 42     /// let mut v = Vec::new();
 43     /// v.push(1, GFP_KERNEL)?;
 44     ///
 45     /// v.extend_from_slice(&[20, 30, 40], GFP_KERNEL)?;
 46     /// assert_eq!(&v, &[1, 20, 30, 40]);
 47     ///
 48     /// v.extend_from_slice(&[50, 60], GFP_KERNEL)?;
 49     /// assert_eq!(&v, &[1, 20, 30, 40, 50, 60]);
 50     /// # Ok::<(), Error>(())
 51     /// ```
 52     fn extend_from_slice(&mut self, other: &[T], flags: Flags) -> Result<(), AllocError>
 53     where
 54         T: Clone;
 55 
 56     /// Ensures that the capacity exceeds the length by at least `additional` elements.
 57     ///
 58     /// # Examples
 59     ///
 60     /// ```
 61     /// let mut v = Vec::new();
 62     /// v.push(1, GFP_KERNEL)?;
 63     ///
 64     /// v.reserve(10, GFP_KERNEL)?;
 65     /// let cap = v.capacity();
 66     /// assert!(cap >= 10);
 67     ///
 68     /// v.reserve(10, GFP_KERNEL)?;
 69     /// let new_cap = v.capacity();
 70     /// assert_eq!(new_cap, cap);
 71     ///
 72     /// # Ok::<(), Error>(())
 73     /// ```
 74     fn reserve(&mut self, additional: usize, flags: Flags) -> Result<(), AllocError>;
 75 }
 76 
 77 impl<T> VecExt<T> for Vec<T> {
 78     fn with_capacity(capacity: usize, flags: Flags) -> Result<Self, AllocError> {
 79         let mut v = Vec::new();
 80         <Self as VecExt<_>>::reserve(&mut v, capacity, flags)?;
 81         Ok(v)
 82     }
 83 
 84     fn push(&mut self, v: T, flags: Flags) -> Result<(), AllocError> {
 85         <Self as VecExt<_>>::reserve(self, 1, flags)?;
 86         let s = self.spare_capacity_mut();
 87         s[0].write(v);
 88 
 89         // SAFETY: We just initialised the first spare entry, so it is safe to increase the length
 90         // by 1. We also know that the new length is <= capacity because of the previous call to
 91         // `reserve` above.
 92         unsafe { self.set_len(self.len() + 1) };
 93         Ok(())
 94     }
 95 
 96     fn extend_from_slice(&mut self, other: &[T], flags: Flags) -> Result<(), AllocError>
 97     where
 98         T: Clone,
 99     {
100         <Self as VecExt<_>>::reserve(self, other.len(), flags)?;
101         for (slot, item) in core::iter::zip(self.spare_capacity_mut(), other) {
102             slot.write(item.clone());
103         }
104 
105         // SAFETY: We just initialised the `other.len()` spare entries, so it is safe to increase
106         // the length by the same amount. We also know that the new length is <= capacity because
107         // of the previous call to `reserve` above.
108         unsafe { self.set_len(self.len() + other.len()) };
109         Ok(())
110     }
111 
112     #[cfg(any(test, testlib))]
113     fn reserve(&mut self, additional: usize, _flags: Flags) -> Result<(), AllocError> {
114         Vec::reserve(self, additional);
115         Ok(())
116     }
117 
118     #[cfg(not(any(test, testlib)))]
119     fn reserve(&mut self, additional: usize, flags: Flags) -> Result<(), AllocError> {
120         let len = self.len();
121         let cap = self.capacity();
122 
123         if cap - len >= additional {
124             return Ok(());
125         }
126 
127         if core::mem::size_of::<T>() == 0 {
128             // The capacity is already `usize::MAX` for SZTs, we can't go higher.
129             return Err(AllocError);
130         }
131 
132         // We know cap is <= `isize::MAX` because `Layout::array` fails if the resulting byte size
133         // is greater than `isize::MAX`. So the multiplication by two won't overflow.
134         let new_cap = core::cmp::max(cap * 2, len.checked_add(additional).ok_or(AllocError)?);
135         let layout = core::alloc::Layout::array::<T>(new_cap).map_err(|_| AllocError)?;
136 
137         let (old_ptr, len, cap) = destructure(self);
138 
139         // We need to make sure that `ptr` is either NULL or comes from a previous call to
140         // `krealloc_aligned`. A `Vec<T>`'s `ptr` value is not guaranteed to be NULL and might be
141         // dangling after being created with `Vec::new`. Instead, we can rely on `Vec<T>`'s capacity
142         // to be zero if no memory has been allocated yet.
143         let ptr = if cap == 0 {
144             core::ptr::null_mut()
145         } else {
146             old_ptr
147         };
148 
149         // SAFETY: `ptr` is valid because it's either NULL or comes from a previous call to
150         // `krealloc_aligned`. We also verified that the type is not a ZST.
151         let new_ptr = unsafe { super::allocator::krealloc_aligned(ptr.cast(), layout, flags) };
152         if new_ptr.is_null() {
153             // SAFETY: We are just rebuilding the existing `Vec` with no changes.
154             unsafe { rebuild(self, old_ptr, len, cap) };
155             Err(AllocError)
156         } else {
157             // SAFETY: `ptr` has been reallocated with the layout for `new_cap` elements. New cap
158             // is greater than `cap`, so it continues to be >= `len`.
159             unsafe { rebuild(self, new_ptr.cast::<T>(), len, new_cap) };
160             Ok(())
161         }
162     }
163 }
164 
165 #[cfg(not(any(test, testlib)))]
166 fn destructure<T>(v: &mut Vec<T>) -> (*mut T, usize, usize) {
167     let mut tmp = Vec::new();
168     core::mem::swap(&mut tmp, v);
169     let mut tmp = core::mem::ManuallyDrop::new(tmp);
170     let len = tmp.len();
171     let cap = tmp.capacity();
172     (tmp.as_mut_ptr(), len, cap)
173 }
174 
175 /// Rebuilds a `Vec` from a pointer, length, and capacity.
176 ///
177 /// # Safety
178 ///
179 /// The same as [`Vec::from_raw_parts`].
180 #[cfg(not(any(test, testlib)))]
181 unsafe fn rebuild<T>(v: &mut Vec<T>, ptr: *mut T, len: usize, cap: usize) {
182     // SAFETY: The safety requirements from this function satisfy those of `from_raw_parts`.
183     let mut tmp = unsafe { Vec::from_raw_parts(ptr, len, cap) };
184     core::mem::swap(&mut tmp, v);
185 }

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php