@@ -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 " "
@@ -194,10 +193,36 @@ type state_cell = {
194193}
195194
196195let num_runs = ref 0
196+ let num_traces = 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 print_trace () =
202+ Printf. printf " -----------------------\n " ;
203+ List. iter
204+ (fun s ->
205+ match s with
206+ | last_run_proc , last_run_op , last_run_ptr ->
207+ let var_name i =
208+ let c = Char. chr (i + 97 ) in
209+ let seq = Seq. cons c Seq. empty in
210+ String. of_seq seq
211+ in
212+
213+ let last_run_ptr =
214+ Option. map (* string_of_int *) var_name last_run_ptr
215+ |> Option. value ~default: " "
216+ in
217+ let tabs =
218+ List. init last_run_proc (fun _ -> " \t\t " ) |> String. concat " "
219+ in
220+ Printf. printf " %sP%d: %s %s\n " tabs last_run_proc
221+ (atomic_op_str last_run_op)
222+ last_run_ptr)
223+ ! schedule_for_checks;
224+ Printf. printf " -----------------------\n %!"
225+
201226let do_run init_func init_schedule =
202227 init_func () ;
203228 (* set up run *)
@@ -214,6 +239,8 @@ let do_run init_func init_schedule =
214239 | [] ->
215240 if ! finished_processes == num_processes then (
216241 tracing := false ;
242+ print_trace () ;
243+ num_traces := ! num_traces + 1 ;
217244 ! final_func () ;
218245 tracing := true )
219246 | (process_id_to_run , next_op , next_ptr ) :: schedule ->
@@ -259,6 +286,172 @@ let do_run init_func init_schedule =
259286 backtrack = IntSet. empty;
260287 }
261288
289+ let _set_to_str s =
290+ IntSet. to_seq s |> List. of_seq |> List. map Int. to_string |> String. concat " , "
291+
292+ let rec explore_source depth func state sleep =
293+ (* sleep := IntSet.empty; *)
294+ let s = last_element state in
295+ (* Printf.printf "[depth=%d] explore (backtrack=[%s], sleep=[%s], enabled=[%s])\n%!" depth
296+ (set_to_str s.backtrack) (set_to_str !sleep) (set_to_str s.enabled); *)
297+ let p_maybe = IntSet. min_elt_opt (IntSet. diff s.enabled ! sleep) in
298+ match p_maybe with
299+ | None -> () (* Printf.printf "[depth=%d] rtn\n%!" depth *)
300+ | Some p ->
301+ s.backtrack < - IntSet. singleton p;
302+
303+ while IntSet. (cardinal (diff s.backtrack ! sleep)) > 0 do
304+ (* Printf.printf "[depth=%d] loop (backtrack=[%s], sleep=[%s])\n%!" depth
305+ (set_to_str s.backtrack) (set_to_str !sleep); *)
306+ let p = IntSet. min_elt (IntSet. diff s.backtrack ! sleep) in
307+ let proc = List. nth s.procs p in
308+
309+ (* Printf.printf "[depth=%d] p=%d, %s\n%!" depth p (atomic_op_str proc.op); *)
310+ (* run *)
311+ let state_top =
312+ let schedule =
313+ List. map (fun s -> (s.run_proc, s.run_op, s.run_ptr)) state
314+ @ [ (p, proc.op, proc.obj_ptr) ]
315+ in
316+ do_run func schedule
317+ in
318+ assert (state_top.run_proc = p);
319+ let new_state = state @ [ state_top ] in
320+
321+ let obj_ptr = Option. value proc.obj_ptr ~default: (- 1 ) in
322+ (* find reversible races *)
323+ let reversible_races =
324+ List. filter
325+ (fun proc' ->
326+ let run_ptr = Option. value proc'.run_ptr ~default: (- 2 ) in
327+ obj_ptr = run_ptr && proc'.run_proc <> p)
328+ new_state
329+ in
330+ let reversible_races =
331+ match reversible_races with
332+ | [] -> []
333+ | _ -> [ last_element reversible_races ]
334+ in
335+
336+ (* Printf.printf "[depth=%d] reversible races sz: %d\n%!" depth
337+ (List.length reversible_races); *)
338+ for i = 0 to List. length reversible_races - 1 do
339+ let e = List. nth reversible_races i in
340+ (* Printf.printf "[depth=%d] inner loop, racing op: e=(q=%d, %s)\n%!"
341+ depth e.run_proc (atomic_op_str e.run_op); *)
342+ let found_e, prefix_rev, suffix_rev =
343+ List. fold_left
344+ (fun (seen_e , prefix , suffix ) proc' ->
345+ if seen_e then (seen_e, prefix, proc' :: suffix)
346+ else if proc' == e then (true , prefix, suffix)
347+ else (false , proc' :: prefix, suffix))
348+ (false , [] , [] ) state
349+ in
350+ assert (
351+ List. length prefix_rev + List. length suffix_rev
352+ = List. length state - 1 );
353+ assert found_e;
354+ let prefix (* E' *) = List. rev prefix_rev in
355+
356+ if List. length prefix > 0 then
357+ (* List.iter
358+ (fun proc ->
359+ Printf.printf "[depth=%d] ::prefix:: (p=%d, %s)\n%!" depth
360+ proc.run_proc
361+ (atomic_op_str proc.run_op))
362+ prefix; *)
363+ let suffix = List. rev suffix_rev in
364+
365+ (* List.iter
366+ (fun proc ->
367+ Printf.printf "[depth=%d] ::suffix:: (p=%d, %s)\n%!" depth
368+ proc.run_proc
369+ (atomic_op_str proc.run_op))
370+ suffix; *)
371+ let prefix_top = last_element prefix in
372+
373+ (* Printf.printf
374+ "[depth=%d] nonempty prefix, prefix_top: (p=%d, %s)\n%!" depth
375+ prefix_top.run_proc
376+ (atomic_op_str prefix_top.run_op); *)
377+ let v_E (* occurs after e but independent of e *) =
378+ List. filter
379+ (fun proc' ->
380+ proc'.run_proc <> e.run_proc
381+ && Option. value proc'.run_ptr ~default: (- 1 )
382+ <> Option. value e.run_ptr ~default: (- 2 ))
383+ suffix
384+ in
385+
386+ (* List.iter
387+ (fun proc ->
388+ Printf.printf
389+ "[depth=%d] ::occurs_after_e_but_indep:: (p=%d, %s)\n%!"
390+ depth proc.run_proc
391+ (atomic_op_str proc.run_op))
392+ v_E; *)
393+ let v = v_E @ [ state_top ] in
394+
395+ (* List.iter
396+ (fun proc ->
397+ Printf.printf "[depth=%d] ::v:: (p=%d, %s)\n%!" depth
398+ proc.run_proc
399+ (atomic_op_str proc.run_op))
400+ v; *)
401+ let initials =
402+ let initials_map, initials_spawns =
403+ List. fold_left
404+ (fun (first_accesses , spawns ) (state_cell : state_cell ) ->
405+ match state_cell.run_ptr with
406+ | None ->
407+ let new_spawns =
408+ IntSet. add state_cell.run_proc spawns
409+ in
410+ (first_accesses, new_spawns)
411+ | Some obj_ptr ->
412+ let new_first_accesses =
413+ IntMap. update obj_ptr
414+ (function
415+ | Some v -> Some v
416+ | None -> Some state_cell.run_proc)
417+ first_accesses
418+ in
419+ (new_first_accesses, spawns))
420+ (IntMap. empty, IntSet. empty)
421+ v
422+ in
423+ IntMap. fold
424+ (fun _ run_proc initials_set ->
425+ IntSet. add run_proc initials_set)
426+ initials_map initials_spawns
427+ in
428+
429+ (* Printf.printf "[depth=%d] initials=[%s], backtrack=[%s]\n%!"
430+ depth (set_to_str initials)
431+ (set_to_str prefix_top.backtrack); *)
432+ if IntSet. (cardinal (inter prefix_top.backtrack initials)) = 0 then
433+ let _initial = IntSet. min_elt initials in
434+ (* Printf.printf "[depth=%d] adding initial to backtrack\n%!"
435+ depth; *)
436+ prefix_top.backtrack < - IntSet. add _initial prefix_top.backtrack
437+ done ;
438+
439+ let sleep' =
440+ IntSet. filter
441+ (fun q ->
442+ (* only keep q that are independent with p: must be other thread of execution and act on a different object (or none) *)
443+ if q == p then false
444+ else
445+ let proc' = List. nth s.procs q in
446+ match proc'.obj_ptr with
447+ | None -> true
448+ | Some obj_ptr' -> obj_ptr' <> obj_ptr)
449+ ! sleep
450+ in
451+ explore_source (depth + 1 ) func new_state (ref sleep');
452+ sleep := IntSet. add p ! sleep
453+ done
454+
262455let rec explore func state clock last_access =
263456 let s = last_element state in
264457 List. iter
@@ -305,17 +498,7 @@ let check f =
305498 tracing := false ;
306499 if not (f () ) then (
307500 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;
501+ print_trace () ;
319502 assert false );
320503 tracing := tracing_at_start
321504
@@ -326,9 +509,18 @@ let reset_state () =
326509 schedule_for_checks := [] ;
327510 CCVector. clear processes
328511
329- let trace func =
512+ let _trace func =
330513 reset_state () ;
331514 let empty_state = do_run func [ (0 , Start , None ) ] :: [] in
332515 let empty_clock = IntMap. empty in
333516 let empty_last_access = IntMap. empty in
334517 explore func empty_state empty_clock empty_last_access
518+
519+ let _trace_source func =
520+ reset_state () ;
521+ let empty_state = do_run func [ (0 , Start , None ) ] in
522+ explore_source 0 func [ empty_state ] (ref IntSet. empty)
523+
524+ let trace func =
525+ _trace_source func;
526+ Printf. printf " \n num_traces: %d\n %!" ! num_traces
0 commit comments