1 // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.fuchsia.Lock -verify %s
2 
3 typedef int spin_lock_t;
4 typedef int zx_status_t;
5 typedef int zx_time_t;
6 
7 void spin_lock(spin_lock_t *lock);
8 int spin_trylock(spin_lock_t *lock);
9 void spin_unlock(spin_lock_t *lock);
10 void spin_lock_init(spin_lock_t *lock);
11 
12 void spin_lock_save(spin_lock_t *lock, void *statep,
13                     int flags);
14 void spin_unlock_restore(spin_lock_t *lock, void *old_state,
15                          int flags);
16 
17 spin_lock_t mtx1;
18 spin_lock_t mtx2;
19 
bad1(void)20 void bad1(void)
21 {
22 	spin_lock(&mtx1);	// no-warning
23 	spin_lock(&mtx1);	// expected-warning{{This lock has already been acquired}}
24 }
25 
bad2(void)26 void bad2(void) {
27   spin_lock(&mtx1);
28   spin_unlock(&mtx1);
29   spin_unlock(&mtx1); // expected-warning {{This lock has already been unlocked}}
30 }
31 
bad3()32 void bad3() {
33   spin_lock_init(&mtx1);
34   if (spin_trylock(&mtx1) != 0)
35     spin_unlock(&mtx1); // expected-warning {{This lock has already been unlocked}}
36 }
37 
bad4(void)38 void bad4(void) {
39   spin_lock(&mtx1);
40   spin_lock(&mtx2);
41   spin_unlock(&mtx1); // expected-warning {{This was not the most recently acquired lock. Possible lock order reversal}}
42   spin_unlock(&mtx2);
43 }
44 
good()45 void good() {
46   spin_lock_t mtx;
47   spin_lock_init(&mtx);
48   spin_lock_save(&mtx, 0, 0);
49   spin_unlock_restore(&mtx, 0, 0);
50 }
51 
good2()52 void good2() {
53   spin_lock_t mtx;
54   spin_lock_init(&mtx);
55   if (spin_trylock(&mtx) == 0)
56     spin_unlock(&mtx);
57 }
58 
59 typedef int sync_mutex_t;
60 void sync_mutex_lock(sync_mutex_t* mutex);
61 void sync_mutex_lock_with_waiter(sync_mutex_t* mutex);
62 zx_status_t sync_mutex_timedlock(sync_mutex_t* mutex, zx_time_t deadline);
63 zx_status_t sync_mutex_trylock(sync_mutex_t* mutex);
64 void sync_mutex_unlock(sync_mutex_t* mutex);
65 
66 sync_mutex_t smtx1;
67 sync_mutex_t smtx2;
68 
bad11(void)69 void bad11(void)
70 {
71 	sync_mutex_lock(&smtx1);	// no-warning
72 	sync_mutex_lock(&smtx1);	// expected-warning{{This lock has already been acquired}}
73 }
74 
bad12(void)75 void bad12(void) {
76   sync_mutex_lock_with_waiter(&smtx1);
77   sync_mutex_unlock(&smtx1);
78   sync_mutex_unlock(&smtx1); // expected-warning {{This lock has already been unlocked}}
79 }
80 
bad13()81 void bad13() {
82   sync_mutex_unlock(&smtx1);
83   if (sync_mutex_trylock(&smtx1) != 0)
84     sync_mutex_unlock(&smtx1); // expected-warning {{This lock has already been unlocked}}
85 }
86 
bad14(void)87 void bad14(void) {
88   sync_mutex_lock(&smtx1);
89   sync_mutex_lock(&smtx2);
90   sync_mutex_unlock(&smtx1); // expected-warning {{This was not the most recently acquired lock. Possible lock order reversal}}
91   sync_mutex_unlock(&smtx2);
92 }
93 
good11()94 void good11() {
95   sync_mutex_t mtx;
96   if (sync_mutex_trylock(&mtx) == 0)
97     sync_mutex_unlock(&mtx);
98 }
99 
good12()100 void good12() {
101   sync_mutex_t mtx;
102   if (sync_mutex_timedlock(&mtx, 0) == 0)
103     sync_mutex_unlock(&mtx);
104 }
105