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 and memory checking enhancements
[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
10 // Number of outputs possible before output stops
11 // set to zero to remove the limit
12 #define OUTPUT_LIMIT      0
13 //
14 // Number of outputs to skip before
15 // printing and counting
16 #define OUTPUT_SKIP       0
17
18 //
19 // Whether or not to print these events
20 //
21 #define PRINT_LOCK_ALLOC  0
22 #define PRINT_LOCK_FREE   0
23 #define PRINT_LOCK_LOCK   0
24 #define PRINT_LOCK_UNLOCK 0
25
26 // How far up the stack to track the caller
27 // 0 => palacios_...
28 // 1 => v3_lock...
29 // 2 => caller of v3_lock..
30 // ... 
31 #define STEP_BACK_DEPTH_FIRST 1
32 #define STEP_BACK_DEPTH_LAST  4
33 #define STEP_BACK_DEPTH       (STEP_BACK_DEPTH_LAST-STEP_BACK_DEPTH_FIRST+1)
34
35 // show when multiple locks are held simultaneously
36 // This is the minimum number
37 #define WARN_MULTIPLE_THRESHOLD 3
38
39 // Detect when last lock a processor holds is released
40 // but interrupts remain off, similarly for first acquire
41 #define CHECK_IRQ_LAST_RELEASE   0
42 #define CHECK_IRQ_FIRST_ACQUIRE  1
43
44 //
45 // Whether lockcheck should lock its own data structures during an
46 // event (alloc, dealloc, lock, unlock, etc) and the subsequent
47 // checking.  If this is off, it will only lock on a lock allocation,
48 // in order to assure each lock has a distinct slot.  If this is off,
49 // lockcheck may miss problems (or see additional problems) due to
50 // internal race conditions.  However, if it is on, lockcheck is
51 // essentially adding a global lock acuire to each lock operation in
52 // palacios, which will perturb palacios.
53 //
54 #define LOCK_SELF 1
55
56
57 typedef struct {
58   int  inuse;         // nonzero if this is in use
59   void *lock;         // the lock
60   void *holder;       // current thread holding it
61   u32   holdingcpu;   // on which cpu it acquired it
62   void *allocator[STEP_BACK_DEPTH];
63                       // who allocated this
64   int   lockcount;    // how many times it's been locked/unlocked (lock=+1, unlock=-1)
65   int   irqcount;     // how many times interrupts have been turned off (+1/-1)
66   void *lastlocker[STEP_BACK_DEPTH];
67                       // who last locked
68   void *lastunlocker[STEP_BACK_DEPTH]; 
69                       // who last unlocked
70   void *lastirqlocker[STEP_BACK_DEPTH];
71                       // who last locked
72   unsigned long lastlockflags; // their flags
73   void *lastirqunlocker[STEP_BACK_DEPTH]
74                     ; // who last unlocked
75   unsigned long lastunlockflags; // their flags
76 } lockcheck_state_t;
77
78
79 // This lock is currently used only to control
80 // allocation of entries in the global state
81 static spinlock_t mylock; 
82 static lockcheck_state_t state[NUM_LOCKS];
83
84 static int numout=0;
85
86 #define DEBUG_OUTPUT(fmt, args...)                                      \
87 do {                                                                    \
88   numout++;                                                             \
89   if (numout>=OUTPUT_SKIP) {                                            \
90     if (OUTPUT_LIMIT==0 ||(numout-OUTPUT_SKIP)<OUTPUT_LIMIT) {          \
91       DEBUG(fmt, ##args);                                               \
92     } else {                                                            \
93       if ((numout-OUTPUT_SKIP)==OUTPUT_LIMIT) {                         \
94         DEBUG("LOCKCHECK: Output limit hit - no further printouts\n");  \
95       }                                                                 \
96     }                                                                   \
97   }                                                                     \
98 } while (0)
99
100 #define DEBUG_DUMPSTACK()                                               \
101 do {                                                                    \
102   if (numout>=OUTPUT_SKIP) {                                            \
103     if (OUTPUT_LIMIT==0 || (numout-OUTPUT_SKIP)<OUTPUT_LIMIT) {         \
104       dump_stack();                                                     \
105     }                                                                   \
106   }                                                                     \
107 } while (0)
108
109 #if LOCK_SELF
110 #define LOCK_DECL unsigned long f
111 #define LOCK() spin_lock_irqsave(&mylock,f)
112 #define UNLOCK() spin_unlock_irqrestore(&mylock,f)
113 #define LOCK_ALLOC_DECL 
114 #define LOCK_ALLOC()  
115 #define UNLOCK_ALLOC() 
116 #else
117 #define LOCK_DECL 
118 #define LOCK()  
119 #define UNLOCK() 
120 #define LOCK_ALLOC_DECL unsigned long f
121 #define LOCK_ALLOC() spin_lock_irqsave(&mylock,f)
122 #define UNLOCK_ALLOC() spin_unlock_irqrestore(&mylock,f)
123 #endif
124
125 static void printlock(char *prefix, lockcheck_state_t *l);
126
127
128 typedef struct {
129   u32 top;               // next open slot 0..
130   void *lock[LOCK_STACK_DEPTH]; // the stack
131   char irq[LOCK_STACK_DEPTH];   // locked with irqsave?
132   char irqoff[LOCK_STACK_DEPTH]; // if so, what was the flag?
133 } lock_stack_t;
134
135 static DEFINE_PER_CPU(lock_stack_t, lock_stack);
136
137 static lockcheck_state_t *get_lock_entry(void)
138 {
139   int i;
140   lockcheck_state_t *l;
141   LOCK_ALLOC_DECL;
142
143   LOCK_ALLOC();
144   for (i=0;i<NUM_LOCKS;i++) { 
145     l=&(state[i]);
146     if (!(l->inuse)) { 
147       l->inuse=1;
148       break;
149     }
150   }
151   UNLOCK_ALLOC();
152   
153   if (i<NUM_LOCKS) { 
154     return l;
155   } else {
156     return 0;
157   }
158 }
159
160
161 static lockcheck_state_t *find_lock_entry(void *lock)
162 {
163   int i;
164   lockcheck_state_t *l;
165
166   for (i=0;i<NUM_LOCKS;i++) { 
167     l=&(state[i]);
168     if (l->inuse && l->lock == lock) { 
169       return l;
170     }
171   }
172   return 0;
173 }
174
175
176 static void free_lock_entry(lockcheck_state_t *l)
177 {
178   l->inuse=0;
179 }
180
181
182 static void lock_stack_print(void)
183 {
184   u32 i;
185   char buf[64];
186   lock_stack_t *mystack = &(get_cpu_var(lock_stack));
187   u32 cpu = get_cpu();  put_cpu();
188   
189   if ((mystack->top)>0) { 
190     for (i=mystack->top; i>0;i--) {
191       snprintf(buf,64,"LOCK STACK (cpu=%u, index=%u, irq=%d, irqoff=%d)",cpu, i-1, (int)(mystack->irq[i-1]), (int)(mystack->irqoff[i-1]));
192       printlock(buf,find_lock_entry(mystack->lock[i-1]));
193     }
194   }
195   put_cpu_var(lock_stack);
196 }
197
198
199 static void lock_stack_lock(void *lock, char irq, unsigned long flags)
200 {
201   lock_stack_t *mystack = &(get_cpu_var(lock_stack));
202   u32 cpu = get_cpu();  put_cpu();
203
204   if (mystack->top>=(LOCK_STACK_DEPTH-1)) {
205     put_cpu_var(lock_stack);
206     DEBUG_OUTPUT("LOCKCHECK: Locking lock 0x%p on cpu %u exceeds stack limit of %d\n",lock,cpu,LOCK_STACK_DEPTH);
207     lock_stack_print();
208   } else {
209     int oldtop = mystack->top;
210     mystack->lock[mystack->top] = lock;
211     mystack->irq[mystack->top] = irq;
212     mystack->irqoff[mystack->top] = irqs_disabled_flags(flags);
213     mystack->top++;
214     put_cpu_var(lock_stack);
215     if (CHECK_IRQ_FIRST_ACQUIRE && oldtop==0 && irqs_disabled_flags(flags) ) { 
216        DEBUG_OUTPUT("LOCKCHECK: First lock on lock stack of processor %d but irqs were already disabled - stack trace follows\n", cpu);
217        DEBUG_DUMPSTACK();
218     }
219        
220   }
221   
222   
223 }
224
225 static void lock_stack_unlock(void *lock, char irq, unsigned long flags)
226 {
227   lock_stack_t *mystack = &(get_cpu_var(lock_stack));
228   u32 cpu = get_cpu(); put_cpu();
229
230   if (mystack->top==0) {
231     put_cpu_var(lock_stack);
232     DEBUG_OUTPUT("LOCKCHECK: Unlocking lock 0x%p on cpu %u when lock stack is empty\n",lock,cpu);
233   } else {
234     if (mystack->lock[mystack->top-1] != lock) { 
235       void *otherlock=mystack->lock[mystack->top-1];
236       put_cpu_var(lock_stack);
237       DEBUG_OUTPUT("LOCKCHECK: Unlocking lock 0x%p on cpu %u when top of stack is lock 0x%p\n",lock,cpu, otherlock);
238       lock_stack_print();
239     } else {
240       if (irq!=mystack->irq[mystack->top-1]) {
241         char otherirq = mystack->irq[mystack->top-1];
242         put_cpu_var(lock_stack);
243         DEBUG_OUTPUT("LOCKCHECK: Unlocking lock 0x%p on cpu %u with irq=%d, but was locked with irq=%d\n",lock,cpu,irq,otherirq);
244         lock_stack_print();
245         mystack = &(get_cpu_var(lock_stack));
246         mystack->top--;
247         put_cpu_var(lock_stack);
248       } else {
249         if (irq) { 
250           if (irqs_disabled_flags(flags)!=mystack->irqoff[mystack->top-1]) {
251              char otherirqoff = mystack->irqoff[mystack->top-1];
252              put_cpu_var(lock_stack);
253              DEBUG_OUTPUT("LOCKCHECK: Unlocking lock 0x%p on cpu %u sets irqoff=%d but the matching lock returned irqoff=%d\n", lock, cpu, irqs_disabled_flags(flags), otherirqoff);
254              lock_stack_print();
255              mystack = &(get_cpu_var(lock_stack));
256              mystack->top--;
257              put_cpu_var(lock_stack);
258           } else {
259             // irq, and irq states match - good
260             mystack->top--;
261             put_cpu_var(lock_stack);
262           }
263         } else {
264           // !irq - we are good
265           mystack->top--;
266           put_cpu_var(lock_stack);
267         }
268       }
269     }
270   }
271
272   mystack = &(get_cpu_var(lock_stack));
273   if (mystack->top == 0) {
274     put_cpu_var(lock_stack);
275     if (CHECK_IRQ_LAST_RELEASE && irqs_disabled()) { 
276        DEBUG_OUTPUT("LOCKCHECK: Lock stack on cpu %u is now empty, but irqs are still disabled! Stack trace follows\n", cpu);
277        DEBUG_DUMPSTACK();
278     }
279   } else {
280     put_cpu_var(lock_stack);
281   }
282
283 }
284
285 void palacios_lockcheck_init()
286 {
287   memset(state,0,sizeof(lockcheck_state_t)*NUM_LOCKS);
288   spin_lock_init(&mylock);
289   DEBUG_OUTPUT("LOCKCHECK: LOCK CHECKING INITED (internal locking: %d, output limit: %d, output skip: %d)\n",LOCK_SELF,OUTPUT_LIMIT,OUTPUT_SKIP);
290 }
291
292 //
293 // This needs to be defined explictly since the intrinsic does not take a var
294 //
295 #define backtrace(t) \
296   t[0]=__builtin_return_address(STEP_BACK_DEPTH_FIRST); \
297   t[1]=__builtin_return_address(STEP_BACK_DEPTH_FIRST+1); \
298   t[2]=__builtin_return_address(STEP_BACK_DEPTH_FIRST+2); \
299   t[3]=__builtin_return_address(STEP_BACK_DEPTH_FIRST+3); 
300
301 //
302 // For printing a backtrace
303 //
304 //
305 #define backtrace_format "%pS << %pS << %pS << %pS"
306 #define backtrace_expand(t) ((t)[0]),((t)[1]),((t)[2]),((t)[3])
307
308
309 static void clear_trace(void **trace)
310 {
311   int i;
312
313   for (i=0;i<STEP_BACK_DEPTH;i++) { 
314     trace[i]=0;
315   }
316 }
317
318
319 static void printlock(char *prefix, lockcheck_state_t *l)
320 {
321   if (!l || !(l->lock) ) { 
322     DEBUG_OUTPUT("LOCKCHECK: %s: lock 0x%p BOGUS\n",prefix,l);
323     return;
324   }
325   if (l->lock) { 
326     DEBUG_OUTPUT("LOCKCHECK: %s: lock 0x%p, holder %s on %u, allocator=" 
327           backtrace_format
328           ", lockcount=%d, lastlocker="
329           backtrace_format
330           ", lastunlocker="
331           backtrace_format
332           ", irqcount=%d, lastirqlocker="
333           backtrace_format
334           ", lastlockflags=%lu, lastirqunlocker="
335           backtrace_format
336           ", lastunlockflags=%lu\n",
337           prefix,l->lock,
338           l->holder ? ((struct task_struct *)(l->holder))->comm : "none",
339           l->holdingcpu,
340           backtrace_expand(l->allocator),
341           l->lockcount,
342           backtrace_expand(l->lastlocker),
343           backtrace_expand(l->lastunlocker),
344           l->irqcount,
345           backtrace_expand(l->lastirqlocker),
346           l->lastlockflags,
347           backtrace_expand(l->lastirqunlocker),
348           l->lastunlockflags);
349   }
350 }
351
352
353
354 static void find_multiple_locks_held(void)
355 {
356   int i;
357   int have=0;
358   lockcheck_state_t *l;
359   char buf[64];
360
361   for (i=0;i<NUM_LOCKS;i++) { 
362     l=&(state[i]);
363     if (l->inuse && l->lockcount>0) { 
364       have++;
365       if (have>=WARN_MULTIPLE_THRESHOLD) { 
366         break;
367       }
368     }
369   }
370   
371   if (have>=WARN_MULTIPLE_THRESHOLD) { 
372     have=0;
373     for (i=0;i<NUM_LOCKS;i++) { 
374       l=&(state[i]);
375       if (l->inuse && l->lockcount>0) {
376         snprintf(buf,64,"MULTIPLE LOCKS HELD (%d)",have);
377         printlock(buf,l);
378         have++;
379       }
380     }
381   }
382     
383 }
384
385 static void find_multiple_irqs_held(void)
386 {
387   int i;
388   int have=0;
389   lockcheck_state_t *l;
390   char buf[64];
391
392   for (i=0;i<NUM_LOCKS;i++) { 
393     l=&(state[i]);
394     if (l->inuse && l->irqcount>0) {
395       have++;
396       if (have>=WARN_MULTIPLE_THRESHOLD) { 
397         break;
398       }
399     }
400   }
401   
402   if (have>=WARN_MULTIPLE_THRESHOLD) { 
403     have=0;
404     for (i=0;i<NUM_LOCKS;i++) { 
405       l=&(state[i]);
406       if (l->inuse && l->irqcount>0) { 
407         snprintf(buf,64,"MULTIPLE IRQS HELD (%d)",have);
408         printlock(buf,l);
409         have++;
410       }
411     }
412   }
413
414 }
415
416
417 void palacios_lockcheck_deinit()
418 {
419   int i;
420   lockcheck_state_t *l;
421   LOCK_DECL;
422   
423   LOCK();
424
425   for (i=0;i<NUM_LOCKS;i++) { 
426     l=&(state[i]);
427     if (l->lock) { 
428       printlock("ALLOCATED LOCK AT DEINIT",l);
429       if ((l->lockcount)) { 
430         printlock("BAD LOCK COUNT AT DEINIT",l);
431       }
432       if ((l->irqcount)) { 
433         printlock("BAD IRQ COUNT AT DEINIT",l);
434       }
435     }
436   } 
437   UNLOCK();
438   INFO("LOCKCHECK: DEINITED\n");
439 }
440
441
442 void palacios_lockcheck_alloc(void *lock)
443 {
444   lockcheck_state_t *l;
445   LOCK_DECL;
446
447   LOCK();
448
449   l=get_lock_entry();
450   
451   if (!l) { 
452     DEBUG_OUTPUT("LOCKCHECK: UNABLE TO ALLOCATE TRACKING DATA FOR LOCK 0x%p\n",lock);
453   }
454   l->lock=lock;
455   backtrace(l->allocator);
456   l->lockcount=l->irqcount=0;
457   clear_trace(l->lastlocker);
458   clear_trace(l->lastunlocker);
459   clear_trace(l->lastirqlocker);
460   clear_trace(l->lastirqunlocker);
461   //INFO("LOCKCHECK: LOCK ALLOCATE 0x%p\n",lock);
462 #if PRINT_LOCK_ALLOC
463   printlock("NEW LOCK", l);
464 #endif
465   
466   UNLOCK();
467 }
468   
469 void palacios_lockcheck_free(void *lock)
470 {
471   lockcheck_state_t *l;
472   LOCK_DECL;
473
474   LOCK();
475   l=find_lock_entry(lock);
476   
477   if (!l){
478     UNLOCK();
479     DEBUG_OUTPUT("LOCKCHECK: FREEING UNTRACKED LOCK 0x%p - stack trace follows\n",lock);
480     DEBUG_DUMPSTACK();
481     return;
482   }
483
484   if ((l->lockcount)) { 
485     printlock("BAD LOCK COUNT AT FREE",l);
486   }
487
488   if ((l->irqcount)) { 
489     printlock("BAD IRQ COUNT AT FREE",l);
490   }
491
492 #if PRINT_LOCK_FREE
493   printlock("FREE LOCK",l);
494 #endif
495
496   free_lock_entry(l);
497
498   UNLOCK();
499
500 }
501
502 void palacios_lockcheck_lock(void *lock)
503 {
504   LOCK_DECL;
505   lockcheck_state_t *l;
506
507
508   LOCK();
509
510   l=find_lock_entry(lock); 
511  
512   if (!l) { 
513     UNLOCK();
514     DEBUG_OUTPUT("LOCKCHECK: LOCKING UNTRACKED LOCK 0x%p - stack follows\n",lock);
515     DEBUG_DUMPSTACK();
516     return;
517   }
518   
519   if (l->lockcount!=0) { 
520     printlock("BAD LOCKCOUNT AT LOCK - stack follows",l);
521     DEBUG_DUMPSTACK();
522   }
523   if (l->irqcount!=0) { 
524     printlock("BAD IRQCOUNT AT LOCK - stack follows",l);
525     DEBUG_DUMPSTACK();
526   }
527   
528   l->lockcount++;
529   l->holder=current;
530   l->holdingcpu=get_cpu(); put_cpu();
531   backtrace(l->lastlocker);
532
533   find_multiple_locks_held();
534
535   lock_stack_lock(lock,0,0);
536
537 #if PRINT_LOCK_LOCK
538   printlock("LOCK",l);
539 #endif
540
541   UNLOCK();
542
543 }
544 void palacios_lockcheck_unlock(void *lock)
545 {
546   LOCK_DECL;
547   lockcheck_state_t *l;
548
549   LOCK();
550
551   l=find_lock_entry(lock);
552   
553   if (!l) { 
554     UNLOCK();
555     DEBUG_OUTPUT("LOCKCHECK: UNLOCKING UNTRACKED LOCK 0x%p - stack follows\n",lock);
556     DEBUG_DUMPSTACK();
557     return;
558   }
559   
560   if (l->lockcount!=1) { 
561     printlock("LOCKCHECK: BAD LOCKCOUNT AT UNLOCK - stack follows",l);
562     DEBUG_DUMPSTACK();
563   }
564   if (l->irqcount!=0) { 
565     printlock("LOCKCHECK: BAD IRQCOUNT AT UNLOCK - stack follows",l);
566     DEBUG_DUMPSTACK();
567   }
568
569   lock_stack_unlock(lock,0,0);
570   
571   l->holder=0;
572   l->holdingcpu=0;
573   l->lockcount--;
574   backtrace(l->lastunlocker);
575
576 #if PRINT_LOCK_UNLOCK
577   printlock("UNLOCK",l);
578 #endif
579
580   UNLOCK();
581
582 }
583
584 void palacios_lockcheck_lock_irqsave(void *lock,unsigned long flags)
585 {
586   LOCK_DECL;
587   lockcheck_state_t *l;
588   
589   LOCK();
590
591   l=find_lock_entry(lock);
592
593   if (!l) { 
594     UNLOCK();
595     DEBUG_OUTPUT("LOCKCHECK: IRQ LOCKING UNTRACKED LOCK 0x%p - stack follows\n",lock);
596     DEBUG_DUMPSTACK();
597     return;
598   }
599   
600   if (l->lockcount!=0) { 
601     printlock("BAD LOCKCOUNT AT IRQ LOCK - stack follows",l);
602     DEBUG_DUMPSTACK();
603   }
604   if (l->irqcount!=0) { 
605     printlock("BAD IRQCOUNT AT IRQ LOCK - stack follows",l);
606     DEBUG_DUMPSTACK();
607   }
608   
609   l->irqcount++;
610   l->holder=current;
611   l->holdingcpu=get_cpu(); put_cpu();
612   l->lastlockflags=flags;
613   backtrace(l->lastirqlocker);
614
615   find_multiple_irqs_held();
616
617   lock_stack_lock(lock,1,flags);
618
619 #if PRINT_LOCK_LOCK
620   printlock("LOCK_IRQSAVE",l);
621 #endif
622
623   UNLOCK();
624
625
626 }
627
628
629 //
630 // This is separated into two components to avoid a race between
631 // the underlying spin_unlock_irqrestore and the next lockcheck_lock_irqsave
632 // If simply record the state after the unlock, we might see that the 
633 // irqcount has already increased.  Therefore, we will acquire the 
634 // lockchecker lock in _pre and release it in _post.  Note that when
635 // we release the lock in _post, we restore the flags provided by the 
636 // code under test - NOT our original flags
637 //
638 // unlock_pre() - stores flags, takes mylock discard flags
639 // At this point, a lockcheck_lock cannot enter, since it's stuck on mylock
640 // spinunlock - restores lock, restores original flags
641 // unlock_post() - restores mylock WITH orig flags
642 //
643 void palacios_lockcheck_unlock_irqrestore_pre(void *lock,unsigned long flags)
644 {
645   LOCK_DECL;
646   
647   LOCK();  // flags are discarded
648   // at this point, the actual spin unlock can run 
649   // if another thread hits lockcheck_irqsave at this point, it
650   // will block on mylock
651 }
652
653 void palacios_lockcheck_unlock_irqrestore_post(void *lock,unsigned long flags)
654 {
655   LOCK_DECL;
656   lockcheck_state_t *l;
657
658 #if LOCK_SELF
659   // when we unlock, want to restore the flags *the user wants*
660   f = flags;
661 #endif
662
663   // Note that we DO NOT take mylock here, since we already took it in
664   // _pre
665
666   l=find_lock_entry(lock);
667
668   if (!l) { 
669     UNLOCK();  // release any waiting threads on lockcheck_lock_irqsave
670     DEBUG_OUTPUT("LOCKCHECK: IRQ UNLOCKING UNTRACKED LOCK 0x%p - stack follows\n",lock);
671     DEBUG_DUMPSTACK();
672     return;
673   }
674   
675   if (l->lockcount!=0) { 
676     printlock("LOCKCHECK: BAD LOCKCOUNT AT IRQ UNLOCK - stack follows",l);
677     DEBUG_DUMPSTACK();
678   }
679   if (l->irqcount!=1) { 
680     printlock("LOCKCHECK: BAD IRQCOUNT AT IRQ UNLOCK - stack follows",l);
681     DEBUG_DUMPSTACK();
682   }
683   
684   l->holder=0;
685   l->holdingcpu=0;
686   l->irqcount--;
687   l->lastunlockflags = flags;
688
689   lock_stack_unlock(lock,1,flags);
690
691   backtrace(l->lastirqunlocker);
692
693 #if PRINT_LOCK_UNLOCK
694   printlock("UNLOCK_IRQRESTORE",l);
695 #endif
696   UNLOCK(); // release any waiting threads on lockcheck_lock_irqsave
697
698 }