@@ -761,11 +761,15 @@ module type ClusterArg = functor (RD: RelationDomain.RD) ->
761761sig
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
771775end
@@ -775,6 +779,7 @@ module NoCluster:ClusterArg = functor (RD: RelationDomain.RD) ->
775779struct
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"
792803end
@@ -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
915931end
@@ -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')
9901012end
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);
0 commit comments