aboutsummaryrefslogtreecommitdiff
path: root/test/Analysis/pthreadlock.c
blob: b90477424511453a6005376fa6a4706a919b0933 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.unix.PthreadLock -verify %s

// Tests performing normal locking patterns and wrong locking orders

typedef struct {
	void	*foo;
} pthread_mutex_t;

typedef pthread_mutex_t lck_mtx_t;

extern int pthread_mutex_lock(pthread_mutex_t *);
extern int pthread_mutex_unlock(pthread_mutex_t *);
extern int pthread_mutex_trylock(pthread_mutex_t *);
extern int lck_mtx_lock(lck_mtx_t *);
extern int lck_mtx_unlock(lck_mtx_t *);
extern int lck_mtx_try_lock(lck_mtx_t *);

pthread_mutex_t mtx1, mtx2;
lck_mtx_t lck1, lck2;

void
ok1(void)
{
	pthread_mutex_lock(&mtx1); // no-warning
}

void
ok2(void)
{
	pthread_mutex_unlock(&mtx1); // no-warning
}

void
ok3(void)
{
	pthread_mutex_lock(&mtx1);	// no-warning
	pthread_mutex_unlock(&mtx1);	// no-warning
	pthread_mutex_lock(&mtx1);	// no-warning
	pthread_mutex_unlock(&mtx1);	// no-warning
}

void
ok4(void)
{
	pthread_mutex_lock(&mtx1);	// no-warning
	pthread_mutex_unlock(&mtx1);	// no-warning
	pthread_mutex_lock(&mtx2);	// no-warning
	pthread_mutex_unlock(&mtx2);	// no-warning
}

void
ok5(void)
{
	if (pthread_mutex_trylock(&mtx1) == 0)	// no-warning
		pthread_mutex_unlock(&mtx1);	// no-warning
}

void
ok6(void)
{
	lck_mtx_lock(&lck1);		// no-warning
}

void
ok7(void)
{
	if (lck_mtx_try_lock(&lck1) != 0)	// no-warning
		lck_mtx_unlock(&lck1);		// no-warning
}

void
bad1(void)
{
	pthread_mutex_lock(&mtx1);	// no-warning
	pthread_mutex_lock(&mtx1);	// expected-warning{{This lock has already been acquired}}
}

void
bad2(void)
{
	pthread_mutex_lock(&mtx1);	// no-warning
	pthread_mutex_unlock(&mtx1);	// no-warning
	pthread_mutex_lock(&mtx1);	// no-warning
	pthread_mutex_lock(&mtx1);	// expected-warning{{This lock has already been acquired}}
}

void
bad3(void)
{
	pthread_mutex_lock(&mtx1);	// no-warning
	pthread_mutex_lock(&mtx2);	// no-warning
	pthread_mutex_unlock(&mtx1);	// expected-warning{{This was not the most recently acquired lock}}
	pthread_mutex_unlock(&mtx2);
}

void
bad4(void)
{
	if (pthread_mutex_trylock(&mtx1)) // no-warning
		return;
	pthread_mutex_lock(&mtx2);	// no-warning
	pthread_mutex_unlock(&mtx1);	// expected-warning{{This was not the most recently acquired lock}}
}

void
bad5(void)
{
	lck_mtx_lock(&lck1);	// no-warning
	lck_mtx_lock(&lck1);	// expected-warning{{This lock has already been acquired}}
}

void
bad6(void)
{
	lck_mtx_lock(&lck1);	// no-warning
	lck_mtx_unlock(&lck1);	// no-warning
	lck_mtx_lock(&lck1);	// no-warning
	lck_mtx_lock(&lck1);	// expected-warning{{This lock has already been acquired}}
}

void
bad7(void)
{
	lck_mtx_lock(&lck1);	// no-warning
	lck_mtx_lock(&lck2);	// no-warning
	lck_mtx_unlock(&lck1);	// expected-warning{{This was not the most recently acquired lock}}
	lck_mtx_unlock(&lck2);
}

void
bad8(void)
{
	if (lck_mtx_try_lock(&lck1) == 0) // no-warning
		return;
	lck_mtx_lock(&lck2);		// no-warning
	lck_mtx_unlock(&lck1);		// expected-warning{{This was not the most recently acquired lock}}
}