@@ -2,21 +2,24 @@ use core::{
2
2
cell:: UnsafeCell ,
3
3
fmt,
4
4
marker:: PhantomData ,
5
+ mem:: MaybeUninit ,
5
6
ops:: { Deref , DerefMut } ,
6
7
} ;
7
8
8
9
use crate :: {
9
- hunk:: { DefaultInitTag , Hunk , HunkDefiner , HunkIniter } ,
10
+ hunk:: Hunk ,
10
11
kernel:: {
11
12
mutex, prelude:: * , traits, Cfg , LockMutexError , MarkConsistentMutexError , MutexProtocol ,
12
13
TryLockMutexError ,
13
14
} ,
15
+ sync:: source:: { DefaultSource , Source } ,
16
+ utils:: Init ,
14
17
} ;
15
18
16
19
/// The definer (static builder) for [`StaticMutex`][].
17
- pub struct Definer < System , T , InitTag > {
20
+ pub struct Definer < System , Source > {
18
21
mutex : mutex:: MutexDefiner < System > ,
19
- hunk : HunkDefiner < System , UnsafeCell < T > , InitTag > ,
22
+ source : Source ,
20
23
}
21
24
22
25
/// A mutual exclusion primitive useful for protecting shared data from
@@ -73,7 +76,7 @@ pub struct GenericMutex<Cell, Mutex> {
73
76
/// .priority(1)
74
77
/// .finish(cfg);
75
78
///
76
- /// let mutex = StaticMutex::define().finish(cfg);
79
+ /// let mutex = StaticMutex::define().init(|| 1). finish(cfg);
77
80
///
78
81
/// Objects { task2, mutex }
79
82
/// }
@@ -85,31 +88,31 @@ pub struct GenericMutex<Cell, Mutex> {
85
88
/// // access `*guard` until `task1` releases the lock
86
89
/// COTTAGE.task2.activate().unwrap();
87
90
///
88
- /// assert_eq!(*guard, 0 );
89
- /// *guard = 1 ;
91
+ /// assert_eq!(*guard, 1 );
92
+ /// *guard = 2 ;
90
93
/// }
91
94
///
92
95
/// fn task2_body() {
93
96
/// let mut guard = COTTAGE.mutex.lock().unwrap();
94
- /// assert_eq!(*guard, 1 );
95
- /// *guard = 2 ;
97
+ /// assert_eq!(*guard, 2 );
98
+ /// *guard = 3 ;
96
99
/// # exit(0);
97
100
/// }
98
101
/// ```
99
102
) ]
100
103
pub type StaticMutex < System , T > =
101
- GenericMutex < Hunk < System , UnsafeCell < T > > , mutex:: StaticMutex < System > > ;
104
+ GenericMutex < Hunk < System , UnsafeCell < MaybeUninit < T > > > , mutex:: StaticMutex < System > > ;
102
105
103
106
// TODO: Test the panicking behavior on invalid unlock order
104
107
// TODO: Test the abandonment behavior
105
108
// TODO: Owned version
106
109
107
110
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 > > >
109
112
{
110
113
}
111
114
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 > > >
113
116
{
114
117
}
115
118
@@ -129,11 +132,11 @@ pub struct GenericMutexGuard<'a, Cell, Mutex: mutex::MutexHandle> {
129
132
130
133
/// The specialization of [`GenericMutexGuard`] for [`StaticMutex`].
131
134
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 > > ;
133
136
134
137
unsafe impl < Cell , Mutex , T : Sync > Sync for GenericMutexGuard < ' _ , Cell , Mutex >
135
138
where
136
- Cell : Deref < Target = UnsafeCell < T > > ,
139
+ Cell : Deref < Target = UnsafeCell < MaybeUninit < T > > > ,
137
140
Mutex : mutex:: MutexHandle ,
138
141
{
139
142
}
@@ -233,17 +236,17 @@ where
233
236
{
234
237
/// Construct a `Definer` to define a mutex in [a configuration
235
238
/// function](crate#static-configuration).
236
- pub const fn define ( ) -> Definer < System , T , DefaultInitTag > {
239
+ pub const fn define ( ) -> Definer < System , DefaultSource < T > > {
237
240
Definer {
238
241
mutex : mutex:: StaticMutex :: define ( ) ,
239
- hunk : Hunk :: define ( ) ,
242
+ source : DefaultSource :: INIT , // [ref:default_source_is_default]
240
243
}
241
244
}
242
245
}
243
246
244
- impl < System , T : ' static , InitTag > Definer < System , T , InitTag >
247
+ impl < System , Source > Definer < System , Source >
245
248
where
246
- System : traits:: KernelMutex + traits :: KernelStatic ,
249
+ System : traits:: KernelMutex ,
247
250
{
248
251
/// Specify the mutex's protocol. Defaults to `None` when unspecified.
249
252
pub const fn protocol ( self , protocol : MutexProtocol ) -> Self {
@@ -254,7 +257,13 @@ where
254
257
}
255
258
}
256
259
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 >
258
267
where
259
268
System : traits:: KernelMutex + traits:: KernelStatic ,
260
269
{
@@ -263,17 +272,20 @@ where
263
272
pub const fn finish < C : ~const traits:: CfgMutex < System = System > + ~const traits:: CfgBase > (
264
273
self ,
265
274
cfg : & mut Cfg < C > ,
266
- ) -> StaticMutex < System , T > {
275
+ ) -> StaticMutex < System , Source :: Target >
276
+ where
277
+ Source : ~const self :: Source < System > ,
278
+ {
267
279
GenericMutex {
268
- cell : self . hunk . finish ( cfg) ,
280
+ cell : self . source . into_unsafe_cell_hunk ( cfg) ,
269
281
mutex : self . mutex . finish ( cfg) ,
270
282
}
271
283
}
272
284
}
273
285
274
286
impl < Cell , Mutex , T > GenericMutex < Cell , Mutex >
275
287
where
276
- Cell : Deref < Target = UnsafeCell < T > > ,
288
+ Cell : Deref < Target = UnsafeCell < MaybeUninit < T > > > ,
277
289
Mutex : mutex:: MutexHandle ,
278
290
{
279
291
/// Acquire the mutex, blocking the current thread until it is able to do
@@ -327,13 +339,13 @@ where
327
339
/// Get a raw pointer to the contained data.
328
340
#[ inline]
329
341
pub fn get_ptr ( & self ) -> * mut T {
330
- self . cell . get ( )
342
+ self . cell . get ( ) . cast ( )
331
343
}
332
344
}
333
345
334
346
impl < Cell , Mutex , T : fmt:: Debug > fmt:: Debug for GenericMutex < Cell , Mutex >
335
347
where
336
- Cell : Deref < Target = UnsafeCell < T > > ,
348
+ Cell : Deref < Target = UnsafeCell < MaybeUninit < T > > > ,
337
349
Mutex : mutex:: MutexHandle ,
338
350
{
339
351
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
@@ -396,7 +408,7 @@ where
396
408
397
409
impl < Cell , Mutex , T : fmt:: Debug > fmt:: Debug for GenericMutexGuard < ' _ , Cell , Mutex >
398
410
where
399
- Cell : Deref < Target = UnsafeCell < T > > ,
411
+ Cell : Deref < Target = UnsafeCell < MaybeUninit < T > > > ,
400
412
Mutex : mutex:: MutexHandle ,
401
413
{
402
414
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
@@ -406,7 +418,7 @@ where
406
418
407
419
impl < Cell , Mutex , T : fmt:: Display > fmt:: Display for GenericMutexGuard < ' _ , Cell , Mutex >
408
420
where
409
- Cell : Deref < Target = UnsafeCell < T > > ,
421
+ Cell : Deref < Target = UnsafeCell < MaybeUninit < T > > > ,
410
422
Mutex : mutex:: MutexHandle ,
411
423
{
412
424
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
@@ -428,37 +440,47 @@ where
428
440
429
441
impl < Cell , Mutex , T > Deref for GenericMutexGuard < ' _ , Cell , Mutex >
430
442
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 > > > ,
432
450
Mutex : mutex:: MutexHandle ,
433
451
{
434
452
type Target = T ;
435
453
#[ inline]
436
454
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 ( ) }
441
465
}
442
466
}
443
467
444
468
impl < Cell , Mutex , T > DerefMut for GenericMutexGuard < ' _ , Cell , Mutex >
445
469
where
446
- Cell : Deref < Target = UnsafeCell < T > > ,
470
+ Cell : Deref < Target = UnsafeCell < MaybeUninit < T > > > ,
447
471
Mutex : mutex:: MutexHandle ,
448
472
{
449
473
#[ inline]
450
474
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 ( ) }
455
477
}
456
478
}
457
479
458
480
// Safety: `MutexGuard::deref` provides a stable address
459
481
unsafe impl < Cell , Mutex , T > stable_deref_trait:: StableDeref for GenericMutexGuard < ' _ , Cell , Mutex >
460
482
where
461
- Cell : Deref < Target = UnsafeCell < T > > ,
483
+ Cell : Deref < Target = UnsafeCell < MaybeUninit < T > > > ,
462
484
Mutex : mutex:: MutexHandle ,
463
485
{
464
486
}
0 commit comments