Skip to content

Commit

Permalink
cpu: Make cpu::Features be !Send.
Browse files Browse the repository at this point in the history
We don't intend to put `cpu::Features` in any type that could be sent
across threads. Enforce this in the type system. This way, we can
potentially change the representation of `cpu::Features` to one that
really couldn't be `Send` in the future.
  • Loading branch information
briansmith committed Jun 14, 2024
1 parent 2071a3f commit adbe5e4
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 4 deletions.
10 changes: 7 additions & 3 deletions src/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ pub(crate) fn features() -> Features {
}

mod features {
use crate::polyfill::NotSend;

/// A witness indicating that CPU features have been detected and cached.
///
/// This is a zero-sized type so that it can be "stored" wherever convenient.
#[derive(Copy, Clone)]
pub(crate) struct Features(());
pub(crate) struct Features(NotSend);

cfg_if::cfg_if! {
if #[cfg(any(target_arch = "aarch64", target_arch = "arm",
Expand All @@ -33,19 +35,21 @@ mod features {
// SAFETY: This must only be called after CPU features have been written
// and synchronized.
pub(super) unsafe fn new_after_feature_flags_written_and_synced_unchecked() -> Self {
Self(())
Self(NotSend::VALUE)
}
}
} else {
impl Features {
pub(super) fn new_no_features_to_detect() -> Self {
Self(())
Self(NotSend::VALUE)
}
}
}
}
}

const _: () = assert!(core::mem::size_of::<Features>() == 0);

cfg_if::cfg_if! {
if #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] {
pub mod arm;
Expand Down
4 changes: 3 additions & 1 deletion src/polyfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ pub mod sliceutil;
#[cfg(feature = "alloc")]
mod leading_zeros_skipped;

mod notsend;
pub mod ptr;

pub mod slice;
Expand All @@ -64,7 +65,8 @@ mod test;
mod unwrap_const;

pub use self::{
array_flat_map::ArrayFlatMap, array_split_map::ArraySplitMap, unwrap_const::unwrap_const,
array_flat_map::ArrayFlatMap, array_split_map::ArraySplitMap, notsend::NotSend,
unwrap_const::unwrap_const,
};

#[cfg(feature = "alloc")]
Expand Down
28 changes: 28 additions & 0 deletions src/polyfill/notsend.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2024 Brian Smith.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

use crate::test;
use core::marker::PhantomData;

/// A ZST that can be added to any type to make the type `!Send`.
#[derive(Clone, Copy)]
pub struct NotSend(PhantomData<*mut ()>);

impl NotSend {
pub const VALUE: Self = Self(PhantomData);
}

const _: () = test::compile_time_assert_clone::<NotSend>();
const _: () = test::compile_time_assert_copy::<NotSend>();
const _: () = assert!(core::mem::size_of::<NotSend>() == 0);

0 comments on commit adbe5e4

Please sign in to comment.