]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/port/taslock.c
pc kernel: fix wrong simd exception mask (fixes go bootstrap)
[plan9front.git] / sys / src / 9 / port / taslock.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "../port/error.h"
7 #include "edf.h"
8
9 long maxlockcycles;
10 long maxilockcycles;
11 long cumlockcycles;
12 long cumilockcycles;
13 uintptr maxlockpc;
14 uintptr maxilockpc;
15
16 struct
17 {
18         ulong   locks;
19         ulong   glare;
20         ulong   inglare;
21 } lockstats;
22
23 static void
24 dumplockmem(char *tag, Lock *l)
25 {
26         uchar *cp;
27         int i;
28
29         iprint("%s: ", tag);
30         cp = (uchar*)l;
31         for(i = 0; i < 64; i++)
32                 iprint("%2.2ux ", cp[i]);
33         iprint("\n");
34 }
35
36 void
37 lockloop(Lock *l, uintptr pc)
38 {
39         Proc *p;
40
41         p = l->p;
42         print("lock %#p loop key %#lux pc %#p held by pc %#p proc %lud\n",
43                 l, l->key, pc, l->pc, p ? p->pid : 0);
44         dumpaproc(up);
45         if(p != nil)
46                 dumpaproc(p);
47 }
48
49 int
50 lock(Lock *l)
51 {
52         int i;
53         uintptr pc;
54
55         pc = getcallerpc(&l);
56
57         lockstats.locks++;
58         if(up)
59                 up->nlocks++;   /* prevent being scheded */
60         if(tas(&l->key) == 0){
61                 if(up)
62                         up->lastlock = l;
63                 l->pc = pc;
64                 l->p = up;
65                 l->m = MACHP(m->machno);
66                 l->isilock = 0;
67 #ifdef LOCKCYCLES
68                 l->lockcycles = -lcycles();
69 #endif
70                 return 0;
71         }
72         if(up)
73                 up->nlocks--;
74
75         lockstats.glare++;
76         for(;;){
77                 lockstats.inglare++;
78                 i = 0;
79                 while(l->key){
80                         if(conf.nmach < 2 && up && up->edf && (up->edf->flags & Admitted)){
81                                 /*
82                                  * Priority inversion, yield on a uniprocessor; on a
83                                  * multiprocessor, the other processor will unlock
84                                  */
85                                 print("inversion %#p pc %#p proc %lud held by pc %#p proc %lud\n",
86                                         l, pc, up ? up->pid : 0, l->pc, l->p ? l->p->pid : 0);
87                                 up->edf->d = todget(nil);       /* yield to process with lock */
88                         }
89                         if(i++ > 100000000){
90                                 i = 0;
91                                 lockloop(l, pc);
92                         }
93                 }
94                 if(up)
95                         up->nlocks++;
96                 if(tas(&l->key) == 0){
97                         if(up)
98                                 up->lastlock = l;
99                         l->pc = pc;
100                         l->p = up;
101                         l->m = MACHP(m->machno);
102                         l->isilock = 0;
103 #ifdef LOCKCYCLES
104                         l->lockcycles = -lcycles();
105 #endif
106                         return 1;
107                 }
108                 if(up)
109                         up->nlocks--;
110         }
111 }
112
113 void
114 ilock(Lock *l)
115 {
116         ulong x;
117         uintptr pc;
118
119         pc = getcallerpc(&l);
120         lockstats.locks++;
121
122         x = splhi();
123         if(tas(&l->key) != 0){
124                 lockstats.glare++;
125                 /*
126                  * Cannot also check l->pc, l->m, or l->isilock here
127                  * because they might just not be set yet, or
128                  * (for pc and m) the lock might have just been unlocked.
129                  */
130                 for(;;){
131                         lockstats.inglare++;
132                         splx(x);
133                         while(l->key)
134                                 ;
135                         x = splhi();
136                         if(tas(&l->key) == 0)
137                                 goto acquire;
138                 }
139         }
140 acquire:
141         m->ilockdepth++;
142         if(up)
143                 up->lastilock = l;
144         l->sr = x;
145         l->pc = pc;
146         l->p = up;
147         l->m = MACHP(m->machno);
148         l->isilock = 1;
149 #ifdef LOCKCYCLES
150         l->lockcycles = -lcycles();
151 #endif
152 }
153
154 int
155 canlock(Lock *l)
156 {
157         if(up)
158                 up->nlocks++;
159         if(tas(&l->key)){
160                 if(up)
161                         up->nlocks--;
162                 return 0;
163         }
164
165         if(up)
166                 up->lastlock = l;
167         l->pc = getcallerpc(&l);
168         l->p = up;
169         l->m = MACHP(m->machno);
170         l->isilock = 0;
171 #ifdef LOCKCYCLES
172         l->lockcycles = -lcycles();
173 #endif
174         return 1;
175 }
176
177 void
178 unlock(Lock *l)
179 {
180 #ifdef LOCKCYCLES
181         l->lockcycles += lcycles();
182         cumlockcycles += l->lockcycles;
183         if(l->lockcycles > maxlockcycles){
184                 maxlockcycles = l->lockcycles;
185                 maxlockpc = l->pc;
186         }
187 #endif
188         if(l->key == 0)
189                 print("unlock: not locked: pc %#p\n", getcallerpc(&l));
190         if(l->isilock)
191                 print("unlock of ilock: pc %#p, held by %#p\n", getcallerpc(&l), l->pc);
192         if(l->p != up)
193                 print("unlock: up changed: pc %#p, acquired at pc %#p, lock p %#p, unlock up %#p\n", getcallerpc(&l), l->pc, l->p, up);
194         l->m = nil;
195         coherence();
196         l->key = 0;
197
198         if(up && --up->nlocks == 0 && up->delaysched && islo()){
199                 /*
200                  * Call sched if the need arose while locks were held
201                  * But, don't do it from interrupt routines, hence the islo() test
202                  */
203                 sched();
204         }
205 }
206
207 uintptr ilockpcs[0x100] = { [0xff] = 1 };
208 static int n;
209
210 void
211 iunlock(Lock *l)
212 {
213         ulong sr;
214
215 #ifdef LOCKCYCLES
216         l->lockcycles += lcycles();
217         cumilockcycles += l->lockcycles;
218         if(l->lockcycles > maxilockcycles){
219                 maxilockcycles = l->lockcycles;
220                 maxilockpc = l->pc;
221         }
222         if(l->lockcycles > 2400)
223                 ilockpcs[n++ & 0xff]  = l->pc;
224 #endif
225         if(l->key == 0)
226                 print("iunlock: not locked: pc %#p\n", getcallerpc(&l));
227         if(!l->isilock)
228                 print("iunlock of lock: pc %#p, held by %#p\n", getcallerpc(&l), l->pc);
229         if(islo())
230                 print("iunlock while lo: pc %#p, held by %#p\n", getcallerpc(&l), l->pc);
231
232         sr = l->sr;
233         l->m = nil;
234         coherence();
235         l->key = 0;
236         m->ilockdepth--;
237         if(up)
238                 up->lastilock = nil;
239         splx(sr);
240 }