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