1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
|
// http://spinroot.com/spin/Doc/Exercises.html
// Sleep/Wakeup scheduling in the UTS kernel, Ruane 1990
mtype = { Wakeme, Running }
bit lk, sleep_q
bit r_lock, r_want
mtype State = Running
active proctype client()
{
sleep: // sleep routine
atomic { (lk == 0) -> lk = 1 } // spinlock(&lk)
do // while r->lock
:: (r_lock == 1) -> // r->lock == 1
r_want = 1
State = Wakeme
lk = 0 // freelock(&lk)
(State == Running) // wait for wakeup
:: else -> // r->lock == 0
break
od;
progress:
assert(r_lock == 0) // should still be true
r_lock = 1 // consumed resource
lk = 0 // freelock(&lk)
goto sleep
}
active proctype server() // interrupt routine
{
wakeup: // wakeup routine
r_lock = 0 // r->lock = 0
(lk == 0) // waitlock(&lk)
if
:: r_want -> // someone is sleeping
atomic { // spinlock on sleep queue
(sleep_q == 0) -> sleep_q = 1
}
r_want = 0
#ifdef PROPOSED_FIX
(lk == 0) // waitlock(&lk)
#endif
if
:: (State == Wakeme) ->
State = Running
:: else ->
fi;
sleep_q = 0
:: else ->
fi
goto wakeup
}
|