1*3c2ddefeSDavid du Colombier/* 2*3c2ddefeSDavid du Colombierspin -a semaphore.p 3*3c2ddefeSDavid du Colombierpcc -DSAFETY -DREACH -DMEMLIM'='500 -o pan pan.c 4*3c2ddefeSDavid du Colombierpan -i 5*3c2ddefeSDavid du Colombierrm pan.* pan 6*3c2ddefeSDavid du Colombier 7*3c2ddefeSDavid du Colombier*/ 8*3c2ddefeSDavid du Colombier 9*3c2ddefeSDavid du Colombier#define N 3 10*3c2ddefeSDavid du Colombier 11*3c2ddefeSDavid du Colombierbit listlock; 12*3c2ddefeSDavid du Colombierbyte value; 13*3c2ddefeSDavid du Colombierbit onlist[N]; 14*3c2ddefeSDavid du Colombierbit waiting[N]; 15*3c2ddefeSDavid du Colombierbit sleeping[N]; 16*3c2ddefeSDavid du Colombierbit acquired[N]; 17*3c2ddefeSDavid du Colombier 18*3c2ddefeSDavid du Colombierinline lock(x) 19*3c2ddefeSDavid du Colombier{ 20*3c2ddefeSDavid du Colombier atomic { x == 0; x = 1 } 21*3c2ddefeSDavid du Colombier} 22*3c2ddefeSDavid du Colombier 23*3c2ddefeSDavid du Colombierinline unlock(x) 24*3c2ddefeSDavid du Colombier{ 25*3c2ddefeSDavid du Colombier assert x==1; 26*3c2ddefeSDavid du Colombier x = 0 27*3c2ddefeSDavid du Colombier} 28*3c2ddefeSDavid du Colombier 29*3c2ddefeSDavid du Colombierinline sleep(cond) 30*3c2ddefeSDavid du Colombier{ 31*3c2ddefeSDavid du Colombier assert !sleeping[_pid]; 32*3c2ddefeSDavid du Colombier assert !interrupted; 33*3c2ddefeSDavid du Colombier if 34*3c2ddefeSDavid du Colombier :: cond 35*3c2ddefeSDavid du Colombier :: atomic { else -> sleeping[_pid] = 1 } -> 36*3c2ddefeSDavid du Colombier !sleeping[_pid] 37*3c2ddefeSDavid du Colombier fi; 38*3c2ddefeSDavid du Colombier if 39*3c2ddefeSDavid du Colombier :: skip 40*3c2ddefeSDavid du Colombier :: interrupted = 1 41*3c2ddefeSDavid du Colombier fi 42*3c2ddefeSDavid du Colombier} 43*3c2ddefeSDavid du Colombier 44*3c2ddefeSDavid du Colombierinline wakeup(id) 45*3c2ddefeSDavid du Colombier{ 46*3c2ddefeSDavid du Colombier if 47*3c2ddefeSDavid du Colombier :: sleeping[id] == 1 -> sleeping[id] = 0 48*3c2ddefeSDavid du Colombier :: else 49*3c2ddefeSDavid du Colombier fi 50*3c2ddefeSDavid du Colombier} 51*3c2ddefeSDavid du Colombier 52*3c2ddefeSDavid du Colombierinline semqueue() 53*3c2ddefeSDavid du Colombier{ 54*3c2ddefeSDavid du Colombier lock(listlock); 55*3c2ddefeSDavid du Colombier assert !onlist[_pid]; 56*3c2ddefeSDavid du Colombier onlist[_pid] = 1; 57*3c2ddefeSDavid du Colombier unlock(listlock) 58*3c2ddefeSDavid du Colombier} 59*3c2ddefeSDavid du Colombier 60*3c2ddefeSDavid du Colombierinline semdequeue() 61*3c2ddefeSDavid du Colombier{ 62*3c2ddefeSDavid du Colombier lock(listlock); 63*3c2ddefeSDavid du Colombier assert onlist[_pid]; 64*3c2ddefeSDavid du Colombier onlist[_pid] = 0; 65*3c2ddefeSDavid du Colombier waiting[_pid] = 0; 66*3c2ddefeSDavid du Colombier unlock(listlock) 67*3c2ddefeSDavid du Colombier} 68*3c2ddefeSDavid du Colombier 69*3c2ddefeSDavid du Colombierinline semwakeup(n) 70*3c2ddefeSDavid du Colombier{ 71*3c2ddefeSDavid du Colombier byte i, j; 72*3c2ddefeSDavid du Colombier 73*3c2ddefeSDavid du Colombier lock(listlock); 74*3c2ddefeSDavid du Colombier i = 0; 75*3c2ddefeSDavid du Colombier j = n; 76*3c2ddefeSDavid du Colombier do 77*3c2ddefeSDavid du Colombier :: (i < N && j > 0) -> 78*3c2ddefeSDavid du Colombier if 79*3c2ddefeSDavid du Colombier :: onlist[i] && waiting[i] -> 80*3c2ddefeSDavid du Colombier atomic { printf("kicked %d\n", i); 81*3c2ddefeSDavid du Colombier waiting[i] = 0 }; 82*3c2ddefeSDavid du Colombier wakeup(i); 83*3c2ddefeSDavid du Colombier j-- 84*3c2ddefeSDavid du Colombier :: else 85*3c2ddefeSDavid du Colombier fi; 86*3c2ddefeSDavid du Colombier i++ 87*3c2ddefeSDavid du Colombier :: else -> break 88*3c2ddefeSDavid du Colombier od; 89*3c2ddefeSDavid du Colombier /* reset i and j to reduce state space */ 90*3c2ddefeSDavid du Colombier i = 0; 91*3c2ddefeSDavid du Colombier j = 0; 92*3c2ddefeSDavid du Colombier unlock(listlock) 93*3c2ddefeSDavid du Colombier} 94*3c2ddefeSDavid du Colombier 95*3c2ddefeSDavid du Colombierinline semrelease(n) 96*3c2ddefeSDavid du Colombier{ 97*3c2ddefeSDavid du Colombier atomic { value = value+n; printf("release %d\n", n); }; 98*3c2ddefeSDavid du Colombier semwakeup(n) 99*3c2ddefeSDavid du Colombier} 100*3c2ddefeSDavid du Colombier 101*3c2ddefeSDavid du Colombierinline canacquire() 102*3c2ddefeSDavid du Colombier{ 103*3c2ddefeSDavid du Colombier atomic { value > 0 -> value--; }; 104*3c2ddefeSDavid du Colombier acquired[_pid] = 1 105*3c2ddefeSDavid du Colombier} 106*3c2ddefeSDavid du Colombier 107*3c2ddefeSDavid du Colombier#define semawoke() !waiting[_pid] 108*3c2ddefeSDavid du Colombier 109*3c2ddefeSDavid du Colombierinline semacquire(block) 110*3c2ddefeSDavid du Colombier{ 111*3c2ddefeSDavid du Colombier if 112*3c2ddefeSDavid du Colombier :: atomic { canacquire() -> printf("easy acquire\n"); } -> 113*3c2ddefeSDavid du Colombier goto out 114*3c2ddefeSDavid du Colombier :: else 115*3c2ddefeSDavid du Colombier fi; 116*3c2ddefeSDavid du Colombier if 117*3c2ddefeSDavid du Colombier :: !block -> goto out 118*3c2ddefeSDavid du Colombier :: else 119*3c2ddefeSDavid du Colombier fi; 120*3c2ddefeSDavid du Colombier 121*3c2ddefeSDavid du Colombier semqueue(); 122*3c2ddefeSDavid du Colombier do 123*3c2ddefeSDavid du Colombier :: skip -> 124*3c2ddefeSDavid du Colombier waiting[_pid] = 1; 125*3c2ddefeSDavid du Colombier if 126*3c2ddefeSDavid du Colombier :: atomic { canacquire() -> printf("hard acquire\n"); } -> 127*3c2ddefeSDavid du Colombier break 128*3c2ddefeSDavid du Colombier :: else 129*3c2ddefeSDavid du Colombier fi; 130*3c2ddefeSDavid du Colombier sleep(semawoke()) 131*3c2ddefeSDavid du Colombier if 132*3c2ddefeSDavid du Colombier :: interrupted -> 133*3c2ddefeSDavid du Colombier printf("%d interrupted\n", _pid); 134*3c2ddefeSDavid du Colombier break 135*3c2ddefeSDavid du Colombier :: !interrupted 136*3c2ddefeSDavid du Colombier fi 137*3c2ddefeSDavid du Colombier od; 138*3c2ddefeSDavid du Colombier semdequeue(); 139*3c2ddefeSDavid du Colombier if 140*3c2ddefeSDavid du Colombier :: !waiting[_pid] -> 141*3c2ddefeSDavid du Colombier semwakeup(1) 142*3c2ddefeSDavid du Colombier :: else 143*3c2ddefeSDavid du Colombier fi; 144*3c2ddefeSDavid du Colombierout: 145*3c2ddefeSDavid du Colombier assert (!block || interrupted || acquired[_pid]); 146*3c2ddefeSDavid du Colombier assert !(interrupted && acquired[_pid]); 147*3c2ddefeSDavid du Colombier assert !waiting[_pid]; 148*3c2ddefeSDavid du Colombier printf("%d done\n", _pid); 149*3c2ddefeSDavid du Colombier} 150*3c2ddefeSDavid du Colombier 151*3c2ddefeSDavid du Colombieractive[N] proctype acquire() 152*3c2ddefeSDavid du Colombier{ 153*3c2ddefeSDavid du Colombier bit interrupted; 154*3c2ddefeSDavid du Colombier 155*3c2ddefeSDavid du Colombier semacquire(1); 156*3c2ddefeSDavid du Colombier printf("%d finished\n", _pid); 157*3c2ddefeSDavid du Colombier skip 158*3c2ddefeSDavid du Colombier} 159*3c2ddefeSDavid du Colombier 160*3c2ddefeSDavid du Colombieractive proctype release() 161*3c2ddefeSDavid du Colombier{ 162*3c2ddefeSDavid du Colombier byte k; 163*3c2ddefeSDavid du Colombier 164*3c2ddefeSDavid du Colombier k = 0; 165*3c2ddefeSDavid du Colombier do 166*3c2ddefeSDavid du Colombier :: k < N -> 167*3c2ddefeSDavid du Colombier semrelease(1); 168*3c2ddefeSDavid du Colombier k++; 169*3c2ddefeSDavid du Colombier :: else -> break 170*3c2ddefeSDavid du Colombier od; 171*3c2ddefeSDavid du Colombier skip 172*3c2ddefeSDavid du Colombier} 173*3c2ddefeSDavid du Colombier 174*3c2ddefeSDavid du Colombier/* 175*3c2ddefeSDavid du Colombier * If this guy, the highest-numbered proc, sticks 176*3c2ddefeSDavid du Colombier * around, then everyone else sticks around. 177*3c2ddefeSDavid du Colombier * This makes sure that we get a state line for 178*3c2ddefeSDavid du Colombier * everyone in a proc dump. 179*3c2ddefeSDavid du Colombier */ 180*3c2ddefeSDavid du Colombieractive proctype dummy() 181*3c2ddefeSDavid du Colombier{ 182*3c2ddefeSDavid du Colombierend: 0; 183*3c2ddefeSDavid du Colombier} 184