@@ -152,7 +152,12 @@ let spawn f =
152152 { next_op = Start ; next_repr = None ; resume_func = fiber_f; finished = false }
153153
154154type 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
157162let 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
172177let 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
211216type 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
247266let 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