diff options
Diffstat (limited to 'scripts/coccinelle/locks/mini_lock.cocci')
-rw-r--r-- | scripts/coccinelle/locks/mini_lock.cocci | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/scripts/coccinelle/locks/mini_lock.cocci b/scripts/coccinelle/locks/mini_lock.cocci new file mode 100644 index 000000000000..7641a2925434 --- /dev/null +++ b/scripts/coccinelle/locks/mini_lock.cocci | |||
@@ -0,0 +1,95 @@ | |||
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 Nicolas Palix, DIKU. GPLv2. | ||
10 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
11 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
12 | // URL: http://coccinelle.lip6.fr/ | ||
13 | // Comments: | ||
14 | // Options: -no_includes -include_headers | ||
15 | |||
16 | virtual org | ||
17 | virtual report | ||
18 | |||
19 | @prelocked@ | ||
20 | position p1,p; | ||
21 | expression E1; | ||
22 | @@ | ||
23 | |||
24 | ( | ||
25 | mutex_lock@p1 | ||
26 | | | ||
27 | mutex_trylock@p1 | ||
28 | | | ||
29 | spin_lock@p1 | ||
30 | | | ||
31 | spin_trylock@p1 | ||
32 | | | ||
33 | read_lock@p1 | ||
34 | | | ||
35 | read_trylock@p1 | ||
36 | | | ||
37 | write_lock@p1 | ||
38 | | | ||
39 | write_trylock@p1 | ||
40 | | | ||
41 | read_lock_irq@p1 | ||
42 | | | ||
43 | write_lock_irq@p1 | ||
44 | | | ||
45 | read_lock_irqsave@p1 | ||
46 | | | ||
47 | write_lock_irqsave@p1 | ||
48 | | | ||
49 | spin_lock_irq@p1 | ||
50 | | | ||
51 | spin_lock_irqsave@p1 | ||
52 | ) (E1@p,...); | ||
53 | |||
54 | @looped@ | ||
55 | position r; | ||
56 | @@ | ||
57 | |||
58 | for(...;...;...) { <+... return@r ...; ...+> } | ||
59 | |||
60 | @err@ | ||
61 | expression E1; | ||
62 | position prelocked.p; | ||
63 | position up != prelocked.p1; | ||
64 | position r!=looped.r; | ||
65 | identifier lock,unlock; | ||
66 | @@ | ||
67 | |||
68 | lock(E1@p,...); | ||
69 | <+... when != E1 | ||
70 | if (...) { | ||
71 | ... when != E1 | ||
72 | return@r ...; | ||
73 | } | ||
74 | ...+> | ||
75 | unlock@up(E1,...); | ||
76 | |||
77 | @script:python depends on org@ | ||
78 | p << prelocked.p1; | ||
79 | lock << err.lock; | ||
80 | unlock << err.unlock; | ||
81 | p2 << err.r; | ||
82 | @@ | ||
83 | |||
84 | cocci.print_main(lock,p) | ||
85 | cocci.print_secs(unlock,p2) | ||
86 | |||
87 | @script:python depends on report@ | ||
88 | p << prelocked.p1; | ||
89 | lock << err.lock; | ||
90 | unlock << err.unlock; | ||
91 | p2 << err.r; | ||
92 | @@ | ||
93 | |||
94 | msg = "preceding lock on line %s" % (p[0].line) | ||
95 | coccilib.report.print_report(p2[0],msg) | ||