Skip to content

Commit 81aabd1

Browse files
committed
feat(sync): use bindings to provide a content storage for r3::sync::Mutex
> - `r3::sync::Mutex` is now backed by bindings (`Bind`). The default > value is now `<T as Default>::default()` instead of `<T as Init>:: > INIT`. Additional options are available, which means you no longer > have to implement `Init` just to put a custom type in `Mutex`, and > that each `Mutex` can have a distinct initial value.
1 parent c350a3c commit 81aabd1

File tree

7 files changed

+402
-48
lines changed

7 files changed

+402
-48
lines changed

examples/basic_wio_terminal/src/main.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -698,23 +698,21 @@ mod queue {
698698
waiting_writer: Option<CryoRef<LocalTask<System>, AtomicLock>>,
699699
}
700700

701-
impl<System: SupportedSystem, T: Init> Init for QueueSt<System, T> {
702-
const INIT: Self = Self {
703-
buf: [T::INIT; CAP],
704-
read_i: 0,
705-
len: 0,
706-
waiting_reader: None,
707-
waiting_writer: None,
708-
};
709-
}
710-
711-
impl<System: SupportedSystem, T: Init + Copy + 'static> Queue<System, T> {
701+
impl<System: SupportedSystem, T: Init + Copy + Send + 'static> Queue<System, T> {
712702
pub const fn new<C>(cfg: &mut Cfg<C>) -> Self
713703
where
714704
C: ~const traits::CfgBase<System = System> + ~const traits::CfgMutex,
715705
{
716706
Self {
717-
st: StaticMutex::define().finish(cfg),
707+
st: StaticMutex::define()
708+
.init(|| QueueSt {
709+
buf: [T::INIT; CAP],
710+
read_i: 0,
711+
len: 0,
712+
waiting_reader: None,
713+
waiting_writer: None,
714+
})
715+
.finish(cfg),
718716
reader_lock: StaticMutex::define().finish(cfg),
719717
writer_lock: StaticMutex::define().finish(cfg),
720718
}

src/r3/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ While much of the application-level API has retained its general shape, there ar
1818
- `r3::kernel::ResultCode::BadId` was renamed to `NoAccess` and covers general protection failures detected by a now-optional protection mechanism. This means that application and library code can't rely on `NoAccess` being returned reliably anymore (it can't anyway once owned handles are implemented), and that a kernel implementation may use this error code to indicate that a given kernel object ID might be valid, but the caller lacks the necessary privileges to access that object.
1919
- The `chrono` Cargo feature was renamed to `chrono_0p4`.
2020
- `r3::sync` is now gated by `cfg(feature = "sync")`.
21+
- `r3::sync::Mutex` is now backed by bindings (`Bind`). The default value is now `<T as Default>::default()` instead of `<T as Init>::INIT`. Additional options are available, which means you no longer have to implement `Init` just to put a custom type in `Mutex`, and that each `Mutex` can have a distinct initial value.
2122

2223
TODO
2324

src/r3/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
#![feature(arbitrary_enum_discriminant)]
2+
#![feature(type_changing_struct_update)]
3+
#![feature(const_precise_live_drops)]
4+
#![feature(const_fn_fn_ptr_basics)]
25
#![feature(const_fn_trait_bound)]
36
#![feature(const_trait_impl)]
47
#![feature(const_mut_refs)]

src/r3/src/sync/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
//! Safe synchronization primitives.
2+
#[macro_use]
3+
pub mod source;
24
pub mod mutex;
35
pub mod recursive_mutex;
46
#[doc(no_inline)]

src/r3/src/sync/mutex.rs

Lines changed: 58 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,24 @@ use core::{
22
cell::UnsafeCell,
33
fmt,
44
marker::PhantomData,
5+
mem::MaybeUninit,
56
ops::{Deref, DerefMut},
67
};
78

89
use crate::{
9-
hunk::{DefaultInitTag, Hunk, HunkDefiner, HunkIniter},
10+
hunk::Hunk,
1011
kernel::{
1112
mutex, prelude::*, traits, Cfg, LockMutexError, MarkConsistentMutexError, MutexProtocol,
1213
TryLockMutexError,
1314
},
15+
sync::source::{DefaultSource, Source},
16+
utils::Init,
1417
};
1518

1619
/// The definer (static builder) for [`StaticMutex`][].
17-
pub struct Definer<System, T, InitTag> {
20+
pub struct Definer<System, Source> {
1821
mutex: mutex::MutexDefiner<System>,
19-
hunk: HunkDefiner<System, UnsafeCell<T>, InitTag>,
22+
source: Source,
2023
}
2124

2225
/// A mutual exclusion primitive useful for protecting shared data from
@@ -73,7 +76,7 @@ pub struct GenericMutex<Cell, Mutex> {
7376
/// .priority(1)
7477
/// .finish(cfg);
7578
///
76-
/// let mutex = StaticMutex::define().finish(cfg);
79+
/// let mutex = StaticMutex::define().init(|| 1).finish(cfg);
7780
///
7881
/// Objects { task2, mutex }
7982
/// }
@@ -85,31 +88,31 @@ pub struct GenericMutex<Cell, Mutex> {
8588
/// // access `*guard` until `task1` releases the lock
8689
/// COTTAGE.task2.activate().unwrap();
8790
///
88-
/// assert_eq!(*guard, 0);
89-
/// *guard = 1;
91+
/// assert_eq!(*guard, 1);
92+
/// *guard = 2;
9093
/// }
9194
///
9295
/// fn task2_body() {
9396
/// let mut guard = COTTAGE.mutex.lock().unwrap();
94-
/// assert_eq!(*guard, 1);
95-
/// *guard = 2;
97+
/// assert_eq!(*guard, 2);
98+
/// *guard = 3;
9699
/// # exit(0);
97100
/// }
98101
/// ```
99102
)]
100103
pub type StaticMutex<System, T> =
101-
GenericMutex<Hunk<System, UnsafeCell<T>>, mutex::StaticMutex<System>>;
104+
GenericMutex<Hunk<System, UnsafeCell<MaybeUninit<T>>>, mutex::StaticMutex<System>>;
102105

103106
// TODO: Test the panicking behavior on invalid unlock order
104107
// TODO: Test the abandonment behavior
105108
// TODO: Owned version
106109

107110
unsafe impl<Cell, Mutex, T: Send> Send for GenericMutex<Cell, Mutex> where
108-
Cell: Deref<Target = UnsafeCell<T>>
111+
Cell: Deref<Target = UnsafeCell<MaybeUninit<T>>>
109112
{
110113
}
111114
unsafe impl<Cell, Mutex, T: Send> Sync for GenericMutex<Cell, Mutex> where
112-
Cell: Deref<Target = UnsafeCell<T>>
115+
Cell: Deref<Target = UnsafeCell<MaybeUninit<T>>>
113116
{
114117
}
115118

@@ -129,11 +132,11 @@ pub struct GenericMutexGuard<'a, Cell, Mutex: mutex::MutexHandle> {
129132

130133
/// The specialization of [`GenericMutexGuard`] for [`StaticMutex`].
131134
pub type StaticMutexGuard<'a, System, T> =
132-
GenericMutexGuard<'a, Hunk<System, UnsafeCell<T>>, mutex::MutexRef<'a, System>>;
135+
GenericMutexGuard<'a, Hunk<System, UnsafeCell<MaybeUninit<T>>>, mutex::MutexRef<'a, System>>;
133136

134137
unsafe impl<Cell, Mutex, T: Sync> Sync for GenericMutexGuard<'_, Cell, Mutex>
135138
where
136-
Cell: Deref<Target = UnsafeCell<T>>,
139+
Cell: Deref<Target = UnsafeCell<MaybeUninit<T>>>,
137140
Mutex: mutex::MutexHandle,
138141
{
139142
}
@@ -233,17 +236,17 @@ where
233236
{
234237
/// Construct a `Definer` to define a mutex in [a configuration
235238
/// function](crate#static-configuration).
236-
pub const fn define() -> Definer<System, T, DefaultInitTag> {
239+
pub const fn define() -> Definer<System, DefaultSource<T>> {
237240
Definer {
238241
mutex: mutex::StaticMutex::define(),
239-
hunk: Hunk::define(),
242+
source: DefaultSource::INIT, // [ref:default_source_is_default]
240243
}
241244
}
242245
}
243246

244-
impl<System, T: 'static, InitTag> Definer<System, T, InitTag>
247+
impl<System, Source> Definer<System, Source>
245248
where
246-
System: traits::KernelMutex + traits::KernelStatic,
249+
System: traits::KernelMutex,
247250
{
248251
/// Specify the mutex's protocol. Defaults to `None` when unspecified.
249252
pub const fn protocol(self, protocol: MutexProtocol) -> Self {
@@ -254,7 +257,13 @@ where
254257
}
255258
}
256259

257-
impl<System, T: 'static, InitTag: HunkIniter<UnsafeCell<T>>> Definer<System, T, InitTag>
260+
// Define methods to set `Definer::source`
261+
impl_source_setter!(impl Definer<System, #Source>);
262+
263+
/// # Finalization
264+
///
265+
/// The following method completes the definition of a mutex.
266+
impl<System, Source> Definer<System, Source>
258267
where
259268
System: traits::KernelMutex + traits::KernelStatic,
260269
{
@@ -263,17 +272,20 @@ where
263272
pub const fn finish<C: ~const traits::CfgMutex<System = System> + ~const traits::CfgBase>(
264273
self,
265274
cfg: &mut Cfg<C>,
266-
) -> StaticMutex<System, T> {
275+
) -> StaticMutex<System, Source::Target>
276+
where
277+
Source: ~const self::Source<System>,
278+
{
267279
GenericMutex {
268-
cell: self.hunk.finish(cfg),
280+
cell: self.source.into_unsafe_cell_hunk(cfg),
269281
mutex: self.mutex.finish(cfg),
270282
}
271283
}
272284
}
273285

274286
impl<Cell, Mutex, T> GenericMutex<Cell, Mutex>
275287
where
276-
Cell: Deref<Target = UnsafeCell<T>>,
288+
Cell: Deref<Target = UnsafeCell<MaybeUninit<T>>>,
277289
Mutex: mutex::MutexHandle,
278290
{
279291
/// Acquire the mutex, blocking the current thread until it is able to do
@@ -327,13 +339,13 @@ where
327339
/// Get a raw pointer to the contained data.
328340
#[inline]
329341
pub fn get_ptr(&self) -> *mut T {
330-
self.cell.get()
342+
self.cell.get().cast()
331343
}
332344
}
333345

334346
impl<Cell, Mutex, T: fmt::Debug> fmt::Debug for GenericMutex<Cell, Mutex>
335347
where
336-
Cell: Deref<Target = UnsafeCell<T>>,
348+
Cell: Deref<Target = UnsafeCell<MaybeUninit<T>>>,
337349
Mutex: mutex::MutexHandle,
338350
{
339351
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -396,7 +408,7 @@ where
396408

397409
impl<Cell, Mutex, T: fmt::Debug> fmt::Debug for GenericMutexGuard<'_, Cell, Mutex>
398410
where
399-
Cell: Deref<Target = UnsafeCell<T>>,
411+
Cell: Deref<Target = UnsafeCell<MaybeUninit<T>>>,
400412
Mutex: mutex::MutexHandle,
401413
{
402414
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -406,7 +418,7 @@ where
406418

407419
impl<Cell, Mutex, T: fmt::Display> fmt::Display for GenericMutexGuard<'_, Cell, Mutex>
408420
where
409-
Cell: Deref<Target = UnsafeCell<T>>,
421+
Cell: Deref<Target = UnsafeCell<MaybeUninit<T>>>,
410422
Mutex: mutex::MutexHandle,
411423
{
412424
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -428,37 +440,47 @@ where
428440

429441
impl<Cell, Mutex, T> Deref for GenericMutexGuard<'_, Cell, Mutex>
430442
where
431-
Cell: Deref<Target = UnsafeCell<T>>,
443+
// TODO: Currently `Cell` is always a `Hunk` given by `Source`, but in the
444+
// future, we might have other ways to provide `Cell`. For now we just
445+
// reference [ref:source_cell] when we're using its precondidtions
446+
// concerns memory safety. To support other variations of `Cell`, we
447+
// might need a better mechanism to express these preconditions than
448+
// to reference [ref:source_cell] whenever they are relevant.
449+
Cell: Deref<Target = UnsafeCell<MaybeUninit<T>>>,
432450
Mutex: mutex::MutexHandle,
433451
{
434452
type Target = T;
435453
#[inline]
436454
fn deref(&self) -> &Self::Target {
437-
// Safety: `GenericMutexGuard` represents a permit acquired from the semaphore,
438-
// which grants the bearer an exclusive access to the underlying
439-
// data
440-
unsafe { &*self.mutex.cell.get() }
455+
// Safety: `GenericMutexGuard` represents a permit acquired from the
456+
// semaphore, which grants the bearer an exclusive access to the
457+
// underlying data. Since this `Hunk` was given by `Source`
458+
// ([ref:source_cell]), we are authorized to enforce the runtime borrow
459+
// rules on its contents.
460+
//
461+
// [ref:source_cell] says that the contents may be unavailable outside
462+
// the context of an executable object. We are in the clear because
463+
// `kernel::Mutex` can only be locked in a task context.
464+
unsafe { (*self.mutex.cell.get()).assume_init_ref() }
441465
}
442466
}
443467

444468
impl<Cell, Mutex, T> DerefMut for GenericMutexGuard<'_, Cell, Mutex>
445469
where
446-
Cell: Deref<Target = UnsafeCell<T>>,
470+
Cell: Deref<Target = UnsafeCell<MaybeUninit<T>>>,
447471
Mutex: mutex::MutexHandle,
448472
{
449473
#[inline]
450474
fn deref_mut(&mut self) -> &mut Self::Target {
451-
// Safety: `GenericMutexGuard` represents a permit acquired from the semaphore,
452-
// which grants the bearer an exclusive access to the underlying
453-
// data
454-
unsafe { &mut *self.mutex.cell.get() }
475+
// Safety: See the `deref` above.
476+
unsafe { (*self.mutex.cell.get()).assume_init_mut() }
455477
}
456478
}
457479

458480
// Safety: `MutexGuard::deref` provides a stable address
459481
unsafe impl<Cell, Mutex, T> stable_deref_trait::StableDeref for GenericMutexGuard<'_, Cell, Mutex>
460482
where
461-
Cell: Deref<Target = UnsafeCell<T>>,
483+
Cell: Deref<Target = UnsafeCell<MaybeUninit<T>>>,
462484
Mutex: mutex::MutexHandle,
463485
{
464486
}

0 commit comments

Comments
 (0)