Skip to content

Commit 8fe2e16

Browse files
Also consider locks
1 parent 24d61c0 commit 8fe2e16

File tree

3 files changed

+106
-6
lines changed

3 files changed

+106
-6
lines changed

src/analyses/pthreadBarriers.ml

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,20 @@ struct
2222
module V = VarinfoV
2323

2424
module TID = ThreadIdDomain.Thread
25-
module Waiters = SetDomain.ToppedSet (MHP) (struct let topname = "All MHP" end)
25+
26+
module MHPplusLock = struct
27+
module Locks = LockDomain.MustLockset
28+
29+
include Printable.Prod (MHP) (Locks)
30+
let name () = "MHPplusLock"
31+
32+
let mhp (mhp1, l1) (mhp2, l2) =
33+
MHP.may_happen_in_parallel mhp1 mhp2 && Locks.is_empty (Locks.inter l1 l2)
34+
35+
let may_be_non_unique_thread (mhp, _) = MHP.may_be_non_unique_thread mhp
36+
end
37+
38+
module Waiters = SetDomain.ToppedSet (MHPplusLock) (struct let topname = "All MHP" end)
2639
module Multiprocess = BoolDomain.MayBool
2740
module G = Lattice.Prod3 (Multiprocess) (Capacity) (Waiters)
2841

@@ -43,15 +56,16 @@ struct
4356
let barriers = possible_vinfos ask barrier in
4457
let mhp = MHP.current ask in
4558
let handle_one b =
46-
man.sideg b (Multiprocess.bot (), Capacity.bot (), Waiters.singleton mhp);
59+
let locks = man.ask (Queries.MustLockset) in
60+
man.sideg b (Multiprocess.bot (), Capacity.bot (), Waiters.singleton (mhp, locks));
4761
let addr = ValueDomain.Addr.of_var b in
4862
let (multiprocess,capacity, waiters) = man.global b in
4963
let may_run =
5064
if multiprocess then
5165
true
5266
else
53-
let relevant_waiters = Waiters.filter (fun other -> MHP.may_happen_in_parallel mhp other) waiters in
54-
if Waiters.exists MHP.may_be_non_unique_thread relevant_waiters then
67+
let relevant_waiters = Waiters.filter (fun other -> MHPplusLock.mhp (mhp, locks) other) waiters in
68+
if Waiters.exists MHPplusLock.may_be_non_unique_thread relevant_waiters then
5569
true
5670
else
5771
let count = Waiters.cardinal relevant_waiters in
@@ -61,7 +75,7 @@ struct
6175
let min_cap = (BatOption.default Z.zero (Capacity.I.minimal c)) in
6276
if Z.leq min_cap Z.one then
6377
true
64-
else if min_cap = Z.of_int 2 && count = 1 then
78+
else if min_cap = Z.of_int 2 && count >= 1 then
6579
true
6680
else if Z.geq (Z.of_int (count + 1)) min_cap then
6781
(* This is quite a cute problem: Do (min_cap-1) elements exist in the set such that
@@ -73,7 +87,7 @@ struct
7387
let candidates = BatList.n_cartesian_product lists in
7488
List.exists (fun candidate ->
7589
let pairwise = BatList.cartesian_product candidate candidate in
76-
List.for_all (fun (a,b) -> MHP.may_happen_in_parallel a b) pairwise
90+
List.for_all (fun (a,b) -> MHPplusLock.mhp a b) pairwise
7791
) candidates
7892
else
7993
false
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// NOMAC 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+
pthread_mutex_t mutex;
10+
11+
void* f1(void* ptr) {
12+
pthread_mutex_lock(&mutex);
13+
pthread_barrier_wait(&barrier);
14+
pthread_mutex_unlock(&mutex);
15+
return NULL;
16+
}
17+
18+
int main(int argc, char const *argv[])
19+
{
20+
int top;
21+
int i = 0;
22+
23+
pthread_barrier_init(&barrier, NULL, 2);
24+
25+
pthread_t t1;
26+
pthread_create(&t1,NULL,f1,NULL);
27+
28+
if(top) {
29+
pthread_mutex_lock(&mutex);
30+
pthread_barrier_wait(&barrier);
31+
// Deadlocks
32+
pthread_mutex_unlock(&mutex);
33+
i = 1;
34+
}
35+
36+
__goblint_check(i == 0);
37+
38+
return 0;
39+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// NOMAC 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+
pthread_mutex_t mutex;
10+
11+
void* f1(void* ptr) {
12+
pthread_mutex_lock(&mutex);
13+
pthread_barrier_wait(&barrier);
14+
pthread_mutex_unlock(&mutex);
15+
return NULL;
16+
}
17+
18+
void* f2(void* ptr) {
19+
pthread_mutex_lock(&mutex);
20+
pthread_barrier_wait(&barrier);
21+
pthread_mutex_unlock(&mutex);
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, 2);
31+
32+
pthread_t t1;
33+
pthread_create(&t1,NULL,f1,NULL);
34+
35+
pthread_t t2;
36+
pthread_create(&t2,NULL,f2,NULL);
37+
38+
39+
if(top) {
40+
pthread_barrier_wait(&barrier);
41+
i = 1;
42+
}
43+
44+
__goblint_check(i == 0); //UNKNOWN!
45+
46+
return 0;
47+
}

0 commit comments

Comments
 (0)