Skip to content

Commit ab62c45

Browse files
committed
backtracking: mark only last operation
1 parent 94a0215 commit ab62c45

File tree

1 file changed

+44
-42
lines changed

1 file changed

+44
-42
lines changed

src/tracedAtomic.ml

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ let spawn f =
152152
{ next_op = Start; next_repr = None; resume_func = fiber_f; finished = false }
153153

154154
type proc_rec = { proc_id: int; op: atomic_op; obj_ptr : int option }
155-
type state_cell = { procs: proc_rec list; run_proc: int; run_op: atomic_op; run_ptr: int option; enabled : IntSet.t; mutable backtrack : IntSet.t }
155+
type state_cell = { procs: proc_rec list; run: proc_rec; enabled : IntSet.t; mutable backtrack : IntSet.t }
156156

157157
let num_runs = ref 0
158158

@@ -183,7 +183,7 @@ let do_run init_schedule =
183183
!final_func ();
184184
tracing := true
185185
end
186-
| (process_id_to_run, next_op, next_ptr) :: schedule -> begin
186+
| { proc_id = process_id_to_run ; op = next_op ; obj_ptr = next_ptr } :: schedule -> begin
187187
if !finished_processes == num_processes then
188188
(* this should never happen *)
189189
failwith("no enabled processes")
@@ -205,8 +205,8 @@ let do_run init_schedule =
205205
|> Seq.filter (fun (_,proc) -> not proc.finished)
206206
|> Seq.map (fun (id,_) -> id)
207207
|> IntSet.of_seq in
208-
let (run_proc, run_op, run_ptr) = List.hd init_schedule in
209-
{ procs; enabled = current_enabled; run_proc; run_op; run_ptr; backtrack = IntSet.empty }
208+
let last_run = List.hd init_schedule in
209+
{ procs; enabled = current_enabled; run = last_run ; backtrack = IntSet.empty }
210210

211211
type category =
212212
| Ignore
@@ -220,31 +220,32 @@ let categorize = function
220220
| Set | Exchange -> Write
221221
| CompareAndSwap | FetchAndAdd -> Read_write
222222

223+
let mark_backtrack proc time state (last_read, last_write) =
224+
let j = proc.proc_id in
225+
let find ptr map = match IntMap.find_opt ptr map with
226+
| None -> None
227+
| Some lst ->
228+
List.find_opt (fun (_, proc_id) -> proc_id <> j) lst
229+
in
230+
let i = match categorize proc.op, proc.obj_ptr with
231+
| Ignore, _ -> None
232+
| Read, Some ptr -> find ptr last_write
233+
| Write, Some ptr -> find ptr last_read
234+
| Read_write, Some ptr -> max (find ptr last_read) (find ptr last_write)
235+
| _ -> assert false
236+
in
237+
match i with
238+
| None -> ()
239+
| Some (i, _) ->
240+
assert (List.length state = time) ;
241+
let pre_s = List.nth state (time - i) in
242+
if IntSet.mem j pre_s.enabled then
243+
pre_s.backtrack <- IntSet.add j pre_s.backtrack
244+
else
245+
pre_s.backtrack <- IntSet.union pre_s.backtrack pre_s.enabled
246+
223247
let rec explore func time state current_schedule clock (last_read, last_write) =
224248
let s = List.hd state in
225-
List.iter (fun proc ->
226-
let j = proc.proc_id in
227-
let find ptr map = match IntMap.find_opt ptr map with
228-
| None -> None
229-
| Some lst ->
230-
List.find_opt (fun (_, proc_id) -> proc_id <> j) lst
231-
in
232-
let i = match categorize proc.op, proc.obj_ptr with
233-
| Ignore, _ -> None
234-
| Read, Some ptr -> find ptr last_write
235-
| Write, Some ptr -> find ptr last_read
236-
| Read_write, Some ptr -> max (find ptr last_read) (find ptr last_write)
237-
| _ -> assert false
238-
in
239-
match i with
240-
| None -> ()
241-
| Some (i, _) ->
242-
let pre_s = List.nth state (time - i + 1) in
243-
if IntSet.mem j pre_s.enabled then
244-
pre_s.backtrack <- IntSet.add j pre_s.backtrack
245-
else
246-
pre_s.backtrack <- IntSet.union pre_s.backtrack pre_s.enabled
247-
) s.procs;
248249
if IntSet.cardinal s.enabled > 0 then begin
249250
let p = IntSet.min_elt s.enabled in
250251
let dones = ref IntSet.empty in
@@ -254,7 +255,7 @@ let rec explore func time state current_schedule clock (last_read, last_write) =
254255
let j = IntSet.min_elt (IntSet.diff s.backtrack !dones) in
255256
dones := IntSet.add j !dones;
256257
let j_proc = List.nth s.procs j in
257-
let new_step = (j, j_proc.op, j_proc.obj_ptr) in
258+
let new_step = j_proc in
258259
let full_schedule = new_step :: current_schedule in
259260
let schedule =
260261
if !is_backtracking
@@ -269,18 +270,19 @@ let rec explore func time state current_schedule clock (last_read, last_write) =
269270
end
270271
in
271272
let step = do_run schedule in
273+
mark_backtrack step.run time state (last_read, last_write);
272274
let new_state = step :: state in
273-
let new_schedule = (step.run_proc, step.run_op, step.run_ptr) :: current_schedule in
275+
let new_schedule = step.run :: current_schedule in
274276
let new_time = time + 1 in
275277
let add ptr map =
276278
IntMap.update
277279
ptr
278-
(function None -> Some [new_time, step.run_proc]
279-
| Some steps -> Some ((new_time, step.run_proc) :: steps))
280+
(function None -> Some [time, step.run.proc_id]
281+
| Some steps -> Some ((time, step.run.proc_id) :: steps))
280282
map
281283
in
282284
let new_last_access =
283-
match categorize step.run_op, step.run_ptr with
285+
match categorize step.run.op, step.run.obj_ptr with
284286
| Ignore, _ -> last_read, last_write
285287
| Read, Some ptr -> add ptr last_read, last_write
286288
| Write, Some ptr -> last_read, add ptr last_write
@@ -303,24 +305,24 @@ let check f =
303305
tracing := false;
304306
if not (f ()) then begin
305307
Printf.printf "Found assertion violation at run %d:\n" !num_runs;
306-
List.iter (fun s ->
307-
begin match s with
308-
| (last_run_proc, last_run_op, last_run_ptr) -> begin
309-
let last_run_ptr = Option.map string_of_int last_run_ptr |> Option.value ~default:"" in
310-
Printf.printf "Process %d: %s %s\n" last_run_proc (atomic_op_str last_run_op) last_run_ptr
311-
end;
312-
end;
308+
List.iter (fun { proc_id ; op ; obj_ptr } ->
309+
let last_run_ptr = Option.map string_of_int obj_ptr |> Option.value ~default:"" in
310+
Printf.printf "Process %d: %s %s\n" proc_id (atomic_op_str op) last_run_ptr
313311
) (List.rev !schedule_for_checks) ;
314312
assert(false)
315313
end;
316314
tracing := tracing_at_start
317315

318316

319317
let trace func =
320-
let empty_schedule = [(0, Start, None)] in
318+
let empty_schedule = [{ proc_id = 0 ; op = Start ; obj_ptr = None }] in
321319
setup_run func empty_schedule ;
322320
let empty_state = do_run empty_schedule :: [] in
323321
let empty_clock = IntMap.empty in
324322
let empty_last_access = IntMap.empty, IntMap.empty in
325-
explore func 1 empty_state empty_schedule empty_clock empty_last_access ;
326-
Printf.printf "Finished after %i runs.\n%!" !num_runs
323+
explore func 1 empty_state empty_schedule empty_clock empty_last_access
324+
325+
let trace func =
326+
Fun.protect
327+
(fun () -> trace func)
328+
~finally:(fun () -> Printf.printf "Finished after %i runs.\n%!" !num_runs)

0 commit comments

Comments
 (0)