Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Lock checking framework and cleanup of linux module code to use palacios interfaces...
[palacios.git] / linux_module / lockcheck.c
1 #include <linux/kernel.h>
2 #include <linux/kthread.h>
3 #include <linux/spinlock.h>
4
5 #include "palacios.h"
6
7 #include "lockcheck.h"
8
9 // How far up the stack to track the caller
10 // 0 => palacios_...
11 // 1 => v3_lock...
12 // 2 => caller of v3_lock..
13 // ... 
14 #define STEP_BACK_DEPTH_FIRST 1
15 #define STEP_BACK_DEPTH_LAST  4
16 #define STEP_BACK_DEPTH       (STEP_BACK_DEPTH_LAST-STEP_BACK_DEPTH_FIRST+1)
17
18 // show when multiple locks are held simultaneously
19 // This is the minimum number
20 #define WARN_MULTIPLE_THRESHOLD 3
21
22 typedef struct {
23   int  inuse;         // nonzero if this is in use
24   void *lock;         // the lock
25   void *allocator[STEP_BACK_DEPTH];
26                       // who allocated this
27   int   lockcount;    // how many times it's been locked/unlocked (lock=+1, unlock=-1)
28   int   irqcount;     // how many times interrupts have been turned off (+1/-1)
29   void *lastlocker[STEP_BACK_DEPTH];
30                       // who last locked
31   void *lastunlocker[STEP_BACK_DEPTH]; 
32                       // who last unlocked
33   void *lastirqlocker[STEP_BACK_DEPTH];
34                       // who last locked
35   unsigned long lastlockflags; // their flags
36   void *lastirqunlocker[STEP_BACK_DEPTH]
37                     ; // who last unlocked
38   unsigned long lastunlockflags; // their flags
39 } lockcheck_state_t;
40
41
42 static spinlock_t lock;
43
44 static lockcheck_state_t state[NUM_LOCKS];
45
46 static lockcheck_state_t *get_lock_entry(void)
47 {
48   int i;
49   unsigned long f;
50   lockcheck_state_t *l;
51
52   spin_lock_irqsave(&lock,f);
53
54   for (i=0;i<NUM_LOCKS;i++) { 
55     l=&(state[i]);
56     if (!(l->inuse)) { 
57       l->inuse=1;
58       break;
59     }
60   }
61
62   spin_unlock_irqrestore(&lock,f);
63   
64   if (i<NUM_LOCKS) { 
65     return l;
66   } else {
67     return 0;
68   }
69 }
70
71
72 static lockcheck_state_t *find_lock_entry(void *lock)
73 {
74   int i;
75   lockcheck_state_t *l;
76
77   for (i=0;i<NUM_LOCKS;i++) { 
78     l=&(state[i]);
79     if (l->inuse && l->lock == lock) { 
80       return l;
81     }
82   }
83   return 0;
84 }
85
86
87 static void free_lock_entry(lockcheck_state_t *l)
88 {
89   l->inuse=0;
90 }
91
92
93
94 void palacios_lockcheck_init()
95 {
96   memset(state,0,sizeof(lockcheck_state_t)*NUM_LOCKS);
97   spin_lock_init(&lock);
98   DEBUG("LOCKCHECK: LOCK CHECKING INITED\n");
99 }
100
101 //
102 // This needs to be defined explictly since the intrinsic does not take a var
103 //
104 #define backtrace(t) \
105   t[0]=__builtin_return_address(STEP_BACK_DEPTH_FIRST); \
106   t[1]=__builtin_return_address(STEP_BACK_DEPTH_FIRST+1); \
107   t[2]=__builtin_return_address(STEP_BACK_DEPTH_FIRST+2); \
108   t[3]=__builtin_return_address(STEP_BACK_DEPTH_FIRST+3); 
109
110 //
111 // For printing a backtrace
112 //
113 //
114 #define backtrace_format "%pS << %pS << %pS << %pS"
115 #define backtrace_expand(t) ((t)[0]),((t)[1]),((t)[2]),((t)[3])
116
117
118 static void clear_trace(void **trace)
119 {
120   int i;
121
122   for (i=0;i<STEP_BACK_DEPTH;i++) { 
123     trace[i]=0;
124   }
125 }
126
127
128 static void printlock(char *prefix, lockcheck_state_t *l)
129 {
130   if (l->lock) { 
131     DEBUG("LOCKCHECK: %s: lock 0x%p, allocator=" 
132           backtrace_format
133           ", lockcount=%d, lastlocker="
134           backtrace_format
135           ", lastunlocker="
136           backtrace_format
137           ", irqcount=%d, lastirqlocker="
138           backtrace_format
139           ", lastlockflags=%lu, lastirqunlocker="
140           backtrace_format
141           ", lastunlockflags=%lu\n",
142           prefix,l->lock,
143           backtrace_expand(l->allocator),
144           l->lockcount,
145           backtrace_expand(l->lastlocker),
146           backtrace_expand(l->lastunlocker),
147           l->irqcount,
148           backtrace_expand(l->lastirqlocker),
149           l->lastlockflags,
150           backtrace_expand(l->lastirqunlocker),
151           l->lastunlockflags);
152   }
153 }
154
155
156
157 static void find_multiple_locks_held(void)
158 {
159   int i;
160   int have=0;
161   lockcheck_state_t *l;
162   char buf[64];
163
164   for (i=0;i<NUM_LOCKS;i++) { 
165     l=&(state[i]);
166     if (l->inuse && l->lockcount>0) { 
167       have++;
168       if (have>=WARN_MULTIPLE_THRESHOLD) { 
169         break;
170       }
171     }
172   }
173   
174   if (have>=WARN_MULTIPLE_THRESHOLD) { 
175     have=0;
176     for (i=0;i<NUM_LOCKS;i++) { 
177       l=&(state[i]);
178       if (l->inuse && l->lockcount>0) {
179         snprintf(buf,64,"MULTIPLE LOCKS HELD (%d)",have);
180         printlock(buf,l);
181         have++;
182       }
183     }
184   }
185     
186 }
187
188 static void find_multiple_irqs_held(void)
189 {
190   int i;
191   int have=0;
192   lockcheck_state_t *l;
193   char buf[64];
194
195   for (i=0;i<NUM_LOCKS;i++) { 
196     l=&(state[i]);
197     if (l->inuse && l->irqcount>0) {
198       have++;
199       if (have>=WARN_MULTIPLE_THRESHOLD) { 
200         break;
201       }
202     }
203   }
204   
205   if (have>=WARN_MULTIPLE_THRESHOLD) { 
206     have=0;
207     for (i=0;i<NUM_LOCKS;i++) { 
208       l=&(state[i]);
209       if (l->inuse && l->irqcount>0) { 
210         snprintf(buf,64,"MULTIPLE IRQS HELD (%d)",have);
211         printlock(buf,l);
212         have++;
213       }
214     }
215   }
216
217 }
218
219
220 void palacios_lockcheck_deinit()
221 {
222   int i;
223   lockcheck_state_t *l;
224   
225   for (i=0;i<NUM_LOCKS;i++) { 
226     l=&(state[i]);
227     if (l->lock) { 
228       printlock("ALLOCATED LOCK AT DEINIT",l);
229       if ((l->lockcount)) { 
230         printlock("BAD LOCK COUNT AT DEINIT",l);
231       }
232       if ((l->irqcount)) { 
233         printlock("BAD IRQ COUNT AT DEINIT",l);
234       }
235     }
236   } 
237   INFO("LOCKCHECK: DEINITED\n");
238 }
239
240
241 void palacios_lockcheck_alloc(void *lock)
242 {
243   lockcheck_state_t *l=get_lock_entry();
244
245   if (!l) { 
246     DEBUG("LOCKCHECK: UNABLE TO ALLOCATE TRACKING DATA FOR LOCK 0x%p\n",lock);
247   }
248   l->lock=lock;
249   backtrace(l->allocator);
250   l->lockcount=l->irqcount=0;
251   clear_trace(l->lastlocker);
252   clear_trace(l->lastunlocker);
253   clear_trace(l->lastirqlocker);
254   clear_trace(l->lastirqunlocker);
255   //INFO("LOCKCHECK: LOCK ALLOCATE 0x%p\n",lock);
256   printlock("NEW LOCK", l);
257  //dump_stack();
258 }
259   
260 void palacios_lockcheck_free(void *lock)
261 {
262   lockcheck_state_t *l=find_lock_entry(lock);
263   
264   if (!l){
265     DEBUG("LOCKCHECK: FREEING UNTRACKED LOCK 0x%p\n",lock);
266     return;
267   }
268
269   if ((l->lockcount)) { 
270     printlock("BAD LOCK COUNT AT FREE",l);
271   }
272
273   if ((l->irqcount)) { 
274     printlock("BAD IRQ COUNT AT FREE",l);
275   }
276   free_lock_entry(l);
277 }
278
279 void palacios_lockcheck_lock(void *lock)
280 {
281   lockcheck_state_t *l=find_lock_entry(lock);
282   
283   if (!l) { 
284     DEBUG("LOCKCHECK: LOCKING UNTRACKED LOCK 0x%p\n",lock);
285     return;
286   }
287   
288   if (l->lockcount!=0) { 
289     printlock("BAD LOCKCOUNT AT LOCK",l);
290   }
291   if (l->irqcount!=0) { 
292     printlock("BAD IRQCOUNT AT LOCK",l);
293   }
294   
295   l->lockcount++;
296   backtrace(l->lastlocker);
297
298   find_multiple_locks_held();
299
300 }
301 void palacios_lockcheck_unlock(void *lock)
302 {
303   lockcheck_state_t *l=find_lock_entry(lock);
304   
305   if (!l) { 
306     DEBUG("LOCKCHECK: UNLOCKING UNTRACKED LOCK 0x%p\n",lock);
307     return;
308   }
309   
310   if (l->lockcount!=1) { 
311     printlock("LOCKCHECK: BAD LOCKCOUNT AT UNLOCK",l);
312   }
313   if (l->irqcount!=0) { 
314     printlock("LOCKCHECK: BAD IRQCOUNT AT UNLOCK",l);
315   }
316   
317   l->lockcount--;
318   backtrace(l->lastunlocker);
319 }
320
321 void palacios_lockcheck_lock_irqsave(void *lock,unsigned long flags)
322 {
323   lockcheck_state_t *l=find_lock_entry(lock);
324   
325   if (!l) { 
326     DEBUG("LOCKCHECK: IRQ LOCKING UNTRACKED LOCK 0x%p\n",lock);
327     return;
328   }
329   
330   if (l->lockcount!=0) { 
331     printlock("BAD LOCKCOUNT AT IRQ LOCK",l);
332   }
333   if (l->irqcount!=0) { 
334     printlock("BAD IRQCOUNT AT IRQ LOCK",l);
335   }
336   
337   l->irqcount++;
338   l->lastlockflags=flags;
339   backtrace(l->lastirqlocker);
340
341
342   find_multiple_irqs_held();
343
344 }
345
346 void palacios_lockcheck_unlock_irqrestore(void *lock,unsigned long flags)
347 {
348   lockcheck_state_t *l=find_lock_entry(lock);
349   
350   if (!l) { 
351     DEBUG("LOCKCHECK: IRQ UNLOCKING UNTRACKED LOCK 0x%p\n",lock);
352     return;
353   }
354   
355   if (l->lockcount!=0) { 
356     printlock("LOCKCHECK: BAD LOCKCOUNT AT IRQ UNLOCK",l);
357   }
358   if (l->irqcount!=1) { 
359     printlock("LOCKCHECK: BAD IRQCOUNT AT IRQ UNLOCK",l);
360   }
361   
362   l->irqcount--;
363   l->lastunlockflags = flags;
364   backtrace(l->lastirqunlocker);
365   
366 }