Skip to content

Commit db320ae

Browse files
More involved MHP check
1 parent 041e544 commit db320ae

File tree

5 files changed

+150
-5
lines changed

5 files changed

+150
-5
lines changed

src/analyses/pthreadBarriers.ml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,26 @@ struct
5353
let count = Waiters.cardinal relevant_waiters in
5454
match capacity with
5555
| `Lifted c ->
56-
Z.geq (Z.of_int count) (BatOption.default Z.zero (Capacity.I.minimal c))
56+
(* Add 1 as the thread calling wait at the moment will not be MHP with itself *)
57+
let min_cap = (BatOption.default Z.zero (Capacity.I.minimal c)) in
58+
if Z.leq min_cap Z.one then
59+
true
60+
else if min_cap = Z.of_int 2 && count = 1 then
61+
true
62+
else if Z.geq (Z.of_int (count + 1)) min_cap then
63+
(* This is quite a cute problem: Do (min_cap-1) elements exist in the set such that
64+
MHP is pairwise true? This solution is a sledgehammer, there should be something much
65+
better algorithmically (beyond just laziness) *)
66+
let waiters = Waiters.elements relevant_waiters in
67+
let min_cap = Z.to_int min_cap in
68+
let lists = List.init (min_cap - 1) (fun _ -> waiters) in
69+
let candidates = BatList.n_cartesian_product lists in
70+
List.exists (fun candidate ->
71+
let pairwise = BatList.cartesian_product candidate candidate in
72+
List.for_all (fun (a,b) -> MHP.may_happen_in_parallel a b) pairwise
73+
) candidates
74+
else
75+
false
5776
| _ -> true
5877
in
5978
if may_run then

tests/regression/82-barrier/02-more.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ int main(int argc, char const *argv[])
3838
i = 1;
3939
}
4040

41-
// Created too late to have any effect
42-
pthread_t t2;
43-
pthread_create(&t2,NULL,f1,NULL);
44-
4541
__goblint_check(i == 0);
4642

4743

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// PARAM: --set ana.activated[+] 'pthreadBarriers'
2+
#include<pthread.h>
3+
#include<stdio.h>
4+
#include<unistd.h>
5+
6+
int g;
7+
8+
pthread_barrier_t barrier;
9+
10+
11+
void* f1(void* ptr) {
12+
pthread_barrier_wait(&barrier);
13+
return NULL;
14+
}
15+
16+
int main(int argc, char const *argv[])
17+
{
18+
int top;
19+
int i = 0;
20+
21+
pthread_barrier_init(&barrier, NULL, 2);
22+
23+
pthread_t t1;
24+
pthread_create(&t1,NULL,f1,NULL);
25+
26+
if(top) {
27+
pthread_barrier_wait(&barrier);
28+
// Live!
29+
i = 1;
30+
}
31+
32+
__goblint_check(i == 0); //UNKNOWN!
33+
34+
35+
return 0;
36+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// PARAM: --set ana.activated[+] 'pthreadBarriers'
2+
#include<pthread.h>
3+
#include<stdio.h>
4+
#include<unistd.h>
5+
6+
int g;
7+
8+
pthread_barrier_t barrier;
9+
10+
void* f2(void* ptr) {
11+
pthread_barrier_wait(&barrier);
12+
return NULL;
13+
}
14+
15+
void* f1(void* ptr) {
16+
pthread_barrier_wait(&barrier);
17+
18+
// This is past the barrier, so it will not be reached
19+
pthread_t t2;
20+
pthread_create(&t2,NULL,f2,NULL);
21+
22+
return NULL;
23+
}
24+
25+
int main(int argc, char const *argv[])
26+
{
27+
int top;
28+
int i = 0;
29+
30+
pthread_barrier_init(&barrier, NULL, 3);
31+
32+
pthread_t t1;
33+
pthread_create(&t1,NULL,f1,NULL);
34+
35+
if(top) {
36+
pthread_barrier_wait(&barrier);
37+
// Unreachable
38+
i = 1;
39+
}
40+
41+
// Created too late to have any effect
42+
pthread_t t2;
43+
pthread_create(&t2,NULL,f1,NULL);
44+
45+
__goblint_check(i == 0);
46+
47+
48+
return 0;
49+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// PARAM: --set ana.activated[+] 'pthreadBarriers'
2+
#include<pthread.h>
3+
#include<stdio.h>
4+
#include<unistd.h>
5+
6+
int g;
7+
8+
pthread_barrier_t barrier;
9+
10+
11+
void* f1(void* ptr) {
12+
pthread_barrier_wait(&barrier);
13+
14+
// This should not be reached as either main calls wait or the other thread is created
15+
// -> In the concrete, there never are three threads calling wait
16+
17+
return NULL;
18+
}
19+
20+
int main(int argc, char const *argv[])
21+
{
22+
int top;
23+
int top2;
24+
int i = 0;
25+
26+
pthread_barrier_init(&barrier, NULL, 3);
27+
28+
pthread_t t1;
29+
pthread_create(&t1,NULL,f1,NULL);
30+
31+
if(top) {
32+
pthread_barrier_wait(&barrier);
33+
// Unreachable
34+
i = 1;
35+
} else {
36+
pthread_t t2;
37+
pthread_create(&t2,NULL,f1,NULL);
38+
}
39+
40+
41+
__goblint_check(i == 0);
42+
43+
44+
return 0;
45+
}

0 commit comments

Comments
 (0)