@@ -209,13 +209,22 @@ pub enum Procstate {
209
209
210
210
/// Represents lock guards that can be slept in a `WaitChannel`.
211
211
pub trait Waitable {
212
- /// Returns a reference to the inner `RawSpinlock`.
212
+ /// Releases the inner `RawSpinlock`.
213
213
///
214
214
/// # Safety
215
215
///
216
- /// You should manually prove the correctness when directly accessing
217
- /// the inner `RawSpinlock` instead of using the lock's API.
218
- unsafe fn get_raw ( & self ) -> & RawSpinlock ;
216
+ /// `raw_release()` and `raw_acquire` must always be used as a pair.
217
+ /// Use these only for temporarily releasing (and then acquiring) the lock.
218
+ /// Also, do not access `self` until re-acquiring the lock with `raw_acquire()`.
219
+ unsafe fn raw_release ( & self ) ;
220
+
221
+ /// Acquires the inner `RawSpinlock`.
222
+ ///
223
+ /// # Safety
224
+ ///
225
+ /// `raw_release()` and `raw_acquire` must always be used as a pair.
226
+ /// Use these only for temporarily releasing (and then acquiring) the lock.
227
+ unsafe fn raw_acquire ( & self ) ;
219
228
}
220
229
221
230
pub struct WaitChannel {
@@ -231,12 +240,11 @@ impl WaitChannel {
231
240
232
241
/// Atomically release lock and sleep on waitchannel.
233
242
/// Reacquires lock when awakened.
234
- ///
235
- /// # Safety
236
- ///
237
- /// Make sure `lk` is the only lock we currently hold.
238
- pub unsafe fn sleep < T : Waitable > ( & self , lk : & mut T ) {
239
- let p = & * myproc ( ) ;
243
+ pub fn sleep < T : Waitable > ( & self , lk : & mut T ) {
244
+ let p = unsafe {
245
+ // TODO: Remove this unsafe part after resolving #258
246
+ & * myproc ( )
247
+ } ;
240
248
241
249
// Must acquire p->lock in order to
242
250
// change p->state and then call sched.
@@ -247,19 +255,31 @@ impl WaitChannel {
247
255
248
256
//DOC: sleeplock1
249
257
let mut guard = p. lock ( ) ;
250
- lk. get_raw ( ) . release ( ) ;
258
+ unsafe {
259
+ // Temporarily release the inner `RawSpinlock`.
260
+ // This is safe, since we don't access `lk` until re-acquiring the lock
261
+ // at `lk.raw_acquire()`.
262
+ lk. raw_release ( ) ;
263
+ }
251
264
252
265
// Go to sleep.
253
266
guard. deref_mut_info ( ) . waitchannel = self ;
254
267
guard. deref_mut_info ( ) . state = Procstate :: SLEEPING ;
255
- guard. sched ( ) ;
268
+ unsafe {
269
+ // Safe since we hold `p.lock()`, changed the process's state,
270
+ // and device interrupts are disabled by `push_off()` in `p.lock()`.
271
+ guard. sched ( ) ;
272
+ }
256
273
257
274
// Tidy up.
258
275
guard. deref_mut_info ( ) . waitchannel = ptr:: null ( ) ;
259
276
260
277
// Reacquire original lock.
261
278
drop ( guard) ;
262
- lk. get_raw ( ) . acquire ( ) ;
279
+ unsafe {
280
+ // Safe since this is paired with a previous `lk.raw_release()`.
281
+ lk. raw_acquire ( ) ;
282
+ }
263
283
}
264
284
265
285
/// Wake up all processes sleeping on waitchannel.
0 commit comments