Skip to content

Commit 8a6e504

Browse files
committed
fix: backtracking nested spawns
1 parent eb124d2 commit 8a6e504

File tree

2 files changed

+35
-15
lines changed

2 files changed

+35
-15
lines changed

src/tracedAtomic.ml

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,13 @@ let categorize = function
234234
| Set | Exchange -> Write
235235
| CompareAndSwap | FetchAndAdd -> Read_write
236236

237+
let rec list_findi predicate lst i = match lst with
238+
| [] -> None
239+
| x::_ when predicate i x -> Some (i, x)
240+
| _::xs -> list_findi predicate xs (i + 1)
241+
242+
let list_findi predicate lst = list_findi predicate lst 0
243+
237244
let mark_backtrack ~is_last proc time state (last_read, last_write) =
238245
let j = proc.proc_id in
239246
let find ptr map = match IdMap.find_opt ptr map with
@@ -249,27 +256,39 @@ let mark_backtrack ~is_last proc time state (last_read, last_write) =
249256
| (Write | Read_write), Some ptr -> max (find ptr last_read) (find ptr last_write)
250257
| _ -> assert false
251258
in
259+
let rec find_replay_trace ~lower ~upper proc_id =
260+
let pre_s = List.nth state (time - upper + 1) in
261+
let replay_steps = List.filteri (fun k s -> k >= lower && k <= time - upper && s.run.proc_id = proc_id) state in
262+
let replay_steps = List.rev_map (fun s -> s.run) replay_steps in
263+
let causal p = match find_loc ~is_last:false p with
264+
| None -> true
265+
| Some (k, _) -> k <= upper in
266+
if List.for_all causal replay_steps
267+
then if IdSet.mem proc_id pre_s.enabled
268+
then Some replay_steps
269+
else let is_parent k s = k > lower && k < time - upper && s.run.op = Spawn && s.run.obj_ptr = Some proc_id in
270+
match list_findi is_parent state with
271+
| None -> None
272+
| Some (parent_i, spawn) ->
273+
assert (parent_i > lower) ;
274+
begin match find_replay_trace ~lower:parent_i ~upper spawn.run.proc_id with
275+
| None -> None
276+
| Some spawn_steps -> Some (spawn_steps @ replay_steps)
277+
end
278+
else None
279+
in
252280
match find_loc ~is_last proc with
253281
| None -> ()
254282
| Some (i, _) ->
255283
assert (List.length state = time) ;
256284
let pre_s = List.nth state (time - i + 1) in
257-
if IdSet.mem j pre_s.enabled then begin
258-
let replay_steps = List.filteri (fun k s -> k <= time - i && s.run.proc_id = j) state in
259-
let replay_steps = List.map (fun s -> s.run) replay_steps in
260-
let todo =
261-
match IdMap.find_opt j pre_s.backtrack with
285+
match find_replay_trace ~lower:0 ~upper:i proc.proc_id with
286+
| None -> ()
287+
| Some replay_steps ->
288+
if match IdMap.find_opt j pre_s.backtrack with
262289
| None -> true
263290
| Some lst -> List.length lst > List.length replay_steps
264-
in
265-
let causal p = match find_loc ~is_last:false p with
266-
| None -> true
267-
| Some (k, _) -> k <= i in
268-
if todo && List.for_all causal replay_steps
269-
then pre_s.backtrack <- IdMap.add j (List.rev replay_steps) pre_s.backtrack
270-
end
271-
else
272-
() (* failwith "TODO: currently untested" *)
291+
then pre_s.backtrack <- IdMap.add j replay_steps pre_s.backtrack
273292

274293
let map_diff_set map set =
275294
IdMap.filter (fun key _ -> not (IdSet.mem key set)) map

tests/test_simple.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ module Atomic = Dscheck.TracedAtomic
66
let test i =
77
let x = Atomic.make i in
88
let y = Atomic.make 0 in
9-
Atomic.spawn (fun () -> if Atomic.get x = 10 then Atomic.set y 2) ;
9+
Atomic.spawn (fun () ->
10+
Atomic.spawn (fun () -> if Atomic.get x = 10 then Atomic.set y 2)) ;
1011
Atomic.set x 0 ;
1112
Atomic.set y 1 ;
1213
Atomic.final (fun () -> Atomic.check (fun () -> Atomic.get y <> 2))

0 commit comments

Comments
 (0)