Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
(* emacs fontification -*-caml-*- *) (* --- Introduction --- This file contains a mathematical version of the relaxed memory model of C11 and C++11, written in the specification language of Lem. Lem can compile it to Ocaml, HOL, Isabelle or Latex. The basic model is faithful to the intent of the 2011 standard and included here in full. In addition, there are several simplified models that either remove redundant concepts or provide simplifications for programs that restrict the input language of programs. There are lots of definitions that make up the models. To help you navigate them, the following table of contents (with unique key phrases) can be used to search the document. Where appropriate, there are comments describing or explaining the definitions. These are especially important for the top-level definitions of the simplified models. --- Contents --- 1 - Relational definitions 2 - Action and location types - 2.1 - Projection functions - 2.2 - Location kinds 3 - The preferred model - 3.1 - Execution records - 3.2 - Well formed action - 3.3 - Well formed threads - 3.4 - Consistent locks - 3.5 - Well formed reads from mapping - 3.6 - Happens before - 3.7 - Consistent SC and modification orders - 3.8 - Visible side effects and VSSEs - 3.9 - Undefined behaviour - 3.10 - Consistent reads from mapping - 3.11 - Consistent execution - 3.12 - Preferred model top level judgement 4 - Standard C/C++ model - 4.1 - Standard model top level judgement 5 - Model with seperate lock order - 5.1 - Seperate lock order top level judgement 6 - Model with per-location lock orders - 6.1 - per-location lock order top level judgement 7 - Model with single step mutex synchronisation - 7.1 - single step mutex synchronisation top level judgement 8 - Model simplified for programs without consumes - 8.1 - No consume top level judgement 9 - Model simplified for programs without consumes or relaxed - 9.1 - No consume or relaxed top level judgement 10 - Model simplified for programs without consumes, relaxed, acquires or releases - 10.1 - No consume, relaxed, acquire or release top level judgement *) (*************************************************** *) (* 1 - Relational definitions *) (*************************************************** *) let irrefl s ord = forall (x IN s). not ((x,x) IN ord) let trans s ord = forall (x IN s) (y IN s) (z IN s). (((x,y) IN ord) && ((y,z) IN ord)) --> ((x,z) IN ord) let cross S T = { (s,t) | forall (s IN S) (t IN T) | true} indreln {isabelle} forall r x y. r (x, y) ==> tc' r (x, y) and forall r x y. (exist z. tc' r (x,z) && tc' r (z,y)) ==> tc' r (x,y) val tc : forall 'a. ('a * 'a) set -> ('a * 'a) set let {isabelle} tc r = let r' = fun (x,y) -> ((x,y) IN r) in { (x,y) | forall ((x,y) IN r) | tc' r' (x,y) } let rec {ocaml} tc r = let one_step = { (x,z) | forall ((x,y) IN r) ((y',z) IN r) | y = y' } in if one_step subset r then r else tc (one_step union r) sub [hol] tc = tc let restrict_relation_set rel s = (rel) inter (cross s s) let strict_preorder s ord = irrefl s (ord) && trans s (ord) let relation_over s rel = forall ((a,b) IN rel). a IN s && b IN s let inj_on f A = (forall (x IN A). (forall (y IN A). (f x = f y) --> (x = y))) let total_order_over s ord = relation_over s ord && (forall (x IN s) (y IN s). (x,y) IN ord || (y,x) IN ord || (x = y)) let strict_total_order_over s ord = strict_preorder s ord && total_order_over s ord let adjacent_less_than ord s x y = (x,y) IN ord && not (exist (z IN s). (x,z) IN ord && (z,y) IN ord) let adjacent_less_than_such_that pred ord s x y = pred x && (x,y) IN ord && not (exist (z IN s). pred z && (x,z) IN ord && (z,y) IN ord) (*************************************************** *) (* 2 - Action and location types *) (*************************************************** *) type action_id = num type thread_id = num type location = num type value = num type program = num type memory_order = Mo_seq_cst | Mo_relaxed | Mo_release | Mo_acquire | Mo_consume | Mo_acq_rel type lock_outcome = Success | Blocked type action = | Lock of action_id * thread_id * location * lock_outcome | Unlock of action_id * thread_id * location | Atomic_load of action_id * thread_id * memory_order * location * value | Atomic_store of action_id * thread_id * memory_order * location * value | Atomic_rmw of action_id * thread_id * memory_order * location * value * value | Load of action_id * thread_id * location * value | Store of action_id * thread_id * location * value | Fence of action_id * thread_id * memory_order | Blocked_rmw of action_id * thread_id * location (*************************************************** *) (* - 2.1 - Projection functions *) (*************************************************** *) let action_id_of a = match a with | Lock aid _ _ _ -> aid | Unlock aid _ _ -> aid | Atomic_load aid _ _ _ _ -> aid | Atomic_store aid _ _ _ _ -> aid | Atomic_rmw aid _ _ _ _ _ -> aid | Load aid _ _ _ -> aid | Store aid _ _ _ -> aid | Fence aid _ _ -> aid | Blocked_rmw aid _ _ -> aid end let thread_id_of a = match a with Lock _ tid _ _ -> tid | Unlock _ tid _ -> tid | Atomic_load _ tid _ _ _ -> tid | Atomic_store _ tid _ _ _ -> tid | Atomic_rmw _ tid _ _ _ _ -> tid | Load _ tid _ _ -> tid | Store _ tid _ _ -> tid | Fence _ tid _ -> tid | Blocked_rmw _ tid _ -> tid end let memory_order_of a = match a with Atomic_load _ _ mo _ _ -> Some mo | Atomic_store _ _ mo _ _ -> Some mo | Atomic_rmw _ _ mo _ _ _ -> Some mo | Fence _ _ mo -> Some mo | _ -> None end let location_of a = match a with Lock _ _ l _ -> Some l | Unlock _ _ l -> Some l | Atomic_load _ _ _ l _ -> Some l | Atomic_store _ _ _ l _ -> Some l | Atomic_rmw _ _ _ l _ _ -> Some l | Load _ _ l _ -> Some l | Store _ _ l _ -> Some l | Fence _ _ _ -> None | Blocked_rmw _ _ l -> Some l end let value_read_by a = match a with Atomic_load _ _ _ _ v -> Some v | Atomic_rmw _ _ _ _ v _ -> Some v | Load _ _ _ v -> Some v | _ -> None end let value_written_by a = match a with Atomic_store _ _ _ _ v -> Some v | Atomic_rmw _ _ _ _ _ v -> Some v | Store _ _ _ v -> Some v | _ -> None end let is_lock a = match a with Lock _ _ _ _ -> true | _ -> false end let is_successful_lock a = match a with Lock _ _ _ Success -> true | _ -> false end let is_blocked_lock a = match a with Lock _ _ _ Blocked -> true | _ -> false end let is_unlock a = match a with Unlock _ _ _ -> true | _ -> false end let is_atomic_load a = match a with Atomic_load _ _ _ _ _ -> true | _ -> false end let is_atomic_store a = match a with Atomic_store _ _ _ _ _ -> true | _ -> false end let is_atomic_rmw a = match a with Atomic_rmw _ _ _ _ _ _ -> true | _ -> false end let is_blocked_rmw a = match a with Blocked_rmw _ _ _ -> true | _ -> false end let is_load a = match a with Load _ _ _ _ -> true | _ -> false end let is_store a = match a with Store _ _ _ _ -> true | _ -> false end let is_fence a = match a with Fence _ _ _ -> true | _ -> false end let is_atomic_action a = is_atomic_load a || is_atomic_store a || is_atomic_rmw a let is_read a = is_load a || is_atomic_load a || is_atomic_rmw a let is_write a = is_store a || is_atomic_store a || is_atomic_rmw a (* It is important to note that seq_cst atomics are both acquires and releases *) let is_acquire a = match memory_order_of a with Some Mo_acquire -> is_read a || is_fence a | Some Mo_acq_rel -> is_read a || is_fence a | Some Mo_seq_cst -> is_read a || is_fence a | Some Mo_consume -> is_fence a | None -> is_lock a | _ -> false end let is_consume a = is_read a && (memory_order_of a = Some Mo_consume) let is_release a = match memory_order_of a with Some Mo_release -> is_write a || is_fence a | Some Mo_acq_rel -> is_write a || is_fence a | Some Mo_seq_cst -> is_write a || is_fence a | None -> is_unlock a | _ -> false end let is_seq_cst a = (memory_order_of a = Some Mo_seq_cst) (**************************************** *) (* - 2.2 - Location kinds *) (**************************************** *) type location_kind = Mutex | Non_atomic | Atomic let actions_respect_location_kinds actions lk = forall (a IN actions). match location_of a with Some l -> match lk l with Mutex -> is_lock a || is_unlock a | Non_atomic -> is_load a || is_store a | Atomic -> is_store a || is_atomic_action a || is_blocked_rmw a end | None -> true end let is_at_location_kind lk a lk0 = match location_of a with Some l -> (lk l = lk0) | None -> false end let is_at_mutex_location lk a = is_at_location_kind lk a Mutex let is_at_non_atomic_location lk a = is_at_location_kind lk a Non_atomic let is_at_atomic_location lk a = is_at_location_kind lk a Atomic (**************************************** *) (* 3 - The preferred model *) (**************************************** *) (* This simplification has ben verified equivalent to the Standard's model (section 4) using the HOL theorem prover. It removes the complicated notion of VSSE's, whose force is covered by the coherence requirements. For those looking to work with C or C++ concurrency, this is the preferred model. Predicates from this model will be used in those that follow. *) (*********************************************** *) (* - 3.1 - Execution records *) (*********************************************** *) type opsem_execution_part = <| actions : action set; threads : thread_id set; lk : location -> location_kind; sb : (action * action) set; asw : (action * action) set; dd : (action * action) set; cd : (action * action) set; |> type witness_execution_part = <| rf : (action * action) set; mo : (action * action) set; sc : (action * action) set; |> (**************************************** *) (* - 3.2 - Well formed action *) (**************************************** *) let same_thread a b = (thread_id_of a = thread_id_of b) let threadwise_relation_over s rel = relation_over s rel && (forall (x IN rel). same_thread (fst x) (snd x)) let same_location a b = (location_of a = location_of b) let locations_of actions = { l | forall (Some l IN { (location_of a) | forall (a IN actions) | true }) | true} let well_formed_action a = match a with Atomic_load _ _ mem_ord _ _ -> mem_ord = Mo_relaxed || mem_ord = Mo_acquire || mem_ord = Mo_seq_cst || mem_ord = Mo_consume | Atomic_store _ _ mem_ord _ _ -> mem_ord = Mo_relaxed || mem_ord = Mo_release || mem_ord = Mo_seq_cst | Atomic_rmw _ _ mem_ord _ _ _ -> mem_ord = Mo_relaxed || mem_ord = Mo_release || mem_ord = Mo_acquire || mem_ord = Mo_acq_rel || mem_ord = Mo_seq_cst || mem_ord = Mo_consume | _ -> true end (*********************************************** *) (* - 3.3 - Well formed threads *) (*********************************************** *) let well_formed_threads actions threads lk sb asw dd cd = inj_on action_id_of (actions) && (forall (a IN actions). well_formed_action a) && threadwise_relation_over actions sb && threadwise_relation_over actions dd && threadwise_relation_over actions cd && strict_preorder actions sb && strict_preorder actions dd && strict_preorder actions cd && (forall (a IN actions). thread_id_of a IN threads) && actions_respect_location_kinds actions lk && dd subset sb && relation_over actions asw && (forall (a IN actions). (is_blocked_rmw a || is_blocked_lock a) --> not (exist (b IN actions). (a,b) IN sb)) (*********************************************** *) (* - 3.4 - Consistent locks *) (*********************************************** *) let consistent_locks actions lo hb = let mutex_actions = {a | forall (a IN actions) | (is_lock a || is_unlock a)} in let lo_happens_before = restrict_relation_set hb mutex_actions in strict_total_order_over mutex_actions lo && lo_happens_before subset lo && (forall ((a,c) IN lo). is_successful_lock a && is_successful_lock c && same_location a c --> (exist (b IN actions). same_location a b && is_unlock b && (a,b) IN lo && (b,c) IN lo)) (*********************************************** *) (* - 3.5 - Well formed reads from mapping *) (*********************************************** *) let well_formed_reads_from_mapping actions lk rf = relation_over actions rf && ( forall (a1 IN actions) (a2 IN actions) (b IN actions). ((a1,b) IN rf && (a2,b) IN rf) --> (a1 = a2) ) && ( forall (a IN actions) (b IN actions). (a,b) IN rf --> same_location a b && ( value_read_by b = value_written_by a ) && not (a = b) && not (is_fence a) && not (is_fence b) && ( is_at_mutex_location lk a --> false ) && ( is_at_non_atomic_location lk a --> is_store a && is_load b ) && ( is_at_atomic_location lk a --> (is_atomic_store a || is_atomic_rmw a || is_store a) && (is_atomic_load b || is_atomic_rmw b || is_load b) ) ) (*********************************************** *) (* - 3.6 - Happens before *) (*********************************************** *) let rs_element rs_head a = same_thread a rs_head || is_atomic_rmw a let release_sequence actions lk mo a_rel b = is_at_atomic_location lk b && is_release a_rel && ( (b = a_rel) || ( rs_element a_rel b && (a_rel,b) IN mo && (forall (c IN actions). ((a_rel,c) IN mo && (c,b) IN mo) --> rs_element a_rel c) ) ) let release_sequence_set actions lk mo = { (a,b) | forall (a IN actions) (b IN actions) | release_sequence actions lk mo a b} let hypothetical_release_sequence actions lk mo a b = is_at_atomic_location lk b && ( (b = a) || ( rs_element a b && (a,b) IN mo && (forall (c IN actions). ((a,c) IN mo && (c,b) IN mo) --> rs_element a c) ) ) let hypothetical_release_sequence_set actions lk mo = { (a,b) | forall (a IN actions) (b IN actions) | hypothetical_release_sequence actions lk mo a b} let synchronizes_with actions sb asw rf lo rs hrs a b = (* thread sync *) (a,b) IN asw || ( same_location a b && a IN actions && b IN actions && ( (* mutex sync *) (is_unlock a && is_successful_lock b && (a,b) IN lo) || (* rel/acq sync *) ( is_release a && is_acquire b && not (same_thread a b) && (exist (c IN actions). (a,c) IN rs && (c,b) IN rf ) ) || (* fence sync *) ( not (same_thread a b) && is_fence a && is_release a && is_fence b && is_acquire b && ( exist (x IN actions) (y IN actions). same_location x y && is_atomic_action x && is_atomic_action y && is_write x && (a,x) IN sb && (y,b) IN sb && ( exist (z IN actions). (x,z) IN hrs && (z,y) IN rf) ) ) || ( not (same_thread a b) && is_fence a && is_release a && is_atomic_action b && is_acquire b && ( exist (x IN actions). same_location x b && is_atomic_action x && is_write x && (a,x) IN sb && ( exist (z IN actions). (x,z) IN hrs && (z,b) IN rf ) ) ) || ( not (same_thread a b) && is_atomic_action a && is_release a && is_fence b && is_acquire b && ( exist (x IN actions). same_location a x && is_atomic_action x && (x,b) IN sb && ( exist (z IN actions). (a,z) IN rs && (z,x) IN rf ) ) ) ) ) let synchronizes_with_set actions sb asw rf lo rs hrs = { (a,b) | forall (a IN actions) (b IN actions) | synchronizes_with actions sb asw rf lo rs hrs a b} let carries_a_dependency_to_set actions sb dd rf = tc ( (rf inter sb) union dd ) let dependency_ordered_before actions rf rs cad a d = a IN actions && d IN actions && ( exist (b IN actions). is_release a && is_consume b && (exist (e IN actions). (a,e) IN rs && (e,b) IN rf) && ( (b,d) IN cad || (b = d) ) ) let dependency_ordered_before_set actions rf rs cad = { (a,b) | forall (a IN actions) (b IN actions) | dependency_ordered_before actions rf rs cad a b} let compose R1 R2 = { (w,z) | forall ((w,x) IN R1) ((y,z) IN R2) | (x = y) } let inter_thread_happens_before actions sb sw dob = let r = sw union dob union (compose sw sb) in tc (r union (compose sb r)) let consistent_inter_thread_happens_before actions ithb = irrefl actions ithb let happens_before actions sb ithb = sb union ithb (*********************************************** *) (* - 3.7 - Consistent SC and modification orders *) (*********************************************** *) let all_sc_actions actions = {a | forall (a IN actions) | is_seq_cst a || is_lock a || is_unlock a} let consistent_sc_order actions mo sc hb = let sc_happens_before = restrict_relation_set hb (all_sc_actions actions) in let sc_mod_order = restrict_relation_set mo (all_sc_actions actions) in strict_total_order_over (all_sc_actions actions) sc && sc_happens_before subset sc && sc_mod_order subset sc let consistent_modification_order actions lk sb mo hb = (forall (a IN actions) (b IN actions). (a,b) IN mo --> (same_location a b && is_write a && is_write b)) && ( forall (l IN locations_of actions). match lk l with Atomic -> ( let actions_at_l = {a | forall (a IN actions) | location_of a = Some l} in let writes_at_l = {a | forall (a IN actions_at_l) | is_write a} in strict_total_order_over writes_at_l (restrict_relation_set mo actions_at_l) && (* hb is a subset of mo at l *) restrict_relation_set hb writes_at_l subset mo ) | _ -> ( let actions_at_l = {a | forall (a IN actions) | location_of a = Some l} in Set.is_empty (restrict_relation_set mo actions_at_l) ) end ) (*********************************************** *) (* - 3.8 - Visible side effects *) (*********************************************** *) let visible_side_effect actions hb a b = (a,b) IN hb && is_write a && is_read b && same_location a b && not ( exist (c IN actions). not (c = a) && not (c = b) && is_write c && same_location c b && (a,c) IN hb && (c,b) IN hb) let visible_side_effect_set actions sb hb = { (a,b) | forall ((a,b) IN hb) | visible_side_effect actions hb a b} (*********************************************** *) (* - 3.9 - Undefined behaviour *) (*********************************************** *) let indeterminate_reads actions rf = {b | forall (b IN actions) | is_read b && not (exist (a IN actions). (a,b) IN rf)} let unsequenced_races actions sb = { (a,b) | forall (a IN actions) (b IN actions) | not (a = b) && same_location a b && (is_write a || is_write b) && same_thread a b && not ((a,b) IN sb || (b,a) IN sb) } let data_races actions hb = { (a,b) | forall (a IN actions) (b IN actions) | not (a = b) && same_location a b && (is_write a || is_write b) && not (same_thread a b) && not (is_atomic_action a && is_atomic_action b) && not ((a,b) IN hb || (b,a) IN hb) } let data_races' Xo Xw lo = let rs = release_sequence_set Xo.actions Xo.lk Xw.mo in let hrs = hypothetical_release_sequence_set Xo.actions Xo.lk Xw.mo in let sw = synchronizes_with_set Xo.actions Xo.sb Xo.asw Xw.rf lo rs hrs in let cad = carries_a_dependency_to_set Xo.actions Xo.sb Xo.dd Xw.rf in let dob = dependency_ordered_before_set Xo.actions Xw.rf rs cad in let ithb = inter_thread_happens_before Xo.actions Xo.sb sw dob in let hb = happens_before Xo.actions Xo.sb ithb in data_races Xo.actions hb let good_mutex_use actions lk sb lo a = let mutexes_at_l = {a' | forall (a' IN actions) | (is_successful_lock a' || is_unlock a') && (location_of a' = location_of a)} in let lock_order = restrict_relation_set lo mutexes_at_l in (* violated requirement: The calling thread shall own the mutex. *) ( is_unlock a --> ( exist (al IN actions). is_successful_lock al && (location_of al = location_of a) && (al,a) IN sb && adjacent_less_than lock_order actions al a ) ) && (* violated requirement: The calling thread does not own the mutex. *) ( is_lock a --> not ( exist (al IN actions). is_successful_lock al && (location_of a = location_of al) && same_thread a al && adjacent_less_than lock_order actions al a ) ) let bad_mutexes Xo lo = { a | forall (a IN Xo.actions) | not (good_mutex_use Xo.actions Xo.lk Xo.sb lo a)} let undefined_behaviour Xo Xw = not (data_races' Xo Xw Xw.sc = {}) || not (unsequenced_races Xo.actions Xo.sb = {}) || not (indeterminate_reads Xo.actions Xw.rf = {}) || not (bad_mutexes Xo Xw.sc = {}) (*********************************************** *) (* - 3.9 - Consistent reads from mapping *) (*********************************************** *) let consistent_non_atomic_read_values actions lk rf vse = forall (b IN actions). (is_read b && is_at_non_atomic_location lk b) --> ( if (exist (a_vse IN actions). (a_vse,b) IN vse) then (exist (a_vse IN actions). (a_vse,b) IN vse && (a_vse,b) IN rf) else not (exist (a IN actions). (a,b) IN rf) ) let coherent_memory_use actions lk rf mo hb = (* CoRR *) ( forall ((x,a) IN rf) ((y,b) IN rf). ((a,b) IN hb && same_location a b && is_at_atomic_location lk b) --> ((x = y) || (x,y) IN mo) ) && (* CoWR *) ( forall ((a,b) IN hb) (c IN actions). ((c,b) IN rf && is_write a && same_location a b && is_at_atomic_location lk b) --> ((c = a) || (a,c) IN mo) ) && (* CoRW *) ( forall ((a,b) IN hb) (c IN actions). ((c,a) IN rf && is_write b && same_location a b && is_at_atomic_location lk a) --> ((c,b) IN mo) ) let rmw_atomicity actions rf mo = forall ((a,b) IN rf). is_atomic_rmw b --> adjacent_less_than mo actions a b let sc_reads_restricted actions rf sc mo hb = forall ((a,b) IN rf). is_seq_cst b --> ( adjacent_less_than_such_that (fun c -> is_write c && same_location b c) sc actions a b ) || ( not (is_seq_cst a) && ( forall (x IN actions). (adjacent_less_than_such_that (fun c -> is_write c && same_location b c) sc actions x b) --> not ((a,x) IN hb) ) ) let sc_fences_heeded actions sb rf sc mo = (* fence restriction N3291 29.3p4 *) ( forall (a IN actions) ((x,b) IN sb) (y IN actions). ( is_write a && is_fence x && adjacent_less_than sc actions a x && is_atomic_action b && same_location a b && (y,b) IN rf) --> ((y = a) || (a,y) IN mo) ) && (* fence restriction N3291 29.3p5 *) ( forall ((a,x) IN sb) ((y,b) IN rf). ((is_atomic_action a && is_write a && is_fence x && is_atomic_action b && (x,b) IN sc && same_location a b) --> ((y = a) || (a,y) IN mo) ) ) && (* fence restriction N3291 29.3p6 *) ( forall ((a,x) IN sb) ((y,b) IN sb) (z IN actions). ( is_atomic_action a && is_write a && is_fence x && is_fence y && (x,y) IN sc && is_atomic_action b && same_location a b && (z,b) IN rf) --> ((z = a) || (a,z) IN mo) ) && (* SC fences impose mo N3291 29.3p7 *) ( forall ((a,x) IN sb) ((y,b) IN sb). ( is_atomic_action a && is_write a && is_atomic_action b && is_write b && is_fence x && is_fence y && (x,y) IN sc && same_location a b --> (a,b) IN mo) ) && (* SC fences impose mo N3291 29.3p7, w collapsed first write*) ( forall (a IN actions) ((y,b) IN sb). ( is_atomic_action a && is_write a && is_fence y && (a,y) IN sc && is_atomic_action b && is_write b && same_location a b --> (a,b) IN mo) ) && (* SC fences impose mo N3291 29.3p7, w collapsed second write*) ( forall ((a,x) IN sb) (b IN actions). ( is_atomic_action a && is_write a && is_fence x && is_atomic_action b && is_write b && (x,b) IN sc && same_location a b --> (a,b) IN mo) ) let no_vsse_consistent_atomic_read_values actions lk rf hb vse = forall (b IN actions). (is_read b && is_at_atomic_location lk b) --> ( if (exist (a_vse IN actions). (a_vse,b) IN vse) then (exist (a IN actions). ((a,b) IN rf) && not ((b,a) IN hb)) else not (exist (a IN actions). (a,b) IN rf) ) let no_vsse_consistent_reads_from_mapping actions lk sb rf sc mo hb vse = consistent_non_atomic_read_values actions lk rf vse && no_vsse_consistent_atomic_read_values actions lk rf hb vse && coherent_memory_use actions lk rf mo hb && rmw_atomicity actions rf mo && sc_reads_restricted actions rf sc mo hb && sc_fences_heeded actions sb rf sc mo (*********************************************** *) (* 3.11 - Consistent execution *) (*********************************************** *) (* This simplification has ben verified equivalent to the model in section 3 using the HOL theorem prover. It removes the complicated notion of VSSE's, whose force is covered by the coherence requirements. For those looking to work with C or C++ concurrency, this is the preferred model. *) let no_vsse_consistent_execution Xo Xw = well_formed_threads Xo.actions Xo.threads Xo.lk Xo.sb Xo.asw Xo.dd Xo.cd && ( let rs = release_sequence_set Xo.actions Xo.lk Xw.mo in let hrs = hypothetical_release_sequence_set Xo.actions Xo.lk Xw.mo in let sw = synchronizes_with_set Xo.actions Xo.sb Xo.asw Xw.rf Xw.sc rs hrs in let cad = carries_a_dependency_to_set Xo.actions Xo.sb Xo.dd Xw.rf in let dob = dependency_ordered_before_set Xo.actions Xw.rf rs cad in let ithb = inter_thread_happens_before Xo.actions Xo.sb sw dob in let hb = happens_before Xo.actions Xo.sb ithb in let vse = visible_side_effect_set Xo.actions Xo.sb hb in consistent_locks Xo.actions Xw.sc hb && consistent_inter_thread_happens_before Xo.actions ithb && consistent_sc_order Xo.actions Xw.mo Xw.sc hb && consistent_modification_order Xo.actions Xo.lk Xo.sb Xw.mo hb && well_formed_reads_from_mapping Xo.actions Xo.lk Xw.rf && no_vsse_consistent_reads_from_mapping Xo.actions Xo.lk Xo.sb Xw.rf Xw.sc Xw.mo hb vse) (*********************************************** *) (* - 3.12 - Preferred model top level judgement *) (*********************************************** *) let {hol; isabelle; coq; tex} no_vsse_cmm opsem (p : program) = let pre_executions = { (Xopsem,Xwitness) | opsem p Xopsem && no_vsse_consistent_execution Xopsem Xwitness} in if exist ((Xo,Xw) IN pre_executions). undefined_behaviour Xo Xw then { (Xo,Xw) | true } else pre_executions (*********************************************** *) (* 4 - Standard C/C++ model *) (*********************************************** *) (* The following definitions make up the memory model described by the 2011 standard. It was constructed in discussion with the standardisation comittee. *) let visible_sequence_of_side_effects_tail actions mo hb vsse_head b = { c | forall (c IN actions) | (vsse_head,c) IN mo && not ((b,c) IN hb) && ( forall (a IN actions). ((vsse_head,a) IN mo && (a,c) IN mo) --> not ((b,a) IN hb) ) } (* visible sequences of side effects have been proven redundant. See the simpler model in section 3. *) let visible_sequence_of_side_effects actions lk mo hb vsse_head b = (b , if is_at_atomic_location lk b then {vsse_head} union visible_sequence_of_side_effects_tail actions mo hb vsse_head b else {}) let visible_sequences_of_side_effects_set actions lk mo hb vse = { visible_sequence_of_side_effects actions lk mo hb vsse_head b | forall (vsse_head IN actions) (b IN actions) | is_at_atomic_location lk b && is_read b && ((vsse_head,b) IN vse) } let consistent_atomic_read_values actions lk rf vsses = forall (b IN actions). (is_read b && is_at_atomic_location lk b) --> ( if (exist ((b',v) IN vsses). b = b') then ( exist ((b',v) IN vsses). b = b' && (exist (c IN v). (c,b) IN rf) ) else not (exist (a IN actions). (a,b) IN rf) ) let consistent_reads_from_mapping actions lk sb rf sc mo hb vse vsses = consistent_non_atomic_read_values actions lk rf vse && consistent_atomic_read_values actions lk rf vsses && coherent_memory_use actions lk rf mo hb && rmw_atomicity actions rf mo && sc_reads_restricted actions rf sc mo hb && sc_fences_heeded actions sb rf sc mo let consistent_execution Xo Xw = well_formed_threads Xo.actions Xo.threads Xo.lk Xo.sb Xo.asw Xo.dd Xo.cd && ( let rs = release_sequence_set Xo.actions Xo.lk Xw.mo in let hrs = hypothetical_release_sequence_set Xo.actions Xo.lk Xw.mo in let sw = synchronizes_with_set Xo.actions Xo.sb Xo.asw Xw.rf Xw.sc rs hrs in let cad = carries_a_dependency_to_set Xo.actions Xo.sb Xo.dd Xw.rf in let dob = dependency_ordered_before_set Xo.actions Xw.rf rs cad in let ithb = inter_thread_happens_before Xo.actions Xo.sb sw dob in let hb = happens_before Xo.actions Xo.sb ithb in let vse = visible_side_effect_set Xo.actions Xo.sb hb in let vsses = visible_sequences_of_side_effects_set Xo.actions Xo.lk Xw.mo hb vse in consistent_locks Xo.actions Xw.sc hb && consistent_inter_thread_happens_before Xo.actions ithb && consistent_sc_order Xo.actions Xw.mo Xw.sc hb && consistent_modification_order Xo.actions Xo.lk Xo.sb Xw.mo hb && well_formed_reads_from_mapping Xo.actions Xo.lk Xw.rf && consistent_reads_from_mapping Xo.actions Xo.lk Xo.sb Xw.rf Xw.sc Xw.mo hb vse vsses) (*********************************************** *) (* - 4.1 - Standard model top level judgement *) (*********************************************** *) let {hol; isabelle; coq; tex} cmm opsem (p : program) = let pre_executions = { (Xopsem,Xwitness) | opsem p Xopsem && consistent_execution Xopsem Xwitness} in if exist ((Xo,Xw) IN pre_executions). undefined_behaviour Xo Xw then { (Xo,Xw) | true } else pre_executions (*********************************************** *) (* 5 - Model with seperate lock order *) (*********************************************** *) (* A version of the no VSSE model with a seperate lock order. *) let no_vsse_seperate_lo_consistent_execution Xo Xw lo = well_formed_threads Xo.actions Xo.threads Xo.lk Xo.sb Xo.asw Xo.dd Xo.cd && ( let rs = release_sequence_set Xo.actions Xo.lk Xw.mo in let hrs = hypothetical_release_sequence_set Xo.actions Xo.lk Xw.mo in let sw = synchronizes_with_set Xo.actions Xo.sb Xo.asw Xw.rf lo rs hrs in let cad = carries_a_dependency_to_set Xo.actions Xo.sb Xo.dd Xw.rf in let dob = dependency_ordered_before_set Xo.actions Xw.rf rs cad in let ithb = inter_thread_happens_before Xo.actions Xo.sb sw dob in let hb = happens_before Xo.actions Xo.sb ithb in let vse = visible_side_effect_set Xo.actions Xo.sb hb in consistent_locks Xo.actions lo hb && consistent_inter_thread_happens_before Xo.actions ithb && consistent_sc_order Xo.actions Xw.mo Xw.sc hb && consistent_modification_order Xo.actions Xo.lk Xo.sb Xw.mo hb && well_formed_reads_from_mapping Xo.actions Xo.lk Xw.rf && no_vsse_consistent_reads_from_mapping Xo.actions Xo.lk Xo.sb Xw.rf Xw.sc Xw.mo hb vse) let no_vsse_seperate_lo_undefined_behaviour Xo Xw lo = not (data_races' Xo Xw lo = {}) || not (unsequenced_races Xo.actions Xo.sb = {}) || not (indeterminate_reads Xo.actions Xw.rf = {}) || not (bad_mutexes Xo lo = {}) (*********************************************** *) (* - 5.1 - Seperate lock order top level judgement *) (*********************************************** *) let {hol; isabelle; coq; tex} no_vsse_seperate_lo_cmm opsem (p : program) = let pre_executions = { (Xopsem,(Xwitness,lo)) | opsem p Xopsem && no_vsse_seperate_lo_consistent_execution Xopsem Xwitness lo} in if exist ((Xo,(Xw,lo)) IN pre_executions). no_vsse_seperate_lo_undefined_behaviour Xo Xw lo then { (Xo,(Xw,lo)) | true } else pre_executions (*********************************************** *) (* 6 - Model with per-location lock orders *) (*********************************************** *) (* This model uses per location lock orders rather than one shared one. *) let multi_lo_consistent_locks actions lk lo hb = let mutex_actions = {a | forall (a IN actions) | (is_lock a || is_unlock a)} in let lo_happens_before = restrict_relation_set hb mutex_actions in lo_happens_before subset lo && (forall ((a,c) IN lo). is_successful_lock a && is_successful_lock c && same_location a c --> (exist (b IN actions). same_location a b && is_unlock b && (a,b) IN lo && (b,c) IN lo)) && forall (l IN locations_of actions). let actions_at_l = {a | forall (a IN actions) | location_of a = Some l} in match lk l with Mutex -> strict_total_order_over actions_at_l (restrict_relation_set lo actions_at_l) | _ -> Set.is_empty (restrict_relation_set lo actions_at_l) end let no_vsse_multi_lo_consistent_execution Xo Xw lo = well_formed_threads Xo.actions Xo.threads Xo.lk Xo.sb Xo.asw Xo.dd Xo.cd && ( let rs = release_sequence_set Xo.actions Xo.lk Xw.mo in let hrs = hypothetical_release_sequence_set Xo.actions Xo.lk Xw.mo in let sw = synchronizes_with_set Xo.actions Xo.sb Xo.asw Xw.rf lo rs hrs in let cad = carries_a_dependency_to_set Xo.actions Xo.sb Xo.dd Xw.rf in let dob = dependency_ordered_before_set Xo.actions Xw.rf rs cad in let ithb = inter_thread_happens_before Xo.actions Xo.sb sw dob in let hb = happens_before Xo.actions Xo.sb ithb in let vse = visible_side_effect_set Xo.actions Xo.sb hb in multi_lo_consistent_locks Xo.actions Xo.lk lo hb && consistent_inter_thread_happens_before Xo.actions ithb && consistent_sc_order Xo.actions Xw.mo Xw.sc hb && consistent_modification_order Xo.actions Xo.lk Xo.sb Xw.mo hb && well_formed_reads_from_mapping Xo.actions Xo.lk Xw.rf && no_vsse_consistent_reads_from_mapping Xo.actions Xo.lk Xo.sb Xw.rf Xw.sc Xw.mo hb vse) (*********************************************** *) (* - 6.1 - per-location lock order top level judgement *) (*********************************************** *) let {hol; isabelle; coq; tex} no_vsse_multi_lo_cmm opsem (p : program) = let pre_executions = { (Xopsem,(Xwitness,lo)) | opsem p Xopsem && no_vsse_multi_lo_consistent_execution Xopsem Xwitness lo} in if exist ((Xo,(Xw,lo)) IN pre_executions). no_vsse_seperate_lo_undefined_behaviour Xo Xw lo then { (Xo,(Xw,lo)) | true } else pre_executions (*********************************************** *) (* 7 - Model with single step mutex synchronisation *) (*********************************************** *) (* This model creates synchronizes-with edges from each unlock to the next lock at the same location, rather than all subsequent ones. *) let lo_single_synchronizes_with actions sb asw rf lo rs hrs a b = (* thread sync *) (a,b) IN asw || ( same_location a b && a IN actions && b IN actions && ( (* mutex sync *) (is_unlock a && is_successful_lock b && (a,b) IN lo && not (exist (c IN actions). (a,c) IN lo && (c,b) IN lo)) || (* rel/acq sync *) ( is_release a && is_acquire b && not (same_thread a b) && (exist (c IN actions). (a,c) IN rs && (c,b) IN rf ) ) || (* fence sync *) ( not (same_thread a b) && is_fence a && is_release a && is_fence b && is_acquire b && ( exist (x IN actions) (y IN actions). same_location x y && is_atomic_action x && is_atomic_action y && is_write x && (a,x) IN sb && (y,b) IN sb && ( exist (z IN actions). (x,z) IN hrs && (z,y) IN rf) ) ) || ( not (same_thread a b) && is_fence a && is_release a && is_atomic_action b && is_acquire b && ( exist (x IN actions). same_location x b && is_atomic_action x && is_write x && (a,x) IN sb && ( exist (z IN actions). (x,z) IN hrs && (z,b) IN rf ) ) ) || ( not (same_thread a b) && is_atomic_action a && is_release a && is_fence b && is_acquire b && ( exist (x IN actions). same_location a x && is_atomic_action x && (x,b) IN sb && ( exist (z IN actions). (a,z) IN rs && (z,x) IN rf ) ) ) ) ) let lo_single_synchronizes_with_set actions sb asw rf lo rs hrs = { (a,b) | forall (a IN actions) (b IN actions) | lo_single_synchronizes_with actions sb asw rf lo rs hrs a b} let no_vsse_multi_lo_single_sw_consistent_execution Xo Xw lo = well_formed_threads Xo.actions Xo.threads Xo.lk Xo.sb Xo.asw Xo.dd Xo.cd && ( let rs = release_sequence_set Xo.actions Xo.lk Xw.mo in let hrs = hypothetical_release_sequence_set Xo.actions Xo.lk Xw.mo in let sw = lo_single_synchronizes_with_set Xo.actions Xo.sb Xo.asw Xw.rf lo rs hrs in let cad = carries_a_dependency_to_set Xo.actions Xo.sb Xo.dd Xw.rf in let dob = dependency_ordered_before_set Xo.actions Xw.rf rs cad in let ithb = inter_thread_happens_before Xo.actions Xo.sb sw dob in let hb = happens_before Xo.actions Xo.sb ithb in let vse = visible_side_effect_set Xo.actions Xo.sb hb in multi_lo_consistent_locks Xo.actions Xo.lk lo hb && consistent_inter_thread_happens_before Xo.actions ithb && consistent_sc_order Xo.actions Xw.mo Xw.sc hb && consistent_modification_order Xo.actions Xo.lk Xo.sb Xw.mo hb && well_formed_reads_from_mapping Xo.actions Xo.lk Xw.rf && no_vsse_consistent_reads_from_mapping Xo.actions Xo.lk Xo.sb Xw.rf Xw.sc Xw.mo hb vse) let los_single_sw_data_races' Xo Xw lo = let rs = release_sequence_set Xo.actions Xo.lk Xw.mo in let hrs = hypothetical_release_sequence_set Xo.actions Xo.lk Xw.mo in let sw = lo_single_synchronizes_with_set Xo.actions Xo.sb Xo.asw Xw.rf lo rs hrs in let cad = carries_a_dependency_to_set Xo.actions Xo.sb Xo.dd Xw.rf in let dob = dependency_ordered_before_set Xo.actions Xw.rf rs cad in let ithb = inter_thread_happens_before Xo.actions Xo.sb sw dob in let hb = happens_before Xo.actions Xo.sb ithb in data_races Xo.actions hb let no_vsse_multi_lo_single_sw_undefined_behaviour Xo Xw lo = not (los_single_sw_data_races' Xo Xw lo = {}) || not (unsequenced_races Xo.actions Xo.sb = {}) || not (indeterminate_reads Xo.actions Xw.rf = {}) || not (bad_mutexes Xo lo = {}) (*********************************************** *) (* - 7.1 - single step mutex synchronisation top level judgement *) (*********************************************** *) let {hol; isabelle; coq; tex} no_vsse_multi_lo_single_sw_cmm opsem (p : program) = let pre_executions = { (Xopsem,(Xwitness,lo)) | opsem p Xopsem && no_vsse_multi_lo_single_sw_consistent_execution Xopsem Xwitness lo} in if exist ((Xo,(Xw,lo)) IN pre_executions). no_vsse_multi_lo_single_sw_undefined_behaviour Xo Xw lo then { (Xo,(Xw,lo)) | true } else pre_executions (*********************************************** *) (* 8 - Model simplified for programs without consumes *) (*********************************************** *) (* This model is simplified for use with programs that don't use consume memory orders. Happens-before is transitive. *) let no_vsse_consume_happens_before actions sb sw = tc (sb union sw) let no_vsse_consume_consistent_happens_before actions hb = irrefl actions hb let no_vsse_consume_consistent_execution Xo Xw = well_formed_threads Xo.actions Xo.threads Xo.lk Xo.sb Xo.asw Xo.dd Xo.cd && ( let rs = release_sequence_set Xo.actions Xo.lk Xw.mo in let hrs = hypothetical_release_sequence_set Xo.actions Xo.lk Xw.mo in let sw = synchronizes_with_set Xo.actions Xo.sb Xo.asw Xw.rf Xw.sc rs hrs in let hb = no_vsse_consume_happens_before Xo.actions Xo.sb sw in let vse = visible_side_effect_set Xo.actions Xo.sb hb in consistent_locks Xo.actions Xw.sc hb && no_vsse_consume_consistent_happens_before Xo.actions hb && consistent_sc_order Xo.actions Xw.mo Xw.sc hb && consistent_modification_order Xo.actions Xo.lk Xo.sb Xw.mo hb && well_formed_reads_from_mapping Xo.actions Xo.lk Xw.rf && no_vsse_consistent_reads_from_mapping Xo.actions Xo.lk Xo.sb Xw.rf Xw.sc Xw.mo hb vse) let no_vsse_consume_data_races' Xo Xw lo = let rs = release_sequence_set Xo.actions Xo.lk Xw.mo in let hrs = hypothetical_release_sequence_set Xo.actions Xo.lk Xw.mo in let sw = synchronizes_with_set Xo.actions Xo.sb Xo.asw Xw.rf lo rs hrs in let hb = no_vsse_consume_happens_before Xo.actions Xo.sb sw in data_races Xo.actions hb let no_vsse_consume_undefined_behaviour Xo Xw = not (no_vsse_consume_data_races' Xo Xw Xw.sc = {}) || not (unsequenced_races Xo.actions Xo.sb = {}) || not (indeterminate_reads Xo.actions Xw.rf = {}) || not (bad_mutexes Xo Xw.sc = {}) (*********************************************** *) (* - 8.1 - No consume top level judgement *) (*********************************************** *) let {hol; isabelle; coq; tex} no_vsse_consume_cmm opsem (p : program) = let pre_executions = { (Xopsem,Xwitness) | opsem p Xopsem && no_vsse_consume_consistent_execution Xopsem Xwitness} in if exist ((Xo,Xw) IN pre_executions). no_vsse_consume_undefined_behaviour Xo Xw then { (Xo,Xw) | true } else pre_executions (*********************************************** *) (* 9 - Model simplified for programs without consumes or relaxed *) (*********************************************** *) (* Without relaxed, can release sequences go? Unfortunately not. This model is NOT equvalent. *) let no_vsse_consume_relaxed_synchronizes_with actions sb asw rf lo a b = (* thread sync *) (a,b) IN asw || ( same_location a b && a IN actions && b IN actions && ( (* mutex sync *) (is_unlock a && is_lock b && (a,b) IN lo) || (* rel/acq sync *) ( is_release a && is_acquire b && not (same_thread a b) && (a,b) IN rf ) ) ) let no_vsse_consume_relaxed_synchronizes_with_set actions sb asw rf lo = { (a,b) | forall (a IN actions) (b IN actions) | no_vsse_consume_relaxed_synchronizes_with actions sb asw rf lo a b} let no_vsse_consume_relaxed_consistent_execution Xo Xw = well_formed_threads Xo.actions Xo.threads Xo.lk Xo.sb Xo.asw Xo.dd Xo.cd && ( let sw = no_vsse_consume_relaxed_synchronizes_with_set Xo.actions Xo.sb Xo.asw Xw.rf Xw.sc in let hb = no_vsse_consume_happens_before Xo.actions Xo.sb sw in let vse = visible_side_effect_set Xo.actions Xo.sb hb in consistent_locks Xo.actions Xw.sc hb && no_vsse_consume_consistent_happens_before Xo.actions hb && consistent_sc_order Xo.actions Xw.mo Xw.sc hb && consistent_modification_order Xo.actions Xo.lk Xo.sb Xw.mo hb && well_formed_reads_from_mapping Xo.actions Xo.lk Xw.rf && no_vsse_consistent_reads_from_mapping Xo.actions Xo.lk Xo.sb Xw.rf Xw.sc Xw.mo hb vse) let no_vsse_consume_relaxed_data_races' Xo Xw lo = let sw = no_vsse_consume_relaxed_synchronizes_with_set Xo.actions Xo.sb Xo.asw Xw.rf lo in let hb = no_vsse_consume_happens_before Xo.actions Xo.sb sw in data_races Xo.actions hb let no_vsse_consume_relaxed_undefined_behaviour Xo Xw = not (no_vsse_consume_relaxed_data_races' Xo Xw Xw.sc = {}) || not (unsequenced_races Xo.actions Xo.sb = {}) || not (indeterminate_reads Xo.actions Xw.rf = {}) || not (bad_mutexes Xo Xw.sc = {}) (*********************************************** *) (* - 9.1 - No consume or relaxed top level judgement *) (*********************************************** *) let {hol; isabelle; coq; tex} no_vsse_consume_relaxed_cmm opsem (p : program) = let pre_executions = { (Xopsem,Xwitness) | opsem p Xopsem && no_vsse_consume_relaxed_consistent_execution Xopsem Xwitness} in if exist ((Xo,Xw) IN pre_executions). no_vsse_consume_relaxed_undefined_behaviour Xo Xw then { (Xo,Xw) | true } else pre_executions (*********************************************** *) (* 10 - Model simplified for programs without consumes, relaxed, acquires or releases *) (*********************************************** *) let consistent_total_order actions sb asw tot = strict_total_order_over actions tot && sb subset tot && asw subset tot let tot_consistent_reads_from_mapping actions lk rf tot = (forall (b IN actions). (is_read b) --> ( let writes_at_same_location = { a | forall (a IN actions) | (same_location a b) && is_write a} in ( if (exist (a IN actions). adjacent_less_than (restrict_relation_set tot (writes_at_same_location union {b})) actions a b) then (exist (a IN actions). ((a,b) IN rf) && adjacent_less_than (restrict_relation_set tot (writes_at_same_location union {b})) actions a b) else not (exist (a IN actions). (a,b) IN rf) ) ) ) let tot_consistent_execution Xo rf tot = let lo = restrict_relation_set tot { a | forall (a IN Xo.actions) | is_lock a || is_unlock a } in well_formed_threads Xo.actions Xo.threads Xo.lk Xo.sb Xo.asw Xo.dd Xo.cd && consistent_total_order Xo.actions Xo.sb Xo.asw tot && consistent_locks Xo.actions lo tot && tot_consistent_reads_from_mapping Xo.actions Xo.lk rf tot && well_formed_reads_from_mapping Xo.actions Xo.lk rf let tot_hb_data_races Xo rf tot = let sc = tot inter { (a,b) | forall (a IN Xo.actions) (b IN Xo.actions) | is_seq_cst a && is_seq_cst b} in let mo = tot inter { (a,b) | forall (a IN Xo.actions) (b IN Xo.actions) | (same_location a b) && is_write a && is_write b} in let sw = no_vsse_consume_relaxed_synchronizes_with_set Xo.actions Xo.sb Xo.asw rf tot in let hb = no_vsse_consume_happens_before Xo.actions Xo.sb sw in data_races Xo.actions hb let tot_data_races actions tot = { (a,b) | forall (a IN actions) (b IN actions) | not (a = b) && same_location a b && (is_write a || is_write b) && not (same_thread a b) && not (is_atomic_action a && is_atomic_action b) && (adjacent_less_than tot actions a b || adjacent_less_than tot actions b a) } let tot_undefined_behaviour Xo rf tot = not (tot_hb_data_races Xo rf tot = {}) || not (unsequenced_races Xo.actions Xo.sb = {}) || not (indeterminate_reads Xo.actions rf = {}) || not (bad_mutexes Xo tot = {}) (*********************************************** *) (* - 10.1 - No consume, relaxed, acquire or release top level judgement *) (*********************************************** *) let {hol; isabelle; coq; tex} tot_cmm opsem (p : program) = let pre_executions = { (Xopsem,(rf,tot)) | opsem p Xopsem && tot_consistent_execution Xopsem rf tot} in if exist ((Xo,(rf,tot)) IN pre_executions). tot_undefined_behaviour Xo rf tot then { (Xo,(rf,tot)) | true } else pre_executions