@@ -12,7 +12,6 @@ type _ Effect.t +=
1212 | FetchAndAdd : (int t * int ) -> int Effect .t
1313
1414module IntSet = Set. Make (Int )
15-
1615module IntMap = Map. Make (Int )
1716
1817let _string_of_set s = IntSet. fold (fun y x -> string_of_int y ^ " ," ^ x) s " "
@@ -193,11 +192,54 @@ type state_cell = {
193192 mutable backtrack : IntSet .t ;
194193}
195194
196- let num_runs = ref 0
195+ let num_states = ref 0
196+ let num_interleavings = ref 0
197197
198198(* we stash the current state in case a check fails and we need to log it *)
199199let schedule_for_checks = ref []
200200
201+ let var_name i =
202+ match i with
203+ | None -> " "
204+ | Some i ->
205+ let c = Char. chr (i + 96 ) in
206+ Printf. sprintf " %c" c
207+
208+ let print_execution_sequence chan =
209+ let highest_proc =
210+ List. fold_left
211+ (fun highest (curr_proc , _ , _ ) ->
212+ if curr_proc > highest then curr_proc else highest)
213+ (- 1 ) ! schedule_for_checks
214+ in
215+
216+ let bar =
217+ List. init ((highest_proc * 20 ) + 20 ) (fun _ -> " -" ) |> String. concat " "
218+ in
219+ Printf. fprintf chan " \n sequence %d\n " ! num_interleavings;
220+ Printf. fprintf chan " %s\n " bar;
221+ List. init (highest_proc + 1 ) (fun proc ->
222+ Printf. fprintf chan " P%d\t\t\t " proc)
223+ |> ignore;
224+ Printf. fprintf chan " \n %s\n " bar;
225+
226+ List. iter
227+ (fun s ->
228+ match s with
229+ | last_run_proc , last_run_op , last_run_ptr ->
230+ let last_run_ptr = var_name last_run_ptr in
231+ let tabs =
232+ List. init last_run_proc (fun _ -> " \t\t\t " ) |> String. concat " "
233+ in
234+ Printf. fprintf chan " %s%s %s\n " tabs
235+ (atomic_op_str last_run_op)
236+ last_run_ptr)
237+ ! schedule_for_checks;
238+ Printf. fprintf chan " %s\n %!" bar
239+
240+ let interleavings_chan = (ref None : out_channel option ref )
241+ let record_traces_flag = ref false
242+
201243let do_run init_func init_schedule =
202244 init_func () ;
203245 (* set up run *)
@@ -214,6 +256,15 @@ let do_run init_func init_schedule =
214256 | [] ->
215257 if ! finished_processes == num_processes then (
216258 tracing := false ;
259+
260+ num_interleavings := ! num_interleavings + 1 ;
261+ if ! record_traces_flag then
262+ Trace_tracker. add_trace ! schedule_for_checks;
263+
264+ (match ! interleavings_chan with
265+ | None -> ()
266+ | Some chan -> print_execution_sequence chan);
267+
217268 ! final_func () ;
218269 tracing := true )
219270 | (process_id_to_run , next_op , next_ptr ) :: schedule ->
@@ -231,8 +282,8 @@ let do_run init_func init_schedule =
231282 run_trace init_schedule () ;
232283 finished_processes := 0 ;
233284 tracing := false ;
234- num_runs := ! num_runs + 1 ;
235- if ! num_runs mod 1000 == 0 then Printf. printf " run: %d\n %!" ! num_runs;
285+ num_states := ! num_states + 1 ;
286+ (* if !num_states mod 1000 == 0 then Printf.printf "run: %d\n%!" !num_states; *)
236287 let procs =
237288 CCVector. mapi
238289 (fun i p -> { proc_id = i; op = p.next_op; obj_ptr = p.next_repr })
@@ -304,31 +355,45 @@ let check f =
304355 let tracing_at_start = ! tracing in
305356 tracing := false ;
306357 if not (f () ) then (
307- Printf. printf " Found assertion violation at run %d:\n " ! num_runs;
308- List. iter
309- (fun s ->
310- match s with
311- | last_run_proc , last_run_op , last_run_ptr ->
312- let last_run_ptr =
313- Option. map string_of_int last_run_ptr |> Option. value ~default: " "
314- in
315- Printf. printf " Process %d: %s %s\n " last_run_proc
316- (atomic_op_str last_run_op)
317- last_run_ptr)
318- ! schedule_for_checks;
358+ Printf. printf " Found assertion violation at run %d:\n " ! num_interleavings;
359+ print_execution_sequence stdout;
319360 assert false );
320361 tracing := tracing_at_start
321362
322363let reset_state () =
323364 finished_processes := 0 ;
324365 atomics_counter := 1 ;
325- num_runs := 0 ;
366+ num_states := 0 ;
367+ num_interleavings := 0 ;
326368 schedule_for_checks := [] ;
369+ Trace_tracker. clear_traces () ;
327370 CCVector. clear processes
328371
329- let trace func =
372+ let dscheck_trace_file_env = Sys. getenv_opt " dscheck_trace_file"
373+
374+ let dpor func =
330375 reset_state () ;
331376 let empty_state = do_run func [ (0 , Start , None ) ] :: [] in
332377 let empty_clock = IntMap. empty in
333378 let empty_last_access = IntMap. empty in
334379 explore func empty_state empty_clock empty_last_access
380+
381+ let trace ?interleavings ?(record_traces = false ) func =
382+ record_traces_flag := record_traces || Option. is_some dscheck_trace_file_env;
383+ interleavings_chan := interleavings;
384+
385+ dpor func;
386+
387+ (* print reports *)
388+ (match ! interleavings_chan with
389+ | None -> ()
390+ | Some chan ->
391+ Printf. fprintf chan " \n explored %d interleavings and %d states\n "
392+ ! num_interleavings ! num_states);
393+
394+ match dscheck_trace_file_env with
395+ | None -> ()
396+ | Some path ->
397+ let chan = open_out path in
398+ Trace_tracker. print_traces chan;
399+ close_out chan
0 commit comments