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