1*54c05628SNicolas Palix/// Find missing unlocks. This semantic match considers the specific case 2*54c05628SNicolas Palix/// where the unlock is missing from an if branch, and there is a lock 3*54c05628SNicolas Palix/// before the if and an unlock after the if. False positives are due to 4*54c05628SNicolas Palix/// cases where the if branch represents a case where the function is 5*54c05628SNicolas Palix/// supposed to exit with the lock held, or where there is some preceding 6*54c05628SNicolas Palix/// function call that releases the lock. 7*54c05628SNicolas Palix/// 8*54c05628SNicolas Palix// Confidence: Moderate 9*54c05628SNicolas Palix// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. 10*54c05628SNicolas Palix// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. 11*54c05628SNicolas Palix// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. 12*54c05628SNicolas Palix// URL: http://coccinelle.lip6.fr/ 13*54c05628SNicolas Palix// Comments: 14*54c05628SNicolas Palix// Options: -no_includes -include_headers 15*54c05628SNicolas Palix 16*54c05628SNicolas Palixvirtual org 17*54c05628SNicolas Palixvirtual report 18*54c05628SNicolas Palix 19*54c05628SNicolas Palix@prelocked@ 20*54c05628SNicolas Palixposition p1,p; 21*54c05628SNicolas Palixexpression E1; 22*54c05628SNicolas Palix@@ 23*54c05628SNicolas Palix 24*54c05628SNicolas Palix( 25*54c05628SNicolas Palixmutex_lock@p1 26*54c05628SNicolas Palix| 27*54c05628SNicolas Palixmutex_trylock@p1 28*54c05628SNicolas Palix| 29*54c05628SNicolas Palixspin_lock@p1 30*54c05628SNicolas Palix| 31*54c05628SNicolas Palixspin_trylock@p1 32*54c05628SNicolas Palix| 33*54c05628SNicolas Palixread_lock@p1 34*54c05628SNicolas Palix| 35*54c05628SNicolas Palixread_trylock@p1 36*54c05628SNicolas Palix| 37*54c05628SNicolas Palixwrite_lock@p1 38*54c05628SNicolas Palix| 39*54c05628SNicolas Palixwrite_trylock@p1 40*54c05628SNicolas Palix| 41*54c05628SNicolas Palixread_lock_irq@p1 42*54c05628SNicolas Palix| 43*54c05628SNicolas Palixwrite_lock_irq@p1 44*54c05628SNicolas Palix| 45*54c05628SNicolas Palixread_lock_irqsave@p1 46*54c05628SNicolas Palix| 47*54c05628SNicolas Palixwrite_lock_irqsave@p1 48*54c05628SNicolas Palix| 49*54c05628SNicolas Palixspin_lock_irq@p1 50*54c05628SNicolas Palix| 51*54c05628SNicolas Palixspin_lock_irqsave@p1 52*54c05628SNicolas Palix) (E1@p,...); 53*54c05628SNicolas Palix 54*54c05628SNicolas Palix@looped@ 55*54c05628SNicolas Palixposition r; 56*54c05628SNicolas Palix@@ 57*54c05628SNicolas Palix 58*54c05628SNicolas Palixfor(...;...;...) { <+... return@r ...; ...+> } 59*54c05628SNicolas Palix 60*54c05628SNicolas Palix@err@ 61*54c05628SNicolas Palixexpression E1; 62*54c05628SNicolas Palixposition prelocked.p; 63*54c05628SNicolas Palixposition up != prelocked.p1; 64*54c05628SNicolas Palixposition r!=looped.r; 65*54c05628SNicolas Palixidentifier lock,unlock; 66*54c05628SNicolas Palix@@ 67*54c05628SNicolas Palix 68*54c05628SNicolas Palixlock(E1@p,...); 69*54c05628SNicolas Palix<+... when != E1 70*54c05628SNicolas Palixif (...) { 71*54c05628SNicolas Palix ... when != E1 72*54c05628SNicolas Palix return@r ...; 73*54c05628SNicolas Palix} 74*54c05628SNicolas Palix...+> 75*54c05628SNicolas Palixunlock@up(E1,...); 76*54c05628SNicolas Palix 77*54c05628SNicolas Palix@script:python depends on org@ 78*54c05628SNicolas Palixp << prelocked.p1; 79*54c05628SNicolas Palixlock << err.lock; 80*54c05628SNicolas Palixunlock << err.unlock; 81*54c05628SNicolas Palixp2 << err.r; 82*54c05628SNicolas Palix@@ 83*54c05628SNicolas Palix 84*54c05628SNicolas Palixcocci.print_main(lock,p) 85*54c05628SNicolas Palixcocci.print_secs(unlock,p2) 86*54c05628SNicolas Palix 87*54c05628SNicolas Palix@script:python depends on report@ 88*54c05628SNicolas Palixp << prelocked.p1; 89*54c05628SNicolas Palixlock << err.lock; 90*54c05628SNicolas Palixunlock << err.unlock; 91*54c05628SNicolas Palixp2 << err.r; 92*54c05628SNicolas Palix@@ 93*54c05628SNicolas Palix 94*54c05628SNicolas Palixmsg = "preceding lock on line %s" % (p[0].line) 95*54c05628SNicolas Palixcoccilib.report.print_report(p2[0],msg) 96