Skip to content

Commit 3108976

Browse files
committed
Pull rust updates from Miguel Ojeda "More additions to the Rust core. Importantly, this adds the pin-init API, which will be used by other abstractions, such as the synchronization ones added here too: - pin-init API: a solution for the safe pinned initialization problem. This allows to reduce the need for 'unsafe' code in the kernel when dealing with data structures that require a stable address. Commit 90e53c5 ("rust: add pin-init API core") contains a nice introduction -- here is an example of how it looks like: #[pin_data] struct Example { #[pin] value: Mutex<u32>, #[pin] value_changed: CondVar, } impl Example { fn new() -> impl PinInit<Self> { pin_init!(Self { value <- new_mutex!(0), value_changed <- new_condvar!(), }) } } // In a `Box`. let b = Box::pin_init(Example::new())?; // In the stack. stack_pin_init!(let s = Example::new()); - 'sync' module: New types 'LockClassKey' ('struct lock_class_key'), 'Lock', 'Guard', 'Mutex' ('struct mutex'), 'SpinLock' ('spinlock_t'), 'LockedBy' and 'CondVar' (uses 'wait_queue_head_t'), plus macros such as 'static_lock_class!' and 'new_spinlock!'. In particular, 'Lock' and 'Guard' are generic implementations that contain code that is common to all locks. Then, different backends (the new 'Backend' trait) are implemented and used to define types like 'Mutex': type Mutex<T> = Lock<T, MutexBackend>; In addition, new methods 'assume_init()', 'init_with()' and 'pin_init_with()' for 'UniqueArc<MaybeUninit<T>>' and 'downcast()' for 'Arc<dyn Any + Send + Sync>'; as well as 'Debug' and 'Display' implementations for 'Arc' and 'UniqueArc'. Reduced stack usage of 'UniqueArc::try_new_uninit()', too. - 'types' module: New trait 'AlwaysRefCounted' and new type 'ARef' (an owned reference to an always-reference-counted object, meant to be used in wrappers for C types that have their own ref counting functions). Moreover, new associated functions 'raw_get()' and 'ffi_init()' for 'Opaque'. - New 'task' module with a new type 'Task' ('struct task_struct'), and a new macro 'current!' to safely get a reference to the current one. - New 'ioctl' module with new '_IOC*' const functions (equivalent to the C macros). - New 'uapi' crate, intended to be accessible by drivers directly. - 'macros' crate: new 'quote!' macro (similar to the one provided in userspace by the 'quote' crate); and the 'module!' macro now allows specifying multiple module aliases. - 'error' module: New associated functions for the 'Error' type, such as 'from_errno()' and new functions such as 'to_result()'. - 'alloc' crate: More fallible 'Vec' methods: 'try_resize` and 'try_extend_from_slice' and the infrastructure (imported from the Rust standard library) they need" * tag 'rust-6.4' of https://github.com/Rust-for-Linux/linux: (44 commits) rust: ioctl: Add ioctl number manipulation functions rust: uapi: Add UAPI crate rust: sync: introduce `CondVar` rust: lock: add `Guard::do_unlocked` rust: sync: introduce `LockedBy` rust: introduce `current` rust: add basic `Task` rust: introduce `ARef` rust: lock: introduce `SpinLock` rust: lock: introduce `Mutex` rust: sync: introduce `Lock` and `Guard` rust: sync: introduce `LockClassKey` MAINTAINERS: add Benno Lossin as Rust reviewer rust: init: broaden the blanket impl of `Init` rust: sync: add functions for initializing `UniqueArc<MaybeUninit<T>>` rust: sync: reduce stack usage of `UniqueArc::try_new_uninit` rust: types: add `Opaque::ffi_init` rust: prelude: add `pin-init` API items to prelude rust: init: add `Zeroable` trait and `init::zeroed` function rust: init: add `stack_pin_init!` macro ...
2 parents 825a071 + ea76e08 commit 3108976

35 files changed

Lines changed: 4980 additions & 24 deletions

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18346,6 +18346,7 @@ M: Wedson Almeida Filho <wedsonaf@gmail.com>
1834618346
R: Boqun Feng <boqun.feng@gmail.com>
1834718347
R: Gary Guo <gary@garyguo.net>
1834818348
R: Björn Roy Baron <bjorn3_gh@protonmail.com>
18349+
R: Benno Lossin <benno.lossin@proton.me>
1834918350
L: rust-for-linux@vger.kernel.org
1835018351
S: Supported
1835118352
W: https://github.com/Rust-for-Linux/linux

rust/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
bindings_generated.rs
44
bindings_helpers_generated.rs
5+
uapi_generated.rs
56
exports_*_generated.h
67
doc/
78
test/

rust/Makefile

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ obj-$(CONFIG_RUST) += alloc.o bindings.o kernel.o
1616
always-$(CONFIG_RUST) += exports_alloc_generated.h exports_bindings_generated.h \
1717
exports_kernel_generated.h
1818

19+
always-$(CONFIG_RUST) += uapi/uapi_generated.rs
20+
obj-$(CONFIG_RUST) += uapi.o
21+
1922
ifdef CONFIG_RUST_BUILD_ASSERT_ALLOW
2023
obj-$(CONFIG_RUST) += build_error.o
2124
else
@@ -113,7 +116,7 @@ rustdoc-alloc: $(src)/alloc/lib.rs rustdoc-core rustdoc-compiler_builtins FORCE
113116

114117
rustdoc-kernel: private rustc_target_flags = --extern alloc \
115118
--extern build_error --extern macros=$(objtree)/$(obj)/libmacros.so \
116-
--extern bindings
119+
--extern bindings --extern uapi
117120
rustdoc-kernel: $(src)/kernel/lib.rs rustdoc-core rustdoc-macros \
118121
rustdoc-compiler_builtins rustdoc-alloc $(obj)/libmacros.so \
119122
$(obj)/bindings.o FORCE
@@ -141,6 +144,9 @@ rusttestlib-macros: $(src)/macros/lib.rs rusttest-prepare FORCE
141144
rusttestlib-bindings: $(src)/bindings/lib.rs rusttest-prepare FORCE
142145
$(call if_changed,rustc_test_library)
143146

147+
rusttestlib-uapi: $(src)/uapi/lib.rs rusttest-prepare FORCE
148+
$(call if_changed,rustc_test_library)
149+
144150
quiet_cmd_rustdoc_test = RUSTDOC T $<
145151
cmd_rustdoc_test = \
146152
OBJTREE=$(abspath $(objtree)) \
@@ -223,9 +229,10 @@ rusttest-macros: $(src)/macros/lib.rs rusttest-prepare FORCE
223229
$(call if_changed,rustdoc_test)
224230

225231
rusttest-kernel: private rustc_target_flags = --extern alloc \
226-
--extern build_error --extern macros --extern bindings
232+
--extern build_error --extern macros --extern bindings --extern uapi
227233
rusttest-kernel: $(src)/kernel/lib.rs rusttest-prepare \
228-
rusttestlib-build_error rusttestlib-macros rusttestlib-bindings FORCE
234+
rusttestlib-build_error rusttestlib-macros rusttestlib-bindings \
235+
rusttestlib-uapi FORCE
229236
$(call if_changed,rustc_test)
230237
$(call if_changed,rustc_test_library)
231238

@@ -302,6 +309,12 @@ $(obj)/bindings/bindings_generated.rs: $(src)/bindings/bindings_helper.h \
302309
$(src)/bindgen_parameters FORCE
303310
$(call if_changed_dep,bindgen)
304311

312+
$(obj)/uapi/uapi_generated.rs: private bindgen_target_flags = \
313+
$(shell grep -v '^#\|^$$' $(srctree)/$(src)/bindgen_parameters)
314+
$(obj)/uapi/uapi_generated.rs: $(src)/uapi/uapi_helper.h \
315+
$(src)/bindgen_parameters FORCE
316+
$(call if_changed_dep,bindgen)
317+
305318
# See `CFLAGS_REMOVE_helpers.o` above. In addition, Clang on C does not warn
306319
# with `-Wmissing-declarations` (unlike GCC), so it is not strictly needed here
307320
# given it is `libclang`; but for consistency, future Clang changes and/or
@@ -402,10 +415,15 @@ $(obj)/bindings.o: $(src)/bindings/lib.rs \
402415
$(obj)/bindings/bindings_helpers_generated.rs FORCE
403416
$(call if_changed_dep,rustc_library)
404417

418+
$(obj)/uapi.o: $(src)/uapi/lib.rs \
419+
$(obj)/compiler_builtins.o \
420+
$(obj)/uapi/uapi_generated.rs FORCE
421+
$(call if_changed_dep,rustc_library)
422+
405423
$(obj)/kernel.o: private rustc_target_flags = --extern alloc \
406-
--extern build_error --extern macros --extern bindings
424+
--extern build_error --extern macros --extern bindings --extern uapi
407425
$(obj)/kernel.o: $(src)/kernel/lib.rs $(obj)/alloc.o $(obj)/build_error.o \
408-
$(obj)/libmacros.so $(obj)/bindings.o FORCE
426+
$(obj)/libmacros.so $(obj)/bindings.o $(obj)/uapi.o FORCE
409427
$(call if_changed_dep,rustc_library)
410428

411429
endif # CONFIG_RUST

rust/alloc/vec/mod.rs

Lines changed: 134 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,8 @@ use self::spec_from_elem::SpecFromElem;
122122
#[cfg(not(no_global_oom_handling))]
123123
mod spec_from_elem;
124124

125-
#[cfg(not(no_global_oom_handling))]
126125
use self::set_len_on_drop::SetLenOnDrop;
127126

128-
#[cfg(not(no_global_oom_handling))]
129127
mod set_len_on_drop;
130128

131129
#[cfg(not(no_global_oom_handling))]
@@ -149,7 +147,8 @@ mod spec_from_iter;
149147
#[cfg(not(no_global_oom_handling))]
150148
use self::spec_extend::SpecExtend;
151149

152-
#[cfg(not(no_global_oom_handling))]
150+
use self::spec_extend::TrySpecExtend;
151+
153152
mod spec_extend;
154153

155154
/// A contiguous growable array type, written as `Vec<T>`, short for 'vector'.
@@ -1919,6 +1918,17 @@ impl<T, A: Allocator> Vec<T, A> {
19191918
self.len += count;
19201919
}
19211920

1921+
/// Tries to append elements to `self` from other buffer.
1922+
#[inline]
1923+
unsafe fn try_append_elements(&mut self, other: *const [T]) -> Result<(), TryReserveError> {
1924+
let count = unsafe { (*other).len() };
1925+
self.try_reserve(count)?;
1926+
let len = self.len();
1927+
unsafe { ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count) };
1928+
self.len += count;
1929+
Ok(())
1930+
}
1931+
19221932
/// Removes the specified range from the vector in bulk, returning all
19231933
/// removed elements as an iterator. If the iterator is dropped before
19241934
/// being fully consumed, it drops the remaining removed elements.
@@ -2340,6 +2350,45 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
23402350
}
23412351
}
23422352

2353+
/// Tries to resize the `Vec` in-place so that `len` is equal to `new_len`.
2354+
///
2355+
/// If `new_len` is greater than `len`, the `Vec` is extended by the
2356+
/// difference, with each additional slot filled with `value`.
2357+
/// If `new_len` is less than `len`, the `Vec` is simply truncated.
2358+
///
2359+
/// This method requires `T` to implement [`Clone`],
2360+
/// in order to be able to clone the passed value.
2361+
/// If you need more flexibility (or want to rely on [`Default`] instead of
2362+
/// [`Clone`]), use [`Vec::resize_with`].
2363+
/// If you only need to resize to a smaller size, use [`Vec::truncate`].
2364+
///
2365+
/// # Examples
2366+
///
2367+
/// ```
2368+
/// let mut vec = vec!["hello"];
2369+
/// vec.try_resize(3, "world").unwrap();
2370+
/// assert_eq!(vec, ["hello", "world", "world"]);
2371+
///
2372+
/// let mut vec = vec![1, 2, 3, 4];
2373+
/// vec.try_resize(2, 0).unwrap();
2374+
/// assert_eq!(vec, [1, 2]);
2375+
///
2376+
/// let mut vec = vec![42];
2377+
/// let result = vec.try_resize(usize::MAX, 0);
2378+
/// assert!(result.is_err());
2379+
/// ```
2380+
#[stable(feature = "kernel", since = "1.0.0")]
2381+
pub fn try_resize(&mut self, new_len: usize, value: T) -> Result<(), TryReserveError> {
2382+
let len = self.len();
2383+
2384+
if new_len > len {
2385+
self.try_extend_with(new_len - len, ExtendElement(value))
2386+
} else {
2387+
self.truncate(new_len);
2388+
Ok(())
2389+
}
2390+
}
2391+
23432392
/// Clones and appends all elements in a slice to the `Vec`.
23442393
///
23452394
/// Iterates over the slice `other`, clones each element, and then appends
@@ -2365,6 +2414,30 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
23652414
self.spec_extend(other.iter())
23662415
}
23672416

2417+
/// Tries to clone and append all elements in a slice to the `Vec`.
2418+
///
2419+
/// Iterates over the slice `other`, clones each element, and then appends
2420+
/// it to this `Vec`. The `other` slice is traversed in-order.
2421+
///
2422+
/// Note that this function is same as [`extend`] except that it is
2423+
/// specialized to work with slices instead. If and when Rust gets
2424+
/// specialization this function will likely be deprecated (but still
2425+
/// available).
2426+
///
2427+
/// # Examples
2428+
///
2429+
/// ```
2430+
/// let mut vec = vec![1];
2431+
/// vec.try_extend_from_slice(&[2, 3, 4]).unwrap();
2432+
/// assert_eq!(vec, [1, 2, 3, 4]);
2433+
/// ```
2434+
///
2435+
/// [`extend`]: Vec::extend
2436+
#[stable(feature = "kernel", since = "1.0.0")]
2437+
pub fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), TryReserveError> {
2438+
self.try_spec_extend(other.iter())
2439+
}
2440+
23682441
/// Copies elements from `src` range to the end of the vector.
23692442
///
23702443
/// # Panics
@@ -2504,6 +2577,36 @@ impl<T, A: Allocator> Vec<T, A> {
25042577
// len set by scope guard
25052578
}
25062579
}
2580+
2581+
/// Try to extend the vector by `n` values, using the given generator.
2582+
fn try_extend_with<E: ExtendWith<T>>(&mut self, n: usize, mut value: E) -> Result<(), TryReserveError> {
2583+
self.try_reserve(n)?;
2584+
2585+
unsafe {
2586+
let mut ptr = self.as_mut_ptr().add(self.len());
2587+
// Use SetLenOnDrop to work around bug where compiler
2588+
// might not realize the store through `ptr` through self.set_len()
2589+
// don't alias.
2590+
let mut local_len = SetLenOnDrop::new(&mut self.len);
2591+
2592+
// Write all elements except the last one
2593+
for _ in 1..n {
2594+
ptr::write(ptr, value.next());
2595+
ptr = ptr.offset(1);
2596+
// Increment the length in every step in case next() panics
2597+
local_len.increment_len(1);
2598+
}
2599+
2600+
if n > 0 {
2601+
// We can write the last element directly without cloning needlessly
2602+
ptr::write(ptr, value.last());
2603+
local_len.increment_len(1);
2604+
}
2605+
2606+
// len set by scope guard
2607+
Ok(())
2608+
}
2609+
}
25072610
}
25082611

25092612
impl<T: PartialEq, A: Allocator> Vec<T, A> {
@@ -2838,6 +2941,34 @@ impl<T, A: Allocator> Vec<T, A> {
28382941
}
28392942
}
28402943

2944+
// leaf method to which various SpecFrom/SpecExtend implementations delegate when
2945+
// they have no further optimizations to apply
2946+
fn try_extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) -> Result<(), TryReserveError> {
2947+
// This is the case for a general iterator.
2948+
//
2949+
// This function should be the moral equivalent of:
2950+
//
2951+
// for item in iterator {
2952+
// self.push(item);
2953+
// }
2954+
while let Some(element) = iterator.next() {
2955+
let len = self.len();
2956+
if len == self.capacity() {
2957+
let (lower, _) = iterator.size_hint();
2958+
self.try_reserve(lower.saturating_add(1))?;
2959+
}
2960+
unsafe {
2961+
ptr::write(self.as_mut_ptr().add(len), element);
2962+
// Since next() executes user code which can panic we have to bump the length
2963+
// after each step.
2964+
// NB can't overflow since we would have had to alloc the address space
2965+
self.set_len(len + 1);
2966+
}
2967+
}
2968+
2969+
Ok(())
2970+
}
2971+
28412972
/// Creates a splicing iterator that replaces the specified range in the vector
28422973
/// with the given `replace_with` iterator and yields the removed items.
28432974
/// `replace_with` does not need to be the same length as `range`.

rust/alloc/vec/set_len_on_drop.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// SPDX-License-Identifier: Apache-2.0 OR MIT
2+
3+
// Set the length of the vec when the `SetLenOnDrop` value goes out of scope.
4+
//
5+
// The idea is: The length field in SetLenOnDrop is a local variable
6+
// that the optimizer will see does not alias with any stores through the Vec's data
7+
// pointer. This is a workaround for alias analysis issue #32155
8+
pub(super) struct SetLenOnDrop<'a> {
9+
len: &'a mut usize,
10+
local_len: usize,
11+
}
12+
13+
impl<'a> SetLenOnDrop<'a> {
14+
#[inline]
15+
pub(super) fn new(len: &'a mut usize) -> Self {
16+
SetLenOnDrop { local_len: *len, len }
17+
}
18+
19+
#[inline]
20+
pub(super) fn increment_len(&mut self, increment: usize) {
21+
self.local_len += increment;
22+
}
23+
}
24+
25+
impl Drop for SetLenOnDrop<'_> {
26+
#[inline]
27+
fn drop(&mut self) {
28+
*self.len = self.local_len;
29+
}
30+
}

0 commit comments

Comments
 (0)