summaryrefslogtreecommitdiff
path: root/test/Analysis/block-in-critical-section.cpp
blob: fcf6188fc033ec8f4f6f7990916003427b26a63b (plain)
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.unix.BlockInCriticalSection -std=c++11 -verify %s

void sleep(int x) {}

namespace std {
struct mutex {
  void lock() {}
  void unlock() {}
};
template<typename T>
struct lock_guard {
  lock_guard<T>(std::mutex) {}
  ~lock_guard<T>() {}
};
template<typename T>
struct unique_lock {
  unique_lock<T>(std::mutex) {}
  ~unique_lock<T>() {}
};
template<typename T>
struct not_real_lock {
  not_real_lock<T>(std::mutex) {}
};
}

void getc() {}
void fgets() {}
void read() {}
void recv() {}

void pthread_mutex_lock() {}
void pthread_mutex_trylock() {}
void pthread_mutex_unlock() {}

void mtx_lock() {}
void mtx_timedlock() {}
void mtx_trylock() {}
void mtx_unlock() {}

void testBlockInCriticalSectionWithStdMutex() {
  std::mutex m;
  m.lock();
  sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
  getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
  fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
  read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
  recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
  m.unlock();
}

void testBlockInCriticalSectionWithPthreadMutex() {
  pthread_mutex_lock();
  sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
  getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
  fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
  read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
  recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
  pthread_mutex_unlock();

  pthread_mutex_trylock();
  sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
  getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
  fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
  read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
  recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
  pthread_mutex_unlock();
}

void testBlockInCriticalSectionC11Locks() {
  mtx_lock();
  sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
  getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
  fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
  read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
  recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
  mtx_unlock();

  mtx_timedlock();
  sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
  getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
  fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
  read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
  recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
  mtx_unlock();

  mtx_trylock();
  sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
  getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}}
  fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}}
  read(); // expected-warning {{Call to blocking function 'read' inside of critical section}}
  recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}}
  mtx_unlock();
}

void testBlockInCriticalSectionWithNestedMutexes() {
  std::mutex m, n, k;
  m.lock();
  n.lock();
  k.lock();
  sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
  k.unlock();
  sleep(5); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
  n.unlock();
  sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
  m.unlock();
  sleep(3); // no-warning
}

void f() {
  sleep(1000); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
}

void testBlockInCriticalSectionInterProcedural() {
  std::mutex m;
  m.lock();
  f();
  m.unlock();
}

void testBlockInCriticalSectionUnexpectedUnlock() {
  std::mutex m;
  m.unlock();
  sleep(1); // no-warning
  m.lock();
  sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
}

void testBlockInCriticalSectionLockGuard() {
  std::mutex g_mutex;
  std::not_real_lock<std::mutex> not_real_lock(g_mutex);
  sleep(1); // no-warning

  std::lock_guard<std::mutex> lock(g_mutex);
  sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
}

void testBlockInCriticalSectionLockGuardNested() {
  testBlockInCriticalSectionLockGuard();
  sleep(1); // no-warning
}

void testBlockInCriticalSectionUniqueLock() {
  std::mutex g_mutex;
  std::not_real_lock<std::mutex> not_real_lock(g_mutex);
  sleep(1); // no-warning

  std::unique_lock<std::mutex> lock(g_mutex);
  sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}}
}

void testBlockInCriticalSectionUniqueLockNested() {
  testBlockInCriticalSectionUniqueLock();
  sleep(1); // no-warning
}