1 #include "include.h"
2
3 #undef LOCKCYCLES
4
5 #ifdef LOCKCYCLES
6 uvlong maxlockcycles;
7 uvlong maxilockcycles;
8 ulong maxlockpc;
9 ulong maxilockpc;
10 #endif
11
12 struct
13 {
14 ulong locks;
15 ulong glare;
16 ulong inglare;
17 } lockstats;
18
19 static void
inccnt(Ref * r)20 inccnt(Ref *r)
21 {
22 _xinc(&r->ref);
23 }
24
25 static int
deccnt(Ref * r)26 deccnt(Ref *r)
27 {
28 int x;
29
30 x = _xdec(&r->ref);
31 assert(x >= 0);
32 // if(x < 0)
33 // panic("deccnt pc=%#p", getcallerpc(&r));
34 return x;
35 }
36
37 static void
dumplockmem(char * tag,Lock * l)38 dumplockmem(char *tag, Lock *l)
39 {
40 uchar *cp;
41 int i;
42
43 iprint("%s: ", tag);
44 cp = (uchar*)l;
45 for(i = 0; i < 64; i++)
46 iprint("%2.2ux ", cp[i]);
47 iprint("\n");
48 }
49
50 void
lockloop(Lock * l,uintptr pc)51 lockloop(Lock *l, uintptr pc)
52 {
53 print("lock %#p loop key %#ux pc %#p\n", l, l->key, pc);
54 }
55
56 int
lock(Lock * l)57 lock(Lock *l)
58 {
59 int i;
60 uintptr pc;
61
62 pc = getcallerpc(&l);
63
64 lockstats.locks++;
65 if(TAS(&l->key) == 0){
66 l->pc = pc;
67 l->isilock = 0;
68 #ifdef LOCKCYCLES
69 cycles(&l->lockcycles);
70 #endif
71 return 0;
72 }
73
74 lockstats.glare++;
75 for(;;){
76 lockstats.inglare++;
77 i = 0;
78 while(l->key){
79 if(i++ > 100000000){
80 i = 0;
81 lockloop(l, pc);
82 }
83 }
84 if(TAS(&l->key) == 0){
85 l->pc = pc;
86 l->isilock = 0;
87 #ifdef LOCKCYCLES
88 cycles(&l->lockcycles);
89 #endif
90 return 1;
91 }
92 }
93 }
94
95 void
ilock(Lock * l)96 ilock(Lock *l)
97 {
98 ulong sr;
99 uintptr pc;
100
101 pc = getcallerpc(&l);
102 lockstats.locks++;
103
104 sr = splhi();
105 if(TAS(&l->key) != 0){
106 lockstats.glare++;
107 /*
108 * Cannot also check l->pc and l->m here because
109 * they might just not be set yet, or the lock might
110 * even have been let go.
111 */
112 if(!l->isilock){
113 dumplockmem("ilock:", l);
114 print("corrupt ilock %#p pc=%#p m=%#p isilock=%d",
115 l, l->pc, l->m, l->isilock);
116 assert(0);
117 }
118 if(l->m == MACHP(m->machno)) {
119 print("ilock: deadlock on cpu%d pc=%#p lockpc=%#p\n",
120 m->machno, pc, l->pc);
121 assert(0);
122 }
123 for(;;){
124 lockstats.inglare++;
125 splx(sr);
126 while(l->key)
127 ;
128 sr = splhi();
129 if(TAS(&l->key) == 0)
130 goto acquire;
131 }
132 }
133 acquire:
134 // m->ilockdepth++;
135 l->sr = sr;
136 l->pc = pc;
137 l->isilock = 1;
138 l->m = MACHP(m->machno);
139 #ifdef LOCKCYCLES
140 cycles(&l->lockcycles);
141 #endif
142 }
143
144 int
canlock(Lock * l)145 canlock(Lock *l)
146 {
147 if(TAS(&l->key))
148 return 0;
149
150 l->pc = getcallerpc(&l);
151 l->m = MACHP(m->machno);
152 l->isilock = 0;
153 #ifdef LOCKCYCLES
154 cycles(&l->lockcycles);
155 #endif
156 return 1;
157 }
158
159 void
unlock(Lock * l)160 unlock(Lock *l)
161 {
162 #ifdef LOCKCYCLES
163 uvlong x;
164 cycles(&x);
165 l->lockcycles = x - l->lockcycles;
166 if(l->lockcycles > maxlockcycles){
167 maxlockcycles = l->lockcycles;
168 maxlockpc = l->pc;
169 }
170 #endif
171
172 if(l->key == 0)
173 print("unlock: not locked: pc %#p\n", getcallerpc(&l));
174 if(l->isilock)
175 print("unlock of ilock: pc %#p, held by %#p\n",
176 getcallerpc(&l), l->pc);
177 l->m = nil;
178 l->key = 0;
179 coherence();
180 }
181
182 void
iunlock(Lock * l)183 iunlock(Lock *l)
184 {
185 ulong sr;
186
187 #ifdef LOCKCYCLES
188 uvlong x;
189 cycles(&x);
190 l->lockcycles = x - l->lockcycles;
191 if(l->lockcycles > maxilockcycles){
192 maxilockcycles = l->lockcycles;
193 maxilockpc = l->pc;
194 }
195 #endif
196
197 if(l->key == 0)
198 print("iunlock: not locked: pc %#p\n", getcallerpc(&l));
199 if(!l->isilock)
200 print("iunlock of lock: pc %#p, held by %#p\n", getcallerpc(&l), l->pc);
201 if(islo())
202 print("iunlock while lo: pc %#p, held by %#p\n", getcallerpc(&l), l->pc);
203
204 sr = l->sr;
205 l->m = nil;
206 l->key = 0;
207 coherence();
208 // m->ilockdepth--;
209 splx(sr);
210 }
211