Skip to content

Commit db4413b

Browse files
Merge pull request #1643 from goblint/lmust_cluster
Relational MM: Cluster LMust
2 parents d982753 + 15b269f commit db4413b

File tree

6 files changed

+179
-40
lines changed

6 files changed

+179
-40
lines changed

src/analyses/apron/relationPriv.apron.ml

Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -761,11 +761,15 @@ module type ClusterArg = functor (RD: RelationDomain.RD) ->
761761
sig
762762
module LRD: Lattice.S
763763

764+
module Cluster: Printable.S
765+
764766
val keep_only_protected_globals: Q.ask -> LockDomain.MustLock.t -> LRD.t -> LRD.t
765767
val keep_global: varinfo -> LRD.t -> LRD.t
766768

767769
val lock: RD.t -> LRD.t -> LRD.t -> RD.t
768-
val unlock: W.t -> RD.t -> LRD.t
770+
val unlock: W.t -> RD.t -> LRD.t * (Cluster.t list)
771+
772+
val filter_clusters: (Cluster.t -> bool) -> LRD.t -> LRD.t
769773

770774
val name: unit -> string
771775
end
@@ -775,6 +779,7 @@ module NoCluster:ClusterArg = functor (RD: RelationDomain.RD) ->
775779
struct
776780
open CommonPerMutex(RD)
777781
module LRD = RD
782+
module Cluster = Printable.Unit
778783

779784
let keep_only_protected_globals = keep_only_protected_globals
780785

@@ -786,7 +791,13 @@ struct
786791
RD.meet oct (RD.join local_m get_m)
787792

788793
let unlock w oct_side =
789-
oct_side
794+
oct_side, [()]
795+
796+
let filter_clusters f oct =
797+
if f () then
798+
oct
799+
else
800+
RD.bot ()
790801

791802
let name () = "no-clusters"
792803
end
@@ -860,6 +871,8 @@ struct
860871
module VS = SetDomain.Make (CilType.Varinfo)
861872
module LRD = MapDomain.MapBot (VS) (RD)
862873

874+
module Cluster = VS
875+
863876
let keep_only_protected_globals ask m octs =
864877
(* normal (strong) mapping: contains only still fully protected *)
865878
(* must filter by protection to avoid later meeting with non-protecting *)
@@ -909,7 +922,10 @@ struct
909922
let oct_side_cluster gs =
910923
RD.keep_vars oct_side (gs |> VS.elements |> List.map V.global)
911924
in
912-
LRD.add_list_fun clusters oct_side_cluster (LRD.empty ())
925+
(LRD.add_list_fun clusters oct_side_cluster (LRD.empty ()), clusters)
926+
927+
let filter_clusters f oct =
928+
LRD.filter (fun gs _ -> f gs) oct
913929

914930
let name = ClusteringArg.name
915931
end
@@ -925,6 +941,8 @@ struct
925941
module LRD1 = DCCluster.LRD
926942
module LRD = Lattice.Prod (LRD1) (LRD1) (* second component is only used between keep_* and lock for additional weak mapping *)
927943

944+
module Cluster = DCCluster.Cluster
945+
928946
let name = ClusteringArg.name
929947

930948
let filter_map' f m =
@@ -986,7 +1004,11 @@ struct
9861004
r
9871005

9881006
let unlock w oct_side =
989-
(DCCluster.unlock w oct_side, LRD1.bot ())
1007+
let lad, clusters = DCCluster.unlock w oct_side in
1008+
((lad, LRD1.bot ()), clusters)
1009+
1010+
let filter_clusters f (lad,lad') =
1011+
(LRD1.filter (fun gs _ -> f gs) lad, LRD1.filter (fun gs _ -> f gs) lad')
9901012
end
9911013

9921014
(** Per-mutex meet with TIDs. *)
@@ -1000,7 +1022,7 @@ struct
10001022
module Cluster = NC
10011023
module LRD = NC.LRD
10021024

1003-
include PerMutexTidCommon (Digest) (LRD)
1025+
include PerMutexTidCommon (Digest) (LRD) (NC.Cluster)
10041026

10051027
module AV = RD.V
10061028
module P = UnitP
@@ -1022,13 +1044,11 @@ struct
10221044
let get_m = get_relevant_writes ask m (G.mutex @@ getg (V.mutex m)) in
10231045
if M.tracing then M.traceli "relationpriv" "get_m_with_mutex_inits %a\n get=%a" LockDomain.MustLock.pretty m LRD.pretty get_m;
10241046
let r =
1025-
if not inits then
1026-
get_m
1027-
else
1028-
let get_mutex_inits = merge_all @@ G.mutex @@ getg V.mutex_inits in
1029-
let get_mutex_inits' = Cluster.keep_only_protected_globals ask m get_mutex_inits in
1030-
if M.tracing then M.trace "relationpriv" "inits=%a\n inits'=%a" LRD.pretty get_mutex_inits LRD.pretty get_mutex_inits';
1031-
LRD.join get_m get_mutex_inits'
1047+
let get_mutex_inits = merge_all @@ G.mutex @@ getg V.mutex_inits in
1048+
let get_mutex_inits' = Cluster.keep_only_protected_globals ask m get_mutex_inits in
1049+
let get_mutex_inits' = Cluster.filter_clusters inits get_mutex_inits' in
1050+
if M.tracing then M.trace "relationpriv" "inits=%a\n inits'=%a" LRD.pretty get_mutex_inits LRD.pretty get_mutex_inits';
1051+
LRD.join get_m get_mutex_inits'
10321052
in
10331053
if M.tracing then M.traceu "relationpriv" "-> %a" LRD.pretty r;
10341054
r
@@ -1047,25 +1067,21 @@ struct
10471067
in
10481068
if M.tracing then M.traceli "relationpriv" "get_mutex_global_g_with_mutex_inits %a\n get=%a" CilType.Varinfo.pretty g LRD.pretty get_mutex_global_g;
10491069
let r =
1050-
if not inits then
1051-
get_mutex_global_g
1052-
else
1053-
let get_mutex_inits = merge_all @@ G.mutex @@ getg V.mutex_inits in
1054-
let get_mutex_inits' = Cluster.keep_global g get_mutex_inits in
1055-
if M.tracing then M.trace "relationpriv" "inits=%a\n inits'=%a" LRD.pretty get_mutex_inits LRD.pretty get_mutex_inits';
1056-
LRD.join get_mutex_global_g get_mutex_inits'
1070+
let get_mutex_inits = merge_all @@ G.mutex @@ getg V.mutex_inits in
1071+
let get_mutex_inits' = Cluster.keep_global g get_mutex_inits in
1072+
let get_mutex_inits' = Cluster.filter_clusters inits get_mutex_inits' in
1073+
if M.tracing then M.trace "relationpriv" "inits=%a\n inits'=%a" LRD.pretty get_mutex_inits LRD.pretty get_mutex_inits';
1074+
LRD.join get_mutex_global_g get_mutex_inits'
10571075
in
10581076
if M.tracing then M.traceu "relationpriv" "-> %a" LRD.pretty r;
10591077
r
10601078

10611079
let get_mutex_global_g_with_mutex_inits_atomic inits ask getg =
10621080
(* Unprotected invariant is one big relation. *)
10631081
let get_mutex_global_g = get_relevant_writes_nofilter ask @@ G.mutex @@ getg (V.mutex atomic_mutex) in
1064-
if not inits then
1065-
get_mutex_global_g
1066-
else
1067-
let get_mutex_inits = merge_all @@ G.mutex @@ getg V.mutex_inits in
1068-
LRD.join get_mutex_global_g get_mutex_inits
1082+
let get_mutex_inits = merge_all @@ G.mutex @@ getg V.mutex_inits in
1083+
let get_mutex_inits' = Cluster.filter_clusters inits get_mutex_inits in
1084+
LRD.join get_mutex_global_g get_mutex_inits'
10691085

10701086
let read_global (ask: Q.ask) getg (st: relation_components_t) g x: RD.t =
10711087
let atomic = Param.handle_atomic && ask.f MustBeAtomic in
@@ -1079,9 +1095,9 @@ struct
10791095
if atomic && RD.mem_var rel (AV.global g) then
10801096
rel (* Read previous unpublished unprotected write in current atomic section. *)
10811097
else if atomic then
1082-
Cluster.lock rel local_m (get_mutex_global_g_with_mutex_inits_atomic (not (LMust.mem lm lmust)) ask getg) (* Read unprotected invariant as full relation. *)
1098+
Cluster.lock rel local_m (get_mutex_global_g_with_mutex_inits_atomic (fun c -> (not (LMust.mem (lm,c) lmust))) ask getg) (* Read unprotected invariant as full relation. *)
10831099
else
1084-
Cluster.lock rel local_m (get_mutex_global_g_with_mutex_inits (not (LMust.mem lm lmust)) ask getg g)
1100+
Cluster.lock rel local_m (get_mutex_global_g_with_mutex_inits (fun c -> (not (LMust.mem (lm,c) lmust))) ask getg g)
10851101
in
10861102
(* read *)
10871103
let g_var = AV.global g in
@@ -1113,9 +1129,9 @@ struct
11131129
if atomic && RD.mem_var rel (AV.global g) then
11141130
rel (* Read previous unpublished unprotected write in current atomic section. *)
11151131
else if atomic then
1116-
Cluster.lock rel local_m (get_mutex_global_g_with_mutex_inits_atomic (not (LMust.mem lm lmust)) ask getg) (* Read unprotected invariant as full relation. *)
1132+
Cluster.lock rel local_m (get_mutex_global_g_with_mutex_inits_atomic (fun c -> (not (LMust.mem (lm,c) lmust))) ask getg) (* Read unprotected invariant as full relation. *)
11171133
else
1118-
Cluster.lock rel local_m (get_mutex_global_g_with_mutex_inits (not (LMust.mem lm lmust)) ask getg g)
1134+
Cluster.lock rel local_m (get_mutex_global_g_with_mutex_inits (fun c -> (not (LMust.mem (lm,c) lmust))) ask getg g)
11191135
in
11201136
(* write *)
11211137
let g_var = AV.global g in
@@ -1125,7 +1141,7 @@ struct
11251141
(* unlock *)
11261142
if not atomic then (
11271143
let rel_side = RD.keep_vars rel_local [g_var] in
1128-
let rel_side = Cluster.unlock (W.singleton g) rel_side in
1144+
let rel_side, clusters = Cluster.unlock (W.singleton g) rel_side in
11291145
let digest = Digest.current ask in
11301146
let sidev = GMutex.singleton digest rel_side in
11311147
if Param.handle_atomic then
@@ -1139,7 +1155,8 @@ struct
11391155
else
11401156
rel_local
11411157
in
1142-
{rel = rel_local'; priv = (W.add g w,LMust.add lm lmust,l')}
1158+
let lmust' = List.fold (fun a c -> LMust.add (lm,c) a) lmust clusters in
1159+
{rel = rel_local'; priv = (W.add g w,lmust',l')}
11431160
)
11441161
else
11451162
(* Delay publishing unprotected write in the atomic section. *)
@@ -1151,7 +1168,7 @@ struct
11511168
let rel = st.rel in
11521169
let _,lmust,l = st.priv in
11531170
let lm = LLock.mutex m in
1154-
let get_m = get_m_with_mutex_inits (not (LMust.mem lm lmust)) ask getg m in
1171+
let get_m = get_m_with_mutex_inits (fun c -> (not (LMust.mem (lm,c) lmust))) ask getg m in
11551172
let local_m = BatOption.default (LRD.bot ()) (L.find_opt lm l) in
11561173
(* Additionally filter get_m in case it contains variables it no longer protects. E.g. in 36/22. *)
11571174
let local_m = Cluster.keep_only_protected_globals ask m local_m in
@@ -1181,13 +1198,14 @@ struct
11811198
{rel = rel_local; priv = (w',lmust,l)}
11821199
else
11831200
let rel_side = keep_only_protected_globals ask m rel in
1184-
let rel_side = Cluster.unlock w rel_side in
1201+
let rel_side, clusters = Cluster.unlock w rel_side in
11851202
let digest = Digest.current ask in
11861203
let sidev = GMutex.singleton digest rel_side in
11871204
sideg (V.mutex m) (G.create_mutex sidev);
11881205
let lm = LLock.mutex m in
11891206
let l' = L.add lm rel_side l in
1190-
{rel = rel_local; priv = (w',LMust.add lm lmust,l')}
1207+
let lmust' = List.fold (fun a c -> LMust.add (lm,c) a) lmust clusters in
1208+
{rel = rel_local; priv = (w',lmust',l')}
11911209
)
11921210
else (
11931211
(* Publish delayed unprotected write as if it were protected by the atomic section. *)
@@ -1198,14 +1216,15 @@ struct
11981216
{rel = rel_local; priv = (w',lmust,l)}
11991217
else
12001218
let rel_side = keep_only_globals ask m rel in
1201-
let rel_side = Cluster.unlock w rel_side in
1219+
let rel_side, clusters = Cluster.unlock w rel_side in
12021220
let digest = Digest.current ask in
12031221
let sidev = GMutex.singleton digest rel_side in
12041222
(* Unprotected invariant is one big relation. *)
12051223
sideg (V.mutex atomic_mutex) (G.create_mutex sidev);
12061224
let (lmust', l') = W.fold (fun g (lmust, l) ->
12071225
let lm = LLock.global g in
1208-
(LMust.add lm lmust, L.add lm rel_side l)
1226+
let lmust'' = List.fold (fun a c -> LMust.add (lm,c) a) lmust clusters in
1227+
(lmust'', L.add lm rel_side l)
12091228
) w (lmust, l)
12101229
in
12111230
{rel = rel_local; priv = (w',lmust',l')}
@@ -1295,7 +1314,7 @@ struct
12951314
) (RD.vars rel)
12961315
in
12971316
let rel_side = RD.keep_vars rel g_vars in
1298-
let rel_side = Cluster.unlock (W.top ()) rel_side in (* top W to avoid any filtering *)
1317+
let rel_side, clusters = Cluster.unlock (W.top ()) rel_side in (* top W to avoid any filtering *)
12991318
let digest = Digest.current ask in
13001319
let sidev = GMutex.singleton digest rel_side in
13011320
sideg V.mutex_inits (G.create_mutex sidev);

src/analyses/basePriv.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ module PerMutexMeetTIDPriv (Digest: Digest): S =
499499
struct
500500
open Queries.Protection
501501
include PerMutexMeetPrivBase
502-
include PerMutexTidCommon (Digest) (CPA)
502+
include PerMutexTidCommonNC (Digest) (CPA)
503503

504504
let iter_sys_vars getg vq vf =
505505
match vq with

src/analyses/commonPriv.ml

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ struct
237237
| _ -> false
238238
end
239239

240-
module PerMutexTidCommon (Digest: Digest) (LD:Lattice.S) =
240+
module PerMutexTidCommon (Digest: Digest) (LD:Lattice.S) (Cluster:Printable.S) =
241241
struct
242242
include ConfCheck.RequireThreadFlagPathSensInit
243243

@@ -266,9 +266,9 @@ struct
266266
let global x = `Right x
267267
end
268268

269-
(** Mutexes / globals to which values have been published, i.e. for which the initializers need not be read **)
269+
(** Mutexes / clusters of globals to which values have been published, i.e., for which the initializers need not be read **)
270270
module LMust = struct
271-
include SetDomain.Reverse (SetDomain.ToppedSet (LLock) (struct let topname = "All locks" end))
271+
include SetDomain.Reverse (SetDomain.ToppedSet (Printable.Prod(LLock)(Cluster)) (struct let topname = "All locks" end))
272272
let name () = "LMust"
273273
end
274274

@@ -315,6 +315,14 @@ struct
315315
let startstate () = W.bot (), LMust.top (), L.bot ()
316316
end
317317

318+
module PerMutexTidCommonNC (Digest: Digest) (LD:Lattice.S) = struct
319+
include PerMutexTidCommon (Digest) (LD) (Printable.Unit)
320+
module LMust = struct
321+
include LMust
322+
let mem lm lmust = mem (lm, ()) lmust
323+
let add lm lmust = add (lm, ()) lmust
324+
end
325+
end
318326

319327
let lift_lock (ask: Q.ask) f st (addr: LockDomain.Addr.t) =
320328
(* Should be in sync with:
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// CRAM
2+
#include<pthread.h>
3+
int d, j, k;
4+
5+
pthread_mutex_t f;
6+
7+
void nothing() {};
8+
void nothing2() {};
9+
10+
int top() {
11+
int top2;
12+
return top2;
13+
}
14+
15+
void main() {
16+
d = top();
17+
if (d) {
18+
k = 1;
19+
pthread_t tid;
20+
pthread_create(&tid, 0, &nothing, NULL);
21+
pthread_mutex_lock(&f);
22+
j = 0; // To ensure something is published
23+
pthread_mutex_unlock(&f);
24+
pthread_mutex_lock(&f);
25+
26+
pthread_t tid2;
27+
pthread_create(&tid2, 0, &nothing2, NULL);
28+
float f = 8.0f;
29+
} else {
30+
pthread_t tid2;
31+
pthread_create(&tid2, 0, &nothing2, NULL);
32+
}
33+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
$ goblint --disable warn.unsound --disable warn.imprecise --disable sem.unknown_function.invalidate.globals --enable warn.deterministic --disable ana.dead-code.lines --disable warn.race --disable warn.behavior --set ana.activated[+] apron --set ana.path_sens[+] threadflag --set ana.relation.privatization mutex-meet-tid --enable witness.yaml.enabled --disable witness.invariant.other --disable witness.invariant.loop-head 98-issue-1511b.c --set witness.yaml.path 98-issue-1511b.yml
2+
[Info][Witness] witness generation summary:
3+
location invariants: 52
4+
loop invariants: 0
5+
flow-insensitive invariants: 2
6+
total generation entries: 29
7+
8+
$ goblint --disable warn.unsound --disable warn.imprecise --disable sem.unknown_function.invalidate.globals --enable warn.deterministic --disable ana.dead-code.lines --disable warn.race --disable warn.behavior --set ana.activated[+] apron --set ana.path_sens[+] threadflag --set ana.relation.privatization mutex-meet-tid-cluster12 --set witness.yaml.validate 98-issue-1511b.yml 98-issue-1511b.c
9+
[Warning][Witness] cannot validate entry of type flow_insensitive_invariant
10+
[Info][Witness] witness validation summary:
11+
confirmed: 52
12+
unconfirmed: 0
13+
refuted: 0
14+
error: 0
15+
unchecked: 0
16+
unsupported: 2
17+
disabled: 0
18+
total validation entries: 54
19+
[Success][Witness] invariant confirmed: (1LL + (long long )j) - (long long )k >= 0LL (98-issue-1511b.c:22:5)
20+
[Success][Witness] invariant confirmed: (1LL - (long long )j) - (long long )k >= 0LL (98-issue-1511b.c:22:5)
21+
[Success][Witness] invariant confirmed: (2147483646LL + (long long )j) + (long long )k >= 0LL (98-issue-1511b.c:22:5)
22+
[Success][Witness] invariant confirmed: (2147483646LL - (long long )d) + (long long )k >= 0LL (98-issue-1511b.c:22:5)
23+
[Success][Witness] invariant confirmed: (2147483646LL - (long long )j) + (long long )k >= 0LL (98-issue-1511b.c:22:5)
24+
[Success][Witness] invariant confirmed: (2147483647LL + (long long )d) + (long long )k >= 0LL (98-issue-1511b.c:22:5)
25+
[Success][Witness] invariant confirmed: (2147483647LL - (long long )d) + (long long )j >= 0LL (98-issue-1511b.c:22:5)
26+
[Success][Witness] invariant confirmed: (2147483647LL - (long long )d) - (long long )j >= 0LL (98-issue-1511b.c:22:5)
27+
[Success][Witness] invariant confirmed: (2147483648LL + (long long )d) + (long long )j >= 0LL (98-issue-1511b.c:22:5)
28+
[Success][Witness] invariant confirmed: (2147483648LL + (long long )d) - (long long )j >= 0LL (98-issue-1511b.c:22:5)
29+
[Success][Witness] invariant confirmed: (2147483648LL - (long long )d) - (long long )k >= 0LL (98-issue-1511b.c:22:5)
30+
[Success][Witness] invariant confirmed: (2147483649LL + (long long )d) - (long long )k >= 0LL (98-issue-1511b.c:22:5)
31+
[Success][Witness] invariant confirmed: j == 0 (98-issue-1511b.c:22:5)
32+
[Success][Witness] invariant confirmed: (1LL + (long long )j) - (long long )k >= 0LL (98-issue-1511b.c:27:5)
33+
[Success][Witness] invariant confirmed: (1LL - (long long )j) - (long long )k >= 0LL (98-issue-1511b.c:27:5)
34+
[Success][Witness] invariant confirmed: (2147483646LL + (long long )j) + (long long )k >= 0LL (98-issue-1511b.c:27:5)
35+
[Success][Witness] invariant confirmed: (2147483646LL - (long long )d) + (long long )k >= 0LL (98-issue-1511b.c:27:5)
36+
[Success][Witness] invariant confirmed: (2147483646LL - (long long )j) + (long long )k >= 0LL (98-issue-1511b.c:27:5)
37+
[Success][Witness] invariant confirmed: (2147483647LL + (long long )d) + (long long )k >= 0LL (98-issue-1511b.c:27:5)
38+
[Success][Witness] invariant confirmed: (2147483647LL - (long long )d) + (long long )j >= 0LL (98-issue-1511b.c:27:5)
39+
[Success][Witness] invariant confirmed: (2147483647LL - (long long )d) - (long long )j >= 0LL (98-issue-1511b.c:27:5)
40+
[Success][Witness] invariant confirmed: (2147483648LL + (long long )d) + (long long )j >= 0LL (98-issue-1511b.c:27:5)
41+
[Success][Witness] invariant confirmed: (2147483648LL + (long long )d) - (long long )j >= 0LL (98-issue-1511b.c:27:5)
42+
[Success][Witness] invariant confirmed: (2147483648LL - (long long )d) - (long long )k >= 0LL (98-issue-1511b.c:27:5)
43+
[Success][Witness] invariant confirmed: (2147483649LL + (long long )d) - (long long )k >= 0LL (98-issue-1511b.c:27:5)
44+
[Success][Witness] invariant confirmed: j == 0 (98-issue-1511b.c:27:5)

0 commit comments

Comments
 (0)