| /* | |
| This file defines a Promela model for xv6's | |
| acquire, release, sleep, and wakeup, along with | |
| a model of a simple producer/consumer queue. | |
| To run: | |
| spinp sleep1.p | |
| (You may need to install Spin, available at http://spinroot.com/.) | |
| After a successful run spin prints something like: | |
| unreached in proctype consumer | |
| (0 of 37 states) | |
| unreached in proctype producer | |
| (0 of 23 states) | |
| After an unsuccessful run, the spinp script prints | |
| an execution trace that causes a deadlock. | |
| The safe body of producer reads: | |
| acquire(lk); | |
| x = value; value = x + 1; x = 0; | |
| wakeup(0); | |
| release(lk); | |
| i = i + 1; | |
| If this is changed to: | |
| x = value; value = x + 1; x = 0; | |
| acquire(lk); | |
| wakeup(0); | |
| release(lk); | |
| i = i + 1; | |
| then a deadlock can happen, because the non-atomic | |
| increment of value conflicts with the non-atomic | |
| decrement in consumer, causing value to have a bad value. | |
| Try this. | |
| If it is changed to: | |
| acquire(lk); | |
| x = value; value = x + 1; x = 0; | |
| release(lk); | |
| wakeup(0); | |
| i = i + 1; | |
| then nothing bad happens: it is okay to wakeup after release | |
| instead of before, although it seems morally wrong. | |
| */ | |
| bit lk; | |
| byte value; | |
| bit sleeping[N]; | |
| inline acquire(x) | |
| { | |
| atomic { x == 0; x = 1 } | |
| } | |
| inline release(x) | |
| { | |
| assert x==1; | |
| x = 0 | |
| } | |
| inline sleep(cond, lk) | |
| { | |
| assert !sleeping[_pid]; | |
| if | |
| :: cond -> | |
| skip | |
| :: else -> | |
| atomic { release(lk); sleeping[_pid] = 1 }; | |
| sleeping[_pid] == 0; | |
| acquire(lk) | |
| fi | |
| } | |
| inline wakeup() | |
| { | |
| w = 0; | |
| do | |
| :: w < N -> | |
| sleeping[w] = 0; | |
| w = w + 1 | |
| :: else -> | |
| break | |
| od | |
| } | |
| active[N] proctype consumer() | |
| { | |
| byte i, x; | |
| i = 0; | |
| do | |
| :: i < ITER -> | |
| acquire(lk); | |
| sleep(value > 0, lk); | |
| x = value; value = x - 1; x = 0; | |
| release(lk); | |
| i = i + 1; | |
| :: else -> | |
| break | |
| od; | |
| i = 0; | |
| skip | |
| } | |
| active[N] proctype producer() | |
| { | |
| byte i, x, w; | |
| i = 0; | |
| do | |
| :: i < ITER -> | |
| acquire(lk); | |
| x = value; value = x + 1; x = 0; | |
| release(lk); | |
| wakeup(); | |
| i = i + 1; | |
| :: else -> | |
| break | |
| od; | |
| i = 0; | |
| skip | |
| } | |
Xet Storage Details
- Size:
- 1.99 kB
- Xet hash:
- 7f8aa23099357e7fd0e0c22a4e76b78aece297b9b1463cceb22c512a2099b580
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.