Add Send/Sync
bounds to PeripheralState
This commit is contained in:
parent
ff9ff5e43a
commit
1b7ad7080e
6 changed files with 44 additions and 24 deletions
|
@ -5,18 +5,26 @@ use core::ptr;
|
||||||
|
|
||||||
use embassy::interrupt::{Interrupt, InterruptExt};
|
use embassy::interrupt::{Interrupt, InterruptExt};
|
||||||
|
|
||||||
|
/// A version of `PeripheralState` without the `'static` bound,
|
||||||
|
/// for cases where the compiler can't statically make sure
|
||||||
|
/// that `on_interrupt` doesn't reference anything which might be invalidated.
|
||||||
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// When types implementing this trait are used with `PeripheralMutex`,
|
/// When types implementing this trait are used with `PeripheralMutex`,
|
||||||
/// no fields referenced by `on_interrupt`'s lifetimes must end without first calling `Drop` on the `PeripheralMutex`.
|
/// no fields referenced by `on_interrupt`'s lifetimes must end without first calling `Drop` on the `PeripheralMutex`.
|
||||||
pub unsafe trait PeripheralStateUnchecked {
|
pub unsafe trait PeripheralStateUnchecked: Send {
|
||||||
type Interrupt: Interrupt;
|
type Interrupt: Interrupt;
|
||||||
fn on_interrupt(&mut self);
|
fn on_interrupt(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
// `PeripheralMutex` is safe because `Pin` guarantees that the memory it references will not be invalidated or reused
|
/// A type which can be used as state with `PeripheralMutex`.
|
||||||
// without calling `Drop`. However, it provides no guarantees about references contained within the state still being valid,
|
///
|
||||||
// so this `'static` bound is necessary.
|
/// It needs to be `Send` because `&mut` references are sent back and forth between the 'thread' which owns the `PeripheralMutex` and the interrupt,
|
||||||
pub trait PeripheralState: 'static {
|
/// and `&mut T` is `Send` where `T: Send`.
|
||||||
|
///
|
||||||
|
/// It also requires `'static`, because although `Pin` guarantees that the memory of the state won't be invalidated,
|
||||||
|
/// it doesn't guarantee that the lifetime will last.
|
||||||
|
pub trait PeripheralState: Send + 'static {
|
||||||
type Interrupt: Interrupt;
|
type Interrupt: Interrupt;
|
||||||
fn on_interrupt(&mut self);
|
fn on_interrupt(&mut self);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,18 +4,25 @@ use core::ptr;
|
||||||
|
|
||||||
use embassy::interrupt::{Interrupt, InterruptExt};
|
use embassy::interrupt::{Interrupt, InterruptExt};
|
||||||
|
|
||||||
|
/// A version of `PeripheralState` without the `'static` bound,
|
||||||
|
/// for cases where the compiler can't statically make sure
|
||||||
|
/// that `on_interrupt` doesn't reference anything which might be invalidated.
|
||||||
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// When types implementing this trait are used with `Peripheral`,
|
/// When types implementing this trait are used with `Peripheral`,
|
||||||
/// no fields referenced by `on_interrupt`'s lifetimes must end without first calling `Drop` on the `Peripheral`.
|
/// no fields referenced by `on_interrupt`'s lifetimes must end without first calling `Drop` on the `Peripheral`.
|
||||||
pub unsafe trait PeripheralStateUnchecked {
|
pub unsafe trait PeripheralStateUnchecked: Sync {
|
||||||
type Interrupt: Interrupt;
|
type Interrupt: Interrupt;
|
||||||
fn on_interrupt(&self);
|
fn on_interrupt(&self);
|
||||||
}
|
}
|
||||||
|
|
||||||
// `Peripheral` is safe because `Pin` guarantees that the memory it references will not be invalidated or reused
|
/// A type which can be used as state with `Peripheral`.
|
||||||
// without calling `Drop`. However, it provides no guarantees about references contained within the state still being valid,
|
///
|
||||||
// so this `'static` bound is necessary.
|
/// It needs to be `Sync` because references are shared between the 'thread' which owns the `Peripheral` and the interrupt.
|
||||||
pub trait PeripheralState: 'static {
|
///
|
||||||
|
/// It also requires `'static`, because although `Pin` guarantees that the memory of the state won't be invalidated,
|
||||||
|
/// it doesn't guarantee that the lifetime will last.
|
||||||
|
pub trait PeripheralState: Sync + 'static {
|
||||||
type Interrupt: Interrupt;
|
type Interrupt: Interrupt;
|
||||||
fn on_interrupt(&self);
|
fn on_interrupt(&self);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use embassy::interrupt::Interrupt;
|
||||||
use usb_serial::{ReadInterface, UsbSerial, WriteInterface};
|
use usb_serial::{ReadInterface, UsbSerial, WriteInterface};
|
||||||
|
|
||||||
/// Marker trait to mark an interrupt to be used with the [`Usb`] abstraction.
|
/// Marker trait to mark an interrupt to be used with the [`Usb`] abstraction.
|
||||||
pub unsafe trait USBInterrupt: Interrupt {}
|
pub unsafe trait USBInterrupt: Interrupt + Send {}
|
||||||
|
|
||||||
pub(crate) struct State<'bus, B, T, I>
|
pub(crate) struct State<'bus, B, T, I>
|
||||||
where
|
where
|
||||||
|
@ -140,7 +140,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ClassSet<B: UsbBus> {
|
pub trait ClassSet<B: UsbBus>: Send {
|
||||||
fn poll_all(&mut self, device: &mut UsbDevice<'_, B>) -> bool;
|
fn poll_all(&mut self, device: &mut UsbDevice<'_, B>) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,8 +176,8 @@ pub struct Index1;
|
||||||
|
|
||||||
impl<B, C1> ClassSet<B> for ClassSet1<B, C1>
|
impl<B, C1> ClassSet<B> for ClassSet1<B, C1>
|
||||||
where
|
where
|
||||||
B: UsbBus,
|
B: UsbBus + Send,
|
||||||
C1: UsbClass<B>,
|
C1: UsbClass<B> + Send,
|
||||||
{
|
{
|
||||||
fn poll_all(&mut self, device: &mut UsbDevice<'_, B>) -> bool {
|
fn poll_all(&mut self, device: &mut UsbDevice<'_, B>) -> bool {
|
||||||
device.poll(&mut [&mut self.class])
|
device.poll(&mut [&mut self.class])
|
||||||
|
@ -186,9 +186,9 @@ where
|
||||||
|
|
||||||
impl<B, C1, C2> ClassSet<B> for ClassSet2<B, C1, C2>
|
impl<B, C1, C2> ClassSet<B> for ClassSet2<B, C1, C2>
|
||||||
where
|
where
|
||||||
B: UsbBus,
|
B: UsbBus + Send,
|
||||||
C1: UsbClass<B>,
|
C1: UsbClass<B> + Send,
|
||||||
C2: UsbClass<B>,
|
C2: UsbClass<B> + Send,
|
||||||
{
|
{
|
||||||
fn poll_all(&mut self, device: &mut UsbDevice<'_, B>) -> bool {
|
fn poll_all(&mut self, device: &mut UsbDevice<'_, B>) -> bool {
|
||||||
device.poll(&mut [&mut self.class1, &mut self.class2])
|
device.poll(&mut [&mut self.class1, &mut self.class2])
|
||||||
|
@ -197,8 +197,8 @@ where
|
||||||
|
|
||||||
impl<B, C1> IntoClassSet<B, ClassSet1<B, C1>> for C1
|
impl<B, C1> IntoClassSet<B, ClassSet1<B, C1>> for C1
|
||||||
where
|
where
|
||||||
B: UsbBus,
|
B: UsbBus + Send,
|
||||||
C1: UsbClass<B>,
|
C1: UsbClass<B> + Send,
|
||||||
{
|
{
|
||||||
fn into_class_set(self) -> ClassSet1<B, C1> {
|
fn into_class_set(self) -> ClassSet1<B, C1> {
|
||||||
ClassSet1 {
|
ClassSet1 {
|
||||||
|
@ -210,9 +210,9 @@ where
|
||||||
|
|
||||||
impl<B, C1, C2> IntoClassSet<B, ClassSet2<B, C1, C2>> for (C1, C2)
|
impl<B, C1, C2> IntoClassSet<B, ClassSet2<B, C1, C2>> for (C1, C2)
|
||||||
where
|
where
|
||||||
B: UsbBus,
|
B: UsbBus + Send,
|
||||||
C1: UsbClass<B>,
|
C1: UsbClass<B> + Send,
|
||||||
C2: UsbClass<B>,
|
C2: UsbClass<B> + Send,
|
||||||
{
|
{
|
||||||
fn into_class_set(self) -> ClassSet2<B, C1, C2> {
|
fn into_class_set(self) -> ClassSet2<B, C1, C2> {
|
||||||
ClassSet2 {
|
ClassSet2 {
|
||||||
|
|
|
@ -29,7 +29,7 @@ pub(crate) mod sealed {
|
||||||
pub trait ExtendedInstance {}
|
pub trait ExtendedInstance {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Instance: Unborrow<Target = Self> + sealed::Instance + 'static {
|
pub trait Instance: Unborrow<Target = Self> + sealed::Instance + 'static + Send {
|
||||||
type Interrupt: Interrupt;
|
type Interrupt: Interrupt;
|
||||||
}
|
}
|
||||||
pub trait ExtendedInstance: Instance + sealed::ExtendedInstance {}
|
pub trait ExtendedInstance: Instance + sealed::ExtendedInstance {}
|
||||||
|
|
|
@ -461,7 +461,7 @@ pub(crate) mod sealed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Instance: Unborrow<Target = Self> + sealed::Instance + 'static {
|
pub trait Instance: Unborrow<Target = Self> + sealed::Instance + 'static + Send {
|
||||||
type Interrupt: Interrupt;
|
type Interrupt: Interrupt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,11 @@ impl WakerRegistration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SAFETY: `WakerRegistration` effectively contains an `Option<Waker>`,
|
||||||
|
// which is `Send` and `Sync`.
|
||||||
|
unsafe impl Send for WakerRegistration {}
|
||||||
|
unsafe impl Sync for WakerRegistration {}
|
||||||
|
|
||||||
pub struct AtomicWaker {
|
pub struct AtomicWaker {
|
||||||
waker: AtomicPtr<TaskHeader>,
|
waker: AtomicPtr<TaskHeader>,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue