xref: /linux/scripts/coccinelle/locks/mini_lock.cocci (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1// SPDX-License-Identifier: GPL-2.0-only
2/// Find missing unlocks.  This semantic match considers the specific case
3/// where the unlock is missing from an if branch, and there is a lock
4/// before the if and an unlock after the if.  False positives are due to
5/// cases where the if branch represents a case where the function is
6/// supposed to exit with the lock held, or where there is some preceding
7/// function call that releases the lock.
8///
9// Confidence: Moderate
10// Copyright: (C) 2010-2012 Nicolas Palix.
11// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.
12// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.
13// URL: https://coccinelle.gitlabpages.inria.fr/website
14// Comments:
15// Options: --no-includes --include-headers
16
17virtual context
18virtual org
19virtual report
20
21@prelocked@
22position p1,p;
23expression E1;
24@@
25
26(
27mutex_lock@p1
28|
29mutex_trylock@p1
30|
31spin_lock@p1
32|
33spin_trylock@p1
34|
35read_lock@p1
36|
37read_trylock@p1
38|
39write_lock@p1
40|
41write_trylock@p1
42|
43read_lock_irq@p1
44|
45write_lock_irq@p1
46|
47read_lock_irqsave@p1
48|
49write_lock_irqsave@p1
50|
51spin_lock_irq@p1
52|
53spin_lock_irqsave@p1
54) (E1@p,...);
55
56@err_candidate exists@
57expression E1;
58position prelocked.p;
59position up != prelocked.p1;
60position rc;
61identifier lock,unlock;
62@@
63
64lock(E1@p,...);
65... when != E1
66    when any
67if (...) {
68  ... when != E1
69  return@rc ...;
70}
71... when != E1
72    when any
73unlock@up(E1,...);
74
75@looped exists@
76position err_candidate.rc;
77position r;
78@@
79
80for(...;...;...) { <+... return@rc@r ...; ...+> }
81
82@err exists@
83expression E1;
84position prelocked.p;
85position up != prelocked.p1;
86position r!=looped.r;
87identifier lock,unlock;
88@@
89
90*lock(E1@p,...);
91... when != E1
92    when any
93if (...) {
94  ... when != E1
95*  return@r ...;
96}
97... when != E1
98    when any
99*unlock@up(E1,...);
100
101@script:python depends on org@
102p << prelocked.p1;
103lock << err.lock;
104unlock << err.unlock;
105p2 << err.r;
106@@
107
108cocci.print_main(lock,p)
109cocci.print_secs(unlock,p2)
110
111@script:python depends on report@
112p << prelocked.p1;
113lock << err.lock;
114unlock << err.unlock;
115p2 << err.r;
116@@
117
118msg = "preceding lock on line %s" % (p[0].line)
119coccilib.report.print_report(p2[0],msg)
120