@@ -152,7 +152,7 @@ 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 : 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
157157let 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
211211type 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+
223247let 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
319317let 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