Skip to content

Commit 3c47616

Browse files
authored
Merge pull request #386 from wedsonaf/borrowed
rust: enhance `PointerWrapper`.
2 parents c93f25f + 20bf0d4 commit 3c47616

File tree

2 files changed

+101
-6
lines changed

2 files changed

+101
-6
lines changed

rust/kernel/of.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ impl OfMatchTable {
6060
}
6161

6262
impl PointerWrapper for OfMatchTable {
63+
type Borrowed = <InnerTable as PointerWrapper>::Borrowed;
64+
6365
fn into_pointer(self) -> *const c_types::c_void {
6466
// Per the invariant above, the generated pointer points to an
6567
// array of `bindings::of_device_id`, where the final element is
@@ -68,6 +70,12 @@ impl PointerWrapper for OfMatchTable {
6870
self.0.into_pointer()
6971
}
7072

73+
unsafe fn borrow(ptr: *const c_types::c_void) -> Self::Borrowed {
74+
// SAFETY: The safety requirements for this function are the same as the ones for
75+
// `InnerTable::borrow`.
76+
unsafe { InnerTable::borrow(ptr) }
77+
}
78+
7179
unsafe fn from_pointer(p: *const c_types::c_void) -> Self {
7280
// SAFETY: The passed pointer comes from a previous call to [`InnerTable::into_pointer()`].
7381
Self(unsafe { InnerTable::from_pointer(p) })

rust/kernel/types.rs

Lines changed: 93 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@
44
//!
55
//! C header: [`include/linux/types.h`](../../../../include/linux/types.h)
66
7-
use core::{ops::Deref, pin::Pin};
8-
7+
use crate::{
8+
bindings, c_types,
9+
sync::{Ref, RefCounted},
10+
};
911
use alloc::{boxed::Box, sync::Arc};
10-
11-
use crate::bindings;
12-
use crate::c_types;
13-
use crate::sync::{Ref, RefCounted};
12+
use core::{ops::Deref, pin::Pin, ptr::NonNull};
1413

1514
/// Permissions.
1615
///
@@ -37,9 +36,22 @@ impl Mode {
3736
/// in kernel data structures, for example, an implementation of [`FileOperations`] in `struct
3837
/// file::private_data`.
3938
pub trait PointerWrapper {
39+
/// Type of values borrowed between calls to [`PointerWrapper::into_pointer`] and
40+
/// [`PointerWrapper::from_pointer`].
41+
type Borrowed: Deref;
42+
4043
/// Returns the raw pointer.
4144
fn into_pointer(self) -> *const c_types::c_void;
4245

46+
/// Returns a borrowed value.
47+
///
48+
/// # Safety
49+
///
50+
/// `ptr` must have been returned by a previous call to [`PointerWrapper::into_pointer`].
51+
/// Additionally, [`PointerWrapper::from_pointer`] can only be called after *all* values
52+
/// returned by [`PointerWrapper::borrow`] have been dropped.
53+
unsafe fn borrow(ptr: *const c_types::c_void) -> Self::Borrowed;
54+
4355
/// Returns the instance back from the raw pointer.
4456
///
4557
/// # Safety
@@ -49,46 +61,121 @@ pub trait PointerWrapper {
4961
}
5062

5163
impl<T> PointerWrapper for Box<T> {
64+
type Borrowed = UnsafeReference<T>;
65+
5266
fn into_pointer(self) -> *const c_types::c_void {
5367
Box::into_raw(self) as _
5468
}
5569

70+
unsafe fn borrow(ptr: *const c_types::c_void) -> Self::Borrowed {
71+
// SAFETY: The safety requirements for this function ensure that the object is still alive,
72+
// so it is safe to dereference the raw pointer.
73+
// The safety requirements also ensure that the object remains alive for the lifetime of
74+
// the returned value.
75+
unsafe { UnsafeReference::new(&*ptr.cast()) }
76+
}
77+
5678
unsafe fn from_pointer(ptr: *const c_types::c_void) -> Self {
5779
// SAFETY: The passed pointer comes from a previous call to [`Self::into_pointer()`].
5880
unsafe { Box::from_raw(ptr as _) }
5981
}
6082
}
6183

6284
impl<T: RefCounted> PointerWrapper for Ref<T> {
85+
type Borrowed = UnsafeReference<T>;
86+
6387
fn into_pointer(self) -> *const c_types::c_void {
6488
Ref::into_raw(self) as _
6589
}
6690

91+
unsafe fn borrow(ptr: *const c_types::c_void) -> Self::Borrowed {
92+
// SAFETY: The safety requirements for this function ensure that the object is still alive,
93+
// so it is safe to dereference the raw pointer.
94+
// The safety requirements also ensure that the object remains alive for the lifetime of
95+
// the returned value.
96+
unsafe { UnsafeReference::new(&*ptr.cast()) }
97+
}
98+
6799
unsafe fn from_pointer(ptr: *const c_types::c_void) -> Self {
68100
// SAFETY: The passed pointer comes from a previous call to [`Self::into_pointer()`].
69101
unsafe { Ref::from_raw(ptr as _) }
70102
}
71103
}
72104

73105
impl<T> PointerWrapper for Arc<T> {
106+
type Borrowed = UnsafeReference<T>;
107+
74108
fn into_pointer(self) -> *const c_types::c_void {
75109
Arc::into_raw(self) as _
76110
}
77111

112+
unsafe fn borrow(ptr: *const c_types::c_void) -> Self::Borrowed {
113+
// SAFETY: The safety requirements for this function ensure that the object is still alive,
114+
// so it is safe to dereference the raw pointer.
115+
// The safety requirements also ensure that the object remains alive for the lifetime of
116+
// the returned value.
117+
unsafe { UnsafeReference::new(&*ptr.cast()) }
118+
}
119+
78120
unsafe fn from_pointer(ptr: *const c_types::c_void) -> Self {
79121
// SAFETY: The passed pointer comes from a previous call to [`Self::into_pointer()`].
80122
unsafe { Arc::from_raw(ptr as _) }
81123
}
82124
}
83125

126+
/// A reference with manually-managed lifetime.
127+
///
128+
/// # Invariants
129+
///
130+
/// There are no mutable references to the underlying object, and it remains valid for the lifetime
131+
/// of the [`UnsafeReference`] instance.
132+
pub struct UnsafeReference<T: ?Sized> {
133+
ptr: NonNull<T>,
134+
}
135+
136+
impl<T: ?Sized> UnsafeReference<T> {
137+
/// Creates a new [`UnsafeReference`] instance.
138+
///
139+
/// # Safety
140+
///
141+
/// Callers must ensure the following for the lifetime of the returned [`UnsafeReference`]
142+
/// instance:
143+
/// 1. That `obj` remains valid;
144+
/// 2. That no mutable references to `obj` are created.
145+
unsafe fn new(obj: &T) -> Self {
146+
// INVARIANT: The safety requirements of this function ensure that the invariants hold.
147+
Self {
148+
ptr: NonNull::from(obj),
149+
}
150+
}
151+
}
152+
153+
impl<T: ?Sized> Deref for UnsafeReference<T> {
154+
type Target = T;
155+
156+
fn deref(&self) -> &Self::Target {
157+
// SAFETY: By the type invariant, the object is still valid and alive, and there are no
158+
// mutable references to it.
159+
unsafe { self.ptr.as_ref() }
160+
}
161+
}
162+
84163
impl<T: PointerWrapper + Deref> PointerWrapper for Pin<T> {
164+
type Borrowed = T::Borrowed;
165+
85166
fn into_pointer(self) -> *const c_types::c_void {
86167
// SAFETY: We continue to treat the pointer as pinned by returning just a pointer to it to
87168
// the caller.
88169
let inner = unsafe { Pin::into_inner_unchecked(self) };
89170
inner.into_pointer()
90171
}
91172

173+
unsafe fn borrow(ptr: *const c_types::c_void) -> Self::Borrowed {
174+
// SAFETY: The safety requirements for this function are the same as the ones for
175+
// `T::borrow`.
176+
unsafe { T::borrow(ptr) }
177+
}
178+
92179
unsafe fn from_pointer(p: *const c_types::c_void) -> Self {
93180
// SAFETY: The object was originally pinned.
94181
// The passed pointer comes from a previous call to `inner::into_pointer()`.

0 commit comments

Comments
 (0)