|
|
|
(*
|
|
|
|
* Copyright (c) 2018 - present Facebook, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD style license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
*)
|
|
|
|
|
|
|
|
open! IStd
|
|
|
|
module F = Format
|
|
|
|
|
|
|
|
(** Abstraction of a path that represents a lock, special-casing equality and comparisons
|
|
|
|
to work over type, base variable modulo this and access list *)
|
|
|
|
module LockIdentity : sig
|
|
|
|
include PrettyPrintable.PrintableOrderedType with type t = AccessPath.t
|
|
|
|
|
|
|
|
val owner_class : t -> Typ.name option
|
|
|
|
(** Class of the root variable of the path representing the lock *)
|
|
|
|
|
|
|
|
val equal : t -> t -> bool
|
|
|
|
end
|
|
|
|
|
|
|
|
(** A lock event. Equality/comparison disregards the call trace but includes location. *)
|
|
|
|
module LockEvent : sig
|
|
|
|
type severity_t = Low | Medium | High [@@deriving compare]
|
|
|
|
|
|
|
|
type event_t = LockAcquire of LockIdentity.t | MayBlock of (string * severity_t)
|
|
|
|
[@@deriving compare]
|
|
|
|
|
|
|
|
val pp_event : F.formatter -> event_t -> unit
|
|
|
|
|
|
|
|
type t = private {event: event_t; loc: Location.t; trace: CallSite.t list}
|
|
|
|
|
|
|
|
include PrettyPrintable.PrintableOrderedType with type t := t
|
|
|
|
end
|
|
|
|
|
|
|
|
(** Represents either
|
|
|
|
- the existence of a program path from the current method to the eventual acquisition of a lock
|
|
|
|
("eventually"), or,
|
|
|
|
- the "first" lock being taken *in the current method* and, before its release, the eventual
|
|
|
|
acquisition of "eventually" *)
|
|
|
|
module LockOrder : sig
|
|
|
|
type t = private {first: LockEvent.t option; eventually: LockEvent.t}
|
|
|
|
|
|
|
|
include PrettyPrintable.PrintableOrderedType with type t := t
|
|
|
|
|
|
|
|
val may_deadlock : t -> t -> bool
|
|
|
|
(** check if two pairs are symmetric in terms of locks, where locks are compared modulo the
|
|
|
|
variable name at the root of each path. *)
|
|
|
|
|
|
|
|
val make_loc_trace : t -> Errlog.loc_trace
|
|
|
|
|
|
|
|
val get_loc : t -> Location.t
|
|
|
|
end
|
|
|
|
|
|
|
|
module LockOrderDomain : sig
|
|
|
|
include PrettyPrintable.PPSet with type elt = LockOrder.t
|
|
|
|
|
|
|
|
include AbstractDomain.WithBottom with type astate = t
|
|
|
|
end
|
|
|
|
|
|
|
|
module UIThreadDomain :
|
|
|
|
AbstractDomain.WithBottom with type astate = string AbstractDomain.Types.bottom_lifted
|
|
|
|
|
|
|
|
include AbstractDomain.WithBottom
|
|
|
|
|
|
|
|
val acquire : astate -> Location.t -> LockIdentity.t -> astate
|
|
|
|
|
|
|
|
val release : astate -> LockIdentity.t -> astate
|
|
|
|
|
|
|
|
val blocking_call :
|
|
|
|
caller:Typ.Procname.t -> callee:Typ.Procname.t -> LockEvent.severity_t -> Location.t -> astate
|
|
|
|
-> astate
|
|
|
|
|
|
|
|
val set_on_ui_thread : astate -> string -> astate
|
|
|
|
(** set the property "runs on UI thread" to true by attaching the given explanation string as to
|
|
|
|
why this method is thought to do so *)
|
|
|
|
|
|
|
|
type summary = LockOrderDomain.astate * UIThreadDomain.astate
|
|
|
|
|
|
|
|
val pp_summary : F.formatter -> summary -> unit
|
|
|
|
|
|
|
|
val to_summary : astate -> summary
|
|
|
|
|
|
|
|
val integrate_summary : astate -> Typ.Procname.t -> Location.t -> summary -> astate
|