[starvation] track on-main-thread status in summaries

Reviewed By: ddino

Differential Revision: D7431140

fbshipit-source-id: d127820
master
Nikos Gorogiannis 7 years ago committed by Facebook Github Bot
parent 0130c09dfc
commit 346589f1fb

@ -20,6 +20,10 @@ let is_java_static pname =
false false
let is_on_main_thread pn =
RacerDConfig.(match Models.get_thread pn with Models.MainThread -> true | _ -> false)
module Summary = Summary.Make (struct module Summary = Summary.Make (struct
type payload = StarvationDomain.summary type payload = StarvationDomain.summary
@ -77,9 +81,12 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
| LockedIfTrue -> | LockedIfTrue ->
astate astate
| NoEffect -> | NoEffect ->
if is_on_main_thread callee_pname then Domain.set_on_main_thread astate
else
Summary.read_summary pdesc callee_pname Summary.read_summary pdesc callee_pname
|> Option.value_map ~default:astate ~f:(fun callee_summary -> |> Option.value_map ~default:astate ~f:(fun callee_summary ->
Domain.integrate_summary ~caller_state:astate ~callee_summary callee_pname loc ) ) Domain.integrate_summary ~caller_state:astate ~callee_summary callee_pname loc
) )
| _ -> | _ ->
astate astate
@ -140,7 +147,7 @@ let get_summary caller_pdesc callee_pdesc =
|> Option.map ~f:(fun summary -> (callee_pdesc, summary)) |> Option.map ~f:(fun summary -> (callee_pdesc, summary))
let report_deadlocks get_proc_desc tenv pdesc summary = let report_deadlocks get_proc_desc tenv pdesc (summary, _) =
let open StarvationDomain in let open StarvationDomain in
let process_callee_elem caller_pdesc caller_elem callee_pdesc elem = let process_callee_elem caller_pdesc caller_elem callee_pdesc elem =
if LockOrder.may_deadlock caller_elem elem && should_report_if_same_class caller_elem then ( if LockOrder.may_deadlock caller_elem elem && should_report_if_same_class caller_elem then (
@ -188,7 +195,7 @@ let report_deadlocks get_proc_desc tenv pdesc summary =
let proc_descs = List.rev_filter_map methods ~f:get_proc_desc in let proc_descs = List.rev_filter_map methods ~f:get_proc_desc in
let summaries = List.rev_filter_map proc_descs ~f:(get_summary pdesc) in let summaries = List.rev_filter_map proc_descs ~f:(get_summary pdesc) in
(* for each summary related to the endpoint, analyse and report on its pairs *) (* for each summary related to the endpoint, analyse and report on its pairs *)
List.iter summaries ~f:(fun (callee_pdesc, summary) -> List.iter summaries ~f:(fun (callee_pdesc, (summary, _)) ->
LockOrderDomain.iter (process_callee_elem pdesc elem callee_pdesc) summary LockOrderDomain.iter (process_callee_elem pdesc elem callee_pdesc) summary
) ) ) ) ) )
in in

@ -207,11 +207,14 @@ module LockState = struct
fold ff map init fold ff map init
end end
include AbstractDomain.Pair (LockState) (LockOrderDomain) module MainThreadDomain = AbstractDomain.BooleanOr
include AbstractDomain.Pair (AbstractDomain.Pair (LockState) (LockOrderDomain)) (MainThreadDomain)
let empty = (LockState.empty, LockOrderDomain.empty) let empty = ((LockState.empty, LockOrderDomain.empty), false)
let is_empty ((ls, lo), main) =
LockState.is_empty ls && LockOrderDomain.is_empty lo && MainThreadDomain.is_empty main
let is_empty (ls, lo) = LockState.is_empty ls && LockOrderDomain.is_empty lo
(* for every lock b held locally, add a pair (b, lock_event), plus (None, lock_event) *) (* for every lock b held locally, add a pair (b, lock_event), plus (None, lock_event) *)
let add_order_pairs ls lock_event acc = let add_order_pairs ls lock_event acc =
@ -233,16 +236,17 @@ let add_order_pairs ls lock_event acc =
LockState.fold_over_events add_first_and_eventually ls acc |> add_eventually LockState.fold_over_events add_first_and_eventually ls acc |> add_eventually
let acquire lockid (ls, lo) loc = let acquire lockid ((ls, lo), main) loc =
let newlock_event = LockEvent.make_acquire lockid loc in let newlock_event = LockEvent.make_acquire lockid loc in
let lo' = add_order_pairs ls newlock_event lo in let lo' = add_order_pairs ls newlock_event lo in
let ls' = LockState.acquire lockid newlock_event ls in let ls' = LockState.acquire lockid newlock_event ls in
(ls', lo') ((ls', lo'), main)
let release lockid (ls, lo) = (LockState.release lockid ls, lo) let release lockid ((ls, lo), main) = ((LockState.release lockid ls, lo), main)
let integrate_summary ~caller_state:(ls, lo) ~callee_summary callee_pname loc = let integrate_summary ~caller_state:((ls, lo), main) ~callee_summary callee_pname loc =
let callee_lo, callee_main = callee_summary in
(* for each pair (b,a) in the callee, add (l,b) and (l,a) to the current state, where (* for each pair (b,a) in the callee, add (l,b) and (l,a) to the current state, where
l is held locally *) l is held locally *)
let do_elem elem acc = let do_elem elem acc =
@ -251,13 +255,17 @@ let integrate_summary ~caller_state:(ls, lo) ~callee_summary callee_pname loc =
in in
let callsite = CallSite.make callee_pname loc in let callsite = CallSite.make callee_pname loc in
(* add callsite to the "eventually" trace *) (* add callsite to the "eventually" trace *)
let elems = LockOrderDomain.with_callsite callsite callee_summary in let elems = LockOrderDomain.with_callsite callsite callee_lo in
let lo' = LockOrderDomain.fold do_elem elems lo in let lo' = LockOrderDomain.fold do_elem elems lo in
(ls, lo') let main' = MainThreadDomain.join main callee_main in
((ls, lo'), main')
let set_on_main_thread (sum, _) = (sum, true)
let to_summary astate = snd astate let to_summary ((_, lo), main) = (lo, main)
type summary = LockOrderDomain.astate type summary = LockOrderDomain.astate * MainThreadDomain.astate
let pp_summary = LockOrderDomain.pp let pp_summary fmt (lo, main) =
F.fprintf fmt "LockOrder: %a, MainThread: %a" LockOrderDomain.pp lo MainThreadDomain.pp main

@ -60,7 +60,9 @@ val acquire : LockIdentity.t -> astate -> Location.t -> astate
val release : LockIdentity.t -> astate -> astate val release : LockIdentity.t -> astate -> astate
type summary = LockOrderDomain.astate val set_on_main_thread : astate -> astate
type summary = LockOrderDomain.astate * bool
val pp_summary : F.formatter -> summary -> unit val pp_summary : F.formatter -> summary -> unit

Loading…
Cancel
Save