1/// Find missing unlocks.  This semantic match considers the specific case
2/// where the unlock is missing from an if branch, and there is a lock
3/// before the if and an unlock after the if.  False positives are due to
4/// cases where the if branch represents a case where the function is
5/// supposed to exit with the lock held, or where there is some preceding
6/// function call that releases the lock.
7///
8// Confidence: Moderate
9// Copyright: (C) 2010-2012 Nicolas Palix.  GPLv2.
10// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.  GPLv2.
11// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.  GPLv2.
12// URL: http://coccinelle.lip6.fr/
13
14virtual context
15virtual org
16virtual report
17
18@prelocked depends on !(file in "ext")@
19position p1,p;
20expression E1;
21@@
22
23(
24irq_lock@p1
25|
26k_mutex_lock@p1
27|
28k_sem_take@p1
29|
30k_spin_lock@p1
31) (E1@p,...);
32
33@looped depends on !(file in "ext")@
34position r;
35@@
36
37for(...;...;...) { <+... return@r ...; ...+> }
38
39@balanced exists@
40position p1 != prelocked.p1;
41position prelocked.p;
42position pif;
43identifier lock,unlock;
44expression x <= prelocked.E1;
45expression E,prelocked.E1;
46expression E2;
47@@
48
49if (E) {
50 ... when != E1
51 lock(E1@p,...)
52 ... when any
53}
54... when != E1
55    when != \(x = E2\|&x\)
56if@pif (E) {
57 ... when != E1
58 unlock@p1(E1,...)
59 ... when any
60}
61
62@err depends on !(file in "ext") exists@
63expression E1;
64position prelocked.p,balanced.pif;
65position up != prelocked.p1;
66position r!=looped.r;
67identifier lock,unlock;
68statement S1,S2;
69@@
70
71*lock(E1@p,...);
72... when != E1
73    when any
74    when != if@pif (...) S1
75if (...) {
76  ... when != E1
77      when != if@pif (...) S2
78*  return@r ...;
79}
80... when != E1
81    when any
82*unlock@up(E1,...);
83
84@script:python depends on org@
85p << prelocked.p1;
86lock << err.lock;
87unlock << err.unlock;
88p2 << err.r;
89@@
90
91cocci.print_main(lock,p)
92cocci.print_secs(unlock,p2)
93
94@script:python depends on report@
95p << prelocked.p1;
96lock << err.lock;
97unlock << err.unlock;
98p2 << err.r;
99@@
100
101msg = "preceding lock on line %s" % (p[0].line)
102coccilib.report.print_report(p2[0],msg)
103