Skip to content

Commit e027887

Browse files
committed
big bad backtracking steps
1 parent ab62c45 commit e027887

File tree

1 file changed

+48
-28
lines changed

1 file changed

+48
-28
lines changed

src/tracedAtomic.ml

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,12 @@ 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_rec; enabled : IntSet.t; mutable backtrack : IntSet.t }
155+
type state_cell = {
156+
procs : proc_rec list;
157+
run : proc_rec;
158+
enabled : IntSet.t;
159+
mutable backtrack : proc_rec list IntMap.t;
160+
}
156161

157162
let num_runs = ref 0
158163

@@ -167,7 +172,7 @@ let setup_run func init_schedule =
167172
finished_processes := 0;
168173
num_runs := !num_runs + 1;
169174
if !num_runs mod 1000 == 0 then
170-
Printf.printf "run: %d\n" !num_runs
175+
Printf.printf "run: %d\n%!" !num_runs
171176

172177
let do_run init_schedule =
173178
(* cache the number of processes in case it's expensive*)
@@ -206,7 +211,7 @@ let do_run init_schedule =
206211
|> Seq.map (fun (id,_) -> id)
207212
|> IntSet.of_seq in
208213
let last_run = List.hd init_schedule in
209-
{ procs; enabled = current_enabled; run = last_run ; backtrack = IntSet.empty }
214+
{ procs; enabled = current_enabled; run = last_run ; backtrack = IntMap.empty }
210215

211216
type category =
212217
| Ignore
@@ -220,65 +225,80 @@ let categorize = function
220225
| Set | Exchange -> Write
221226
| CompareAndSwap | FetchAndAdd -> Read_write
222227

223-
let mark_backtrack proc time state (last_read, last_write) =
228+
let mark_backtrack ~is_last proc time state (last_read, last_write) =
224229
let j = proc.proc_id in
225230
let find ptr map = match IntMap.find_opt ptr map with
226231
| None -> None
227232
| Some lst ->
228233
List.find_opt (fun (_, proc_id) -> proc_id <> j) lst
229234
in
230-
let i = match categorize proc.op, proc.obj_ptr with
235+
let find_loc ~is_last proc =
236+
match categorize proc.op, proc.obj_ptr with
231237
| Ignore, _ -> None
232238
| 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)
239+
| Write, Some ptr when not is_last -> find ptr last_read
240+
| (Write | Read_write), Some ptr -> max (find ptr last_read) (find ptr last_write)
235241
| _ -> assert false
236242
in
237-
match i with
243+
match find_loc ~is_last proc with
238244
| None -> ()
239245
| Some (i, _) ->
240246
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
247+
let pre_s = List.nth state (time - i + 1) in
248+
if IntSet.mem j pre_s.enabled then begin
249+
let replay_steps = List.filteri (fun k s -> k <= time - i && s.run.proc_id = j) state in
250+
let replay_steps = List.map (fun s -> s.run) replay_steps in
251+
let todo =
252+
match IntMap.find_opt j pre_s.backtrack with
253+
| None -> true
254+
| Some lst -> List.length lst > List.length replay_steps
255+
in
256+
let causal p = match find_loc ~is_last:false p with None -> true | Some (k, _) -> k <= i in
257+
if todo && List.for_all causal replay_steps
258+
then pre_s.backtrack <- IntMap.add j replay_steps pre_s.backtrack
259+
end
244260
else
245-
pre_s.backtrack <- IntSet.union pre_s.backtrack pre_s.enabled
261+
failwith "TODO: currently untested"
262+
263+
let map_diff_set map set =
264+
IntMap.filter (fun key _ -> not (IntSet.mem key set)) map
246265

247266
let rec explore func time state current_schedule clock (last_read, last_write) =
248267
let s = List.hd state in
249268
if IntSet.cardinal s.enabled > 0 then begin
250269
let p = IntSet.min_elt s.enabled in
270+
let init_step = List.nth s.procs p in
251271
let dones = ref IntSet.empty in
252-
s.backtrack <- IntSet.singleton p;
272+
s.backtrack <- IntMap.singleton p [init_step] ;
253273
let is_backtracking = ref false in
254-
while IntSet.(cardinal (diff s.backtrack !dones)) > 0 do
255-
let j = IntSet.min_elt (IntSet.diff s.backtrack !dones) in
274+
while IntMap.(cardinal (map_diff_set s.backtrack !dones)) > 0 do
275+
let j, new_step = IntMap.min_binding (map_diff_set s.backtrack !dones) in
256276
dones := IntSet.add j !dones;
257-
let j_proc = List.nth s.procs j in
258-
let new_step = j_proc in
259-
let full_schedule = new_step :: current_schedule in
277+
let new_schedule = List.rev_append (List.rev new_step) current_schedule in
260278
let schedule =
261279
if !is_backtracking
262280
then begin
263-
setup_run func full_schedule ;
264-
full_schedule
281+
setup_run func new_schedule ;
282+
new_schedule
265283
end
266284
else begin
267285
is_backtracking := true ;
268-
schedule_for_checks := full_schedule;
269-
[new_step]
286+
schedule_for_checks := new_schedule;
287+
new_step
270288
end
271289
in
272290
let step = do_run schedule in
273-
mark_backtrack step.run time state (last_read, last_write);
274-
let new_state = step :: state in
275-
let new_schedule = step.run :: current_schedule in
276-
let new_time = time + 1 in
291+
let new_state =
292+
List.map (fun run -> { step with run; backtrack = IntMap.empty }) new_step
293+
@ state
294+
in
295+
let new_time = time + List.length new_step in
296+
mark_backtrack ~is_last:(IntSet.is_empty step.enabled) step.run new_time new_state (last_read, last_write);
277297
let add ptr map =
278298
IntMap.update
279299
ptr
280-
(function None -> Some [time, step.run.proc_id]
281-
| Some steps -> Some ((time, step.run.proc_id) :: steps))
300+
(function None -> Some [new_time, step.run.proc_id]
301+
| Some steps -> Some ((new_time, step.run.proc_id) :: steps))
282302
map
283303
in
284304
let new_last_access =

0 commit comments

Comments
 (0)