@@ -30,7 +30,10 @@ module CasWithStatAndException = struct
3030 if Atomic. compare_and_set key old new_ then
3131 Atomic. incr count_success
3232 else
33- raise CasFailException
33+ begin
34+ Atomic. incr count_failure;
35+ raise CasFailException
36+ end
3437end
3538
3639module Base : GenericCreatingEqSolver =
@@ -54,14 +57,17 @@ module Base : GenericCreatingEqSolver =
5457 stable : bool ;
5558 called : bool ;
5659 root : bool ; (* * If this variable was the starting point of a solver thread *)
60+ id : int ; (* * Just for experimentation *)
5761 }
58- let default () = {value = S.Dom. bot () ; infl = VS. empty; called = false ; stable = false ; wpoint = false ; root = false }
62+ let default () = {value = S.Dom. bot () ; infl = VS. empty; called = false ; stable = false ; wpoint = false ; root = false ; id = 0 }
5963 let to_string s = S.Dom. show s.value
6064 end
6165
6266 (* * Concurrency safe hashmap for the state of the unknowns. *)
6367 module CM = Data. SafeHashmap (S. Var ) (DefaultState ) (HM )
6468
69+ let var_count = Atomic. make 0
70+
6571 let create_empty_data () = CM. create ()
6672
6773 (* TODO this map should also be thread safe, or secured with a lock *)
@@ -77,9 +83,9 @@ module Base : GenericCreatingEqSolver =
7783 let cas = Data.CasWithStat. cas
7884
7985 let print_data data =
80- Logs. debug " CAS success: %d" (Atomic. get Data.CasWithStat . count_success);
81- Logs. debug " CAS failure: %d" (Atomic. get Data.CasWithStat . count_failure);
82- Logs. debug " CAS success rate: %f" (float_of_int (Atomic. get Data.CasWithStat. count_success) /. (float_of_int (Atomic. get Data.CasWithStat. count_success + Atomic. get Data.CasWithStat . count_failure)))
86+ Logs. info " CAS success: %d" (Atomic. get CasWithStatAndException . count_success);
87+ Logs. info " CAS failure: %d" (Atomic. get CasWithStatAndException . count_failure);
88+ Logs. info " CAS success rate: %f" (float_of_int (Atomic. get CasWithStatAndException. count_success) /. (float_of_int (Atomic. get CasWithStatAndException. count_success + Atomic. get CasWithStatAndException . count_failure)))
8389
8490 let print_data_verbose data str =
8591 if Logs.Level. should_log Debug then (
@@ -108,6 +114,9 @@ module Base : GenericCreatingEqSolver =
108114 let init x thread_id =
109115 let value, was_created = CM. find_create data x in
110116 if (was_created) then new_var_event thread_id x;
117+ let var_id = Atomic. fetch_and_add var_count 1 in
118+ let s = Atomic. get value in
119+ Atomic. set value {s with id = var_id};
111120 value
112121 in
113122
@@ -176,7 +185,7 @@ module Base : GenericCreatingEqSolver =
176185 if tracing then trace " thread_pool" " starting task %d to iterate %a" job_id S.Var. pretty_trace y;
177186 thread_starts_solve_event job_id;
178187 let inner_prom = ref [] in
179- iterate None inner_prom y job_id y_atom;
188+ iterate None inner_prom y [] job_id y_atom;
180189 HM. remove unknowns_with_running_jobs y;
181190 thread_ends_solve_event job_id;
182191 Thread_pool. await_all pool (! inner_prom);
@@ -199,13 +208,14 @@ module Base : GenericCreatingEqSolver =
199208 @param job_id The id of the thread that is solving for x.
200209 @param x_atom The atomic reference to the state of x, to prevent unnecessary lookups.
201210 *)
202- and iterate orig prom x job_id x_atom = (* ~(inner) solve in td3*)
211+ and iterate orig prom x ichain job_id x_atom = (* ~(inner) solve in td3*)
203212
204213 (* * Get the value for y, triggering an iteration if necessary, and performing a lookup otherwise.
205214 @param x The variable whose query led to the query for y, so that the infl of y can be updated.
206215 @param y The variable to get the value for.
207216 @return The value of y.
208217 *)
218+
209219 let rec query x y = (* ~eval in td3 *)
210220 (* Query with atomics: if anything is changed, query is repeated and the initial call *)
211221 (* has no side effects. Thus, imitating that the query just happend in a later point in time.*)
@@ -233,7 +243,8 @@ module Base : GenericCreatingEqSolver =
233243 ) else (
234244 if tracing then trace " infl" " add_infl %a %a" S.Var. pretty_trace y S.Var. pretty_trace x;
235245 cas y_atom y_state {y_state_with_infl with stable = true ; called= true };
236- iterate (Some x) prom y job_id y_atom;
246+ let ichain = y_state.id :: ichain in
247+ iterate (Some x) prom y ichain job_id y_atom;
237248 (Atomic. get y_atom).value
238249 )
239250 ) ) with CasFailException -> query x y
@@ -281,9 +292,19 @@ module Base : GenericCreatingEqSolver =
281292 in
282293
283294 (* begining of iteration to update the value for x *)
295+ (* let ichain_as_string = List.fold_left (fun acc x -> acc ^ (string_of_int x) ^ ".") "" in *)
296+ (* if tracing then trace "ichain" "%s" (ichain_as_string ichain); *)
284297 assert (not @@ is_global x);
285298 let cas = CasWithStatAndException. cas in
286299 let x_state = Atomic. get x_atom in
300+
301+ (match orig with
302+ Some orig -> begin
303+ let orig_atom = CM. find data orig in
304+ let orig_state = Atomic. get orig_atom in
305+ if tracing then trace " ilink" " %d,%d" orig_state.id x_state.id;
306+ end
307+ | None -> () );
287308 if tracing then trace " iter" " %d iterate %a, stable: %b, wpoint: %b" job_id S.Var. pretty_trace x x_state.stable x_state.wpoint;
288309 let x_is_widening_point = x_state.wpoint in (* if x becomes a wpoint during eq, checking this will delay widening until next iterate *)
289310 eval_rhs_event job_id x;
@@ -302,13 +323,13 @@ module Base : GenericCreatingEqSolver =
302323 | Some z -> (VS. add z x_state.infl)
303324 | None -> x_state.infl in
304325 let x_state_new = {x_state with infl = infl; called = false ; wpoint = false } in
305- try (cas x_atom x_state x_state_new ) with CasFailException -> (iterate[@ tailcall]) orig prom x job_id x_atom;
326+ try (cas x_atom x_state x_state_new ) with CasFailException -> (iterate[@ tailcall]) orig prom x ichain job_id x_atom;
306327 ) else (
307328 let x_state_new = {x_state with stable = true } in
308329 (* No need to track cas success, as we will iterate again anyway. *)
309330 ignore @@ Atomic. compare_and_set x_atom x_state x_state_new;
310331 if tracing then trace " iter" " iterate still unstable %a" S.Var. pretty_trace x;
311- (iterate[@ tailcall]) orig prom x job_id x_atom
332+ (iterate[@ tailcall]) orig prom x ichain job_id x_atom
312333 )
313334 ) else (
314335 (* value has changed *)
@@ -336,11 +357,11 @@ module Base : GenericCreatingEqSolver =
336357 let success = Atomic. compare_and_set x_atom x_state new_s in
337358 if success then (
338359 if tracing then trace " iter" " iterate changed %a" S.Var. pretty_trace x;
339- (iterate[@ tailcall]) orig prom x job_id x_atom
360+ (iterate[@ tailcall]) orig prom x ichain job_id x_atom
340361 ) else (finalize[@ tailcall]) ()
341362 ) in
342363 finalize () ;
343- ) with CasFailException -> (iterate[@ tailcall]) orig prom x job_id x_atom;
364+ ) with CasFailException -> (iterate[@ tailcall]) orig prom x ichain job_id x_atom;
344365 ) in
345366
346367 let set_start (x ,d ) =
@@ -350,6 +371,7 @@ module Base : GenericCreatingEqSolver =
350371 in
351372
352373 (* beginning of main solve *)
374+
353375 start_event () ;
354376
355377 List. iter set_start st;
@@ -388,6 +410,7 @@ module Base : GenericCreatingEqSolver =
388410 (* After termination, only those variables are stable which are
389411 * - reachable from any of the queried variables vs, or
390412 * - effected by side-effects and have no constraints on their own (this should be the case for all of our analyses). *)
413+ print_data () ;
391414 print_stats () ;
392415 stop_event () ;
393416
0 commit comments