-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
tokio: avoid temporary references in Link impls #4841
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
//! This module defines a macro that lets you go from a raw pointer to a struct | ||
//! to a raw pointer to a field of the struct. | ||
|
||
#[cfg(not(tokio_no_addr_of))] | ||
macro_rules! generate_addr_of_methods { | ||
( | ||
impl<$($gen:ident)*> $struct_name:ty {$( | ||
$(#[$attrs:meta])* | ||
$vis:vis unsafe fn $fn_name:ident(self: NonNull<Self>) -> NonNull<$field_type:ty> { | ||
&self$(.$field_name:tt)+ | ||
} | ||
)*} | ||
) => { | ||
impl<$($gen)*> $struct_name {$( | ||
$(#[$attrs])* | ||
$vis unsafe fn $fn_name(me: ::core::ptr::NonNull<Self>) -> ::core::ptr::NonNull<$field_type> { | ||
let me = me.as_ptr(); | ||
let field = ::std::ptr::addr_of_mut!((*me) $(.$field_name)+ ); | ||
::core::ptr::NonNull::new_unchecked(field) | ||
} | ||
)*} | ||
}; | ||
} | ||
|
||
// The `addr_of_mut!` macro is only available for MSRV at least 1.51.0. This | ||
// version of the macro uses a workaround for older versions of rustc. | ||
#[cfg(tokio_no_addr_of)] | ||
macro_rules! generate_addr_of_methods { | ||
( | ||
impl<$($gen:ident)*> $struct_name:ty {$( | ||
$(#[$attrs:meta])* | ||
$vis:vis unsafe fn $fn_name:ident(self: NonNull<Self>) -> NonNull<$field_type:ty> { | ||
&self$(.$field_name:tt)+ | ||
} | ||
)*} | ||
) => { | ||
impl<$($gen)*> $struct_name {$( | ||
$(#[$attrs])* | ||
$vis unsafe fn $fn_name(me: ::core::ptr::NonNull<Self>) -> ::core::ptr::NonNull<$field_type> { | ||
let me = me.as_ptr(); | ||
let me_u8 = me as *mut u8; | ||
|
||
let field_offset = { | ||
let me_ref = &*me; | ||
let field_ref_u8 = (&me_ref $(.$field_name)+ ) as *const $field_type as *const u8; | ||
field_ref_u8.offset_from(me_u8) | ||
}; | ||
|
||
::core::ptr::NonNull::new_unchecked(me_u8.offset(field_offset).cast()) | ||
} | ||
)*} | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -326,7 +326,7 @@ pub(super) type EntryList = crate::util::linked_list::LinkedList<TimerShared, Ti | |
/// | ||
/// Note that this structure is located inside the `TimerEntry` structure. | ||
#[derive(Debug)] | ||
#[repr(C)] // required by `link_list::Link` impl | ||
#[repr(C)] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we keep this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you tell me There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤷♀️ The layout is pretty stupid if they're not in the order written here. I guess we will keep it. (Though Rust would always pick the same layout, at least today.) |
||
pub(crate) struct TimerShared { | ||
/// Data manipulated by the driver thread itself, only. | ||
driver_state: CachePadded<TimerSharedPadded>, | ||
|
@@ -339,6 +339,14 @@ pub(crate) struct TimerShared { | |
_p: PhantomPinned, | ||
} | ||
|
||
generate_addr_of_methods! { | ||
impl<> TimerShared { | ||
unsafe fn addr_of_pointers(self: NonNull<Self>) -> NonNull<linked_list::Pointers<TimerShared>> { | ||
&self.driver_state.0.pointers | ||
} | ||
} | ||
} | ||
|
||
impl TimerShared { | ||
pub(super) fn new() -> Self { | ||
Self { | ||
|
@@ -421,7 +429,6 @@ impl TimerShared { | |
/// padded. This contains the information that the driver thread accesses most | ||
/// frequently to minimize contention. In particular, we move it away from the | ||
/// waker, as the waker is updated on every poll. | ||
#[repr(C)] // required by `link_list::Link` impl | ||
struct TimerSharedPadded { | ||
/// A link within the doubly-linked list of timers on a particular level and | ||
/// slot. Valid only if state is equal to Registered. | ||
|
@@ -476,7 +483,7 @@ unsafe impl linked_list::Link for TimerShared { | |
unsafe fn pointers( | ||
target: NonNull<Self::Target>, | ||
) -> NonNull<linked_list::Pointers<Self::Target>> { | ||
target.cast() | ||
TimerShared::addr_of_pointers(target) | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is ok since
Pointers
already contains anUnsafeCell
.tokio/tokio/src/util/linked_list.rs
Lines 70 to 73 in 922fc91