@@ -8,6 +8,7 @@ type config = {
88 thread_count : int ;
99 generate_conditionals : bool ;
1010 print_tests : bool ;
11+ seed : int option ;
1112}
1213
1314let print_config t =
@@ -16,29 +17,60 @@ let print_config t =
1617 Printf. printf " value_limit: %d\n " t.value_limit;
1718 Printf. printf " operations_count: %d\n " t.operations_count;
1819 Printf. printf " thread_count: %d\n " t.thread_count;
19- Printf. printf " generate_conditionals: %b\n %!" t.generate_conditionals
20+ Printf. printf " generate_conditionals: %b\n %!" t.generate_conditionals;
21+ Printf. printf " seed: %s\n %!"
22+ (Option. map Int. to_string t.seed |> Option. value ~default: " <random>" )
2023
2124let var_name i = Char. chr (i + 97 )
2225
2326module Function = struct
24- (* Arbitrary function from int to bool *)
25- type t = IntSet .t
27+ type t =
28+ | Get of { true_on : IntSet .t }
29+ | CompareAndSet of { old_value : int ; new_value : int }
30+ | FetchAndAdd of { delta : int ; true_on : IntSet .t }
2631
27- let rec gen value_limit =
28- let true_set =
29- List. init value_limit (fun i -> if Random. bool () then Some i else None )
30- |> List. filter_map Fun. id |> IntSet. of_list
32+ let gen value_limit =
33+ let rec set_f () =
34+ let set =
35+ List. init value_limit (fun i -> if Random. bool () then Some i else None )
36+ |> List. filter_map Fun. id |> IntSet. of_list
37+ in
38+ let size = IntSet. cardinal set in
39+ if 0 < size && size < value_limit then set else set_f ()
3140 in
32- let size = IntSet. cardinal true_set in
33- if 0 < size && size < value_limit then true_set else gen value_limit
41+ match Random. int 6 with
42+ | 0 | 1 | 2 -> Get { true_on = set_f () }
43+ | 3 | 4 ->
44+ let old_value = Random. int value_limit in
45+ let new_value = Random. int value_limit in
46+ CompareAndSet { old_value; new_value }
47+ | 5 ->
48+ let delta = Random. int value_limit in
49+ FetchAndAdd { delta; true_on = set_f () }
50+ | _ -> assert false
3451
35- let eval t input = IntSet. mem input t
52+ let eval variable = function
53+ | Get { true_on } -> IntSet. mem (Atomic. get variable) true_on
54+ | FetchAndAdd { delta; true_on } ->
55+ IntSet. mem (Atomic. fetch_and_add variable delta) true_on
56+ | CompareAndSet { old_value; new_value } ->
57+ Atomic. compare_and_set variable old_value new_value
3658
37- let to_string t var_id =
38- Printf. sprintf " IntSet.mem (Atomic.get %c) (IntSet.of_list [%s])"
39- (var_name var_id)
40- (IntSet. to_seq t |> List. of_seq |> List. map Int. to_string
41- |> String. concat " ; " )
59+ let to_string var_id = function
60+ | Get { true_on } ->
61+ Printf. sprintf " IntSet.mem (Atomic.get %c) (IntSet.of_list [%s])"
62+ (var_name var_id)
63+ (IntSet. to_seq true_on |> List. of_seq |> List. map Int. to_string
64+ |> String. concat " ; " )
65+ | FetchAndAdd { delta; true_on } ->
66+ Printf. sprintf
67+ " IntSet.mem (Atomic.fetch_and_add %c %d) (IntSet.of_list [%s])"
68+ (var_name var_id) delta
69+ (IntSet. to_seq true_on |> List. of_seq |> List. map Int. to_string
70+ |> String. concat " ; " )
71+ | CompareAndSet { old_value; new_value } ->
72+ Printf. sprintf " Atomic.compare_and_set %c %d %d" (var_name var_id)
73+ old_value new_value
4274end
4375
4476module Conditional = struct
@@ -57,8 +89,7 @@ module Conditional = struct
5789 match (vars, funcs) with
5890 | [] , [] -> ( match operator with `And -> true | `Or -> false )
5991 | var :: vars_tl , func :: funcs_tl -> (
60- let input = Atomic. get var in
61- let output = Function. eval func input in
92+ let output = Function. eval var func in
6293 match (operator, output) with
6394 | `Or , true -> true
6495 | `And , false -> false
@@ -73,14 +104,21 @@ module Conditional = struct
73104 let to_string t ~var_ids =
74105 let operator_str = match t.operator with `Or -> " || " | `And -> " && " in
75106 List. combine t.functions var_ids
76- |> List. map (fun (func , var_id ) -> Function. to_string func var_id)
107+ |> List. map (fun (func , var_id ) -> Function. to_string var_id func )
77108 |> String. concat operator_str
78109end
79110
80111module Step = struct
81112 type t =
82113 | Write of { var_id : int ; new_value : int ; next : t }
83114 | Read of { var_id : int ; next : t }
115+ | CompareAndSet of {
116+ var_id : int ;
117+ old_value : int ;
118+ new_value : int ;
119+ next : t ;
120+ }
121+ | FetchAndAdd of { var_id : int ; delta : int ; next : t }
84122 | Conditional of {
85123 var_ids : int list ;
86124 conditional : Conditional .t ;
@@ -96,6 +134,15 @@ module Step = struct
96134 | Read { var_id; next } ->
97135 ignore (Atomic. get (CCVector. get globals var_id));
98136 run ~globals next
137+ | CompareAndSet { var_id; old_value; new_value; next } ->
138+ ignore
139+ (Atomic. compare_and_set
140+ (CCVector. get globals var_id)
141+ old_value new_value);
142+ run ~globals next
143+ | FetchAndAdd { var_id; delta; next } ->
144+ ignore (Atomic. fetch_and_add (CCVector. get globals var_id) delta);
145+ run ~globals next
99146 | Conditional { var_ids; conditional; on_true; next } ->
100147 let variables =
101148 List. map (fun var_id -> CCVector. get globals var_id) var_ids
@@ -113,6 +160,14 @@ module Step = struct
113160 | Read { var_id; next } ->
114161 Printf. printf " %sAtomic.get %c |> ignore;\n " indent (var_name var_id);
115162 print ~depth next
163+ | CompareAndSet { var_id; old_value; new_value; next } ->
164+ Printf. printf " %sAtomic.compare_and_set %c %d %d |> ignore;\n " indent
165+ (var_name var_id) old_value new_value;
166+ print ~depth next
167+ | FetchAndAdd { var_id; delta; next } ->
168+ Printf. printf " %sAtomic.fetch_and_add %c %d |> ignore;\n " indent
169+ (var_name var_id) delta;
170+ print ~depth next
116171 | Conditional { var_ids; conditional; on_true; next } ->
117172 let s = Conditional. to_string conditional ~var_ids in
118173 Printf. printf " %sif (%s) then (\n " indent s;
@@ -127,12 +182,19 @@ module Step = struct
127182 if fuel > 1 then gen ~config ~fuel: (fuel - 1 ) () else Noop
128183 in
129184 let maybe_conditionals = if config.generate_conditionals then 1 else 0 in
130- match Random. int (2 + maybe_conditionals) with
131- | 0 ->
185+ match Random. int (6 + maybe_conditionals) with
186+ | 0 | 1 ->
132187 let new_value = Random. int config.value_limit in
133188 Write { var_id; new_value; next = next fuel }
134- | 1 -> Read { var_id; next = next fuel }
135- | 2 ->
189+ | 2 | 3 -> Read { var_id; next = next fuel }
190+ | 4 ->
191+ let old_value = Random. int config.value_limit in
192+ let new_value = Random. int config.value_limit in
193+ CompareAndSet { var_id; old_value; new_value; next = next fuel }
194+ | 5 ->
195+ let delta = Random. int config.value_limit - (config.value_limit / 2 ) in
196+ FetchAndAdd { var_id; delta; next = next fuel }
197+ | 6 ->
136198 let func_count =
137199 min (max 1 fuel) (min config.globals_count (1 + Random. int 2 ))
138200 in
@@ -144,7 +206,7 @@ module Step = struct
144206 in
145207 let fuel_a, fuel_b =
146208 let tmp = Random. int (max (fuel - func_count) 1 ) in
147- (tmp/ 2 , tmp/ 2 )
209+ (tmp / 2 , tmp / 2 )
148210 in
149211
150212 let on_true = gen ~config ~fuel: fuel_a () in
@@ -179,13 +241,14 @@ module Program = struct
179241end
180242
181243let run_random config () =
182- Random. self_init () ;
244+ (match config.seed with
245+ | None -> Random. self_init ()
246+ | Some seed -> Random. init seed);
183247 let globals = CCVector. of_list (List. init config.globals_count Fun. id) in
184248 let thread_f = Step. gen ~config ~fuel: config.operations_count in
185249 let threads = List. init config.thread_count (fun _ -> thread_f () ) in
186250 let program = ({ globals; threads } : Program.t ) in
187251 if config.print_tests then Program. print program;
188-
189252 let random = Program. run ~impl: (`Random 100 ) program in
190253 let dpor = Program. run ~impl: `Dpor program in
191254 if not (Dscheck.Trace_tracker. subset random dpor) then (
@@ -212,6 +275,7 @@ let _ =
212275 let thread_count = ref 3 in
213276 let generate_conditionals = ref true in
214277 let print_tests = ref false in
278+ let seed = ref 0 in
215279 let speclist =
216280 [
217281 ( " -test-count" ,
@@ -232,6 +296,7 @@ let _ =
232296 ( " -generate-conditionals" ,
233297 Arg. Set generate_conditionals,
234298 " enable/disable generation of conditional statements" );
299+ (" -seed" , Arg. Set_int seed, " random seed for generation" );
235300 ]
236301 in
237302 Arg. parse speclist
@@ -247,6 +312,7 @@ let _ =
247312 thread_count = ! thread_count;
248313 generate_conditionals = ! generate_conditionals;
249314 print_tests = ! print_tests;
315+ seed = (if ! seed > 0 then Some ! seed else None );
250316 }
251317 : config)
252318 in
0 commit comments