-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce backwards compatible infrastructure for parallelism #1708
base: master
Are you sure you want to change the base?
Changes from all commits
b1d786f
1667683
f9ed034
bc33346
67a1c61
3b9d901
539a853
3f7d226
48c76c0
7fe63ef
490d047
16db900
dec26b3
f423d8e
ccb2a6f
a18cd77
9e1614d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
(** Mutex attribute type domain. *) | ||
open Goblint_parallel | ||
|
||
module MutexKind = | ||
struct | ||
|
@@ -21,7 +22,7 @@ end | |
include Lattice.FlatConf (struct include Printable.DefaultConf let bot_name = "Uninitialized" let top_name = "Top" end) (MutexKind) | ||
|
||
(* Needed because OS X is weird and assigns different constants than normal systems... :( *) | ||
let recursive_int = lazy ( | ||
let recursive_int = DomainsafeLazy.from_fun (fun () -> | ||
Comment on lines
-24
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is
There's also There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point! Also what about There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These two were the ones discovered by Felix back then. Currently it is quite out of scope to go through all analysis and decide for each if they are thread-safe. In order to keep this moving (this branch does not have the solvers and they are slowly diverging) we can: |
||
let res = ref (Z.of_int 2) in (* Use OS X as the default, it doesn't have the enum *) | ||
GoblintCil.iterGlobals !Cilfacade.current_file (function | ||
| GEnumTag (einfo, _) -> | ||
|
@@ -39,7 +40,7 @@ let of_int z = | |
if Z.equal z Z.zero then | ||
`Lifted MutexKind.NonRec | ||
else | ||
let recursive_int = Lazy.force recursive_int in | ||
let recursive_int = DomainsafeLazy.force recursive_int in | ||
if Z.equal z recursive_int then | ||
`Lifted MutexKind.Recursive | ||
else | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,8 @@ module Category = MessageCategory | |
|
||
open GobResult.Syntax | ||
|
||
module Format = BatFormat | ||
|
||
|
||
module Severity = | ||
struct | ||
|
@@ -195,10 +197,14 @@ let print ?(ppf= !formatter) (m: Message.t) = | |
| Debug -> "white" (* non-bright white is actually some gray *) | ||
| Success -> "green" | ||
in | ||
let pp_prefix = Format.dprintf "@{<%s>[%a]%a@}" severity_stag Severity.pp m.severity Tags.pp m.tags in | ||
let pp_print_option ?(none = fun _ () -> ()) pp_v ppf = function | ||
| None -> none ppf () | ||
| Some v -> pp_v ppf v | ||
in | ||
Comment on lines
+200
to
+203
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's this about? Isn't it just a copy of what's in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The module now uses |
||
let pp_prefix = (fun ppf -> Format.fprintf ppf "@{<%s>[%a]%a@}" severity_stag Severity.pp m.severity Tags.pp m.tags) in | ||
let pp_loc ppf = Format.fprintf ppf " @{<violet>(%a)@}" CilType.Location.pp in | ||
let pp_loc ppf loc = | ||
Format.fprintf ppf "%a" (Format.pp_print_option pp_loc) (Option.map Location.to_cil loc) | ||
Format.fprintf ppf "%a" (pp_print_option pp_loc) (Option.map Location.to_cil loc) | ||
in | ||
let pp_piece ppf piece = | ||
Format.fprintf ppf "@{<%s>%s@}%a" severity_stag (Piece.text_with_context piece) pp_loc piece.loc | ||
|
@@ -229,7 +235,7 @@ let print ?(ppf= !formatter) (m: Message.t) = | |
let pp_quote ppf loc = | ||
if get_bool "warn.quote-code" then ( | ||
let pp_cut_quote ppf = Format.fprintf ppf "@,@[<v 0>%a@,@]" pp_quote in | ||
(Format.pp_print_option pp_cut_quote) ppf (Option.map Location.to_cil loc) | ||
(pp_print_option pp_cut_quote) ppf (Option.map Location.to_cil loc) | ||
) | ||
in | ||
let pp_piece ppf piece = Format.fprintf ppf "%a%a" pp_piece piece pp_quote piece.loc in | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,13 +12,13 @@ module Token = WideningToken | |
module TS = SetDomain.ToppedSet (Token) (struct let topname = "Top" end) | ||
|
||
(** Reference to current {!add} implementation. Maintained by {!Lifter}. *) | ||
let add_ref: (Token.t -> unit) ref = ref (fun _ -> | ||
let add_ref: (Token.t -> unit) Domain.DLS.key = Domain.DLS.new_key (fun () _ -> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar question here: we have a lot of top-level There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe the same from above applies here as well. |
||
if GobConfig.get_bool "ana.widen.tokens" then | ||
failwith "Unhandled widening token" | ||
) | ||
|
||
(** Add widening token to local state. *) | ||
let add t = !add_ref t | ||
let add t = (Domain.DLS.get add_ref) t | ||
|
||
|
||
(** Widening tokens added to side effects. | ||
|
@@ -137,16 +137,16 @@ struct | |
|
||
let lift_fun man f g h = | ||
let new_tokens = ref (snd man.local) in (* New tokens not yet used during this transfer function, such that it is deterministic. *) | ||
let old_add = !add_ref in | ||
let old_add = Domain.DLS.get add_ref in | ||
let old_local_tokens = !local_tokens in | ||
add_ref := (fun t -> new_tokens := TS.add t !new_tokens); | ||
Domain.DLS.set add_ref (fun t -> new_tokens := TS.add t !new_tokens); | ||
local_tokens := snd man.local; | ||
let d = | ||
Fun.protect (fun () -> | ||
h (g (conv man)) | ||
) ~finally:(fun () -> | ||
local_tokens := old_local_tokens; | ||
add_ref := old_add | ||
Domain.DLS.set add_ref old_add | ||
) | ||
in | ||
(* If transfer function exits via exception, then new tokens are forgotten. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
type 'a t = GobMutex.t * ('a Stdlib.Lazy.t) | ||
|
||
let from_fun f = (GobMutex.create (), Stdlib.Lazy.from_fun f) | ||
|
||
let force (mtx, blk) = | ||
GobMutex.lock mtx; | ||
let value = Stdlib.Lazy.force blk in | ||
GobMutex.unlock mtx; | ||
value |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
(** Lazy type which protects against concurrent calls of 'force'. *) | ||
|
||
type 'a t | ||
|
||
val from_fun: (unit -> 'a) -> 'a t | ||
val force: 'a t -> 'a |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
(include_subdirs no) | ||
|
||
(library | ||
(name goblint_parallel) | ||
(public_name goblint.parallel) | ||
(libraries | ||
batteries | ||
(select gobMutex.ml from | ||
(domainslib -> gobMutex.domainslib.ml) | ||
( -> gobMutex.no-domainslib.ml) | ||
) | ||
(select threadpool.ml from | ||
(domainslib -> threadpool.domainslib.ml) | ||
(-> threadpool.no-domainslib.ml) | ||
) | ||
domain_shims | ||
domain-local-await) | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
(* Simple Mutex Implementation using Domain-Local Await (https://github.com/ocaml-multicore/domain-local-await) | ||
Copyright © 2023 Vesa Karvonen | ||
|
||
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, | ||
provided that the above copyright notice and this permission notice appear in all copies. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES | ||
OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY | ||
DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | ||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *) | ||
|
||
type state = | ||
| Unlocked | ||
| Locked of (unit -> unit) list | ||
|
||
type t = state Atomic.t | ||
|
||
let create () = Atomic.make Unlocked | ||
|
||
let unlock t = | ||
match Atomic.exchange t Unlocked with | ||
| Unlocked -> invalid_arg "mutex: already unlocked" | ||
| Locked awaiters -> List.iter ((|>) ()) awaiters | ||
|
||
let rec lock t = | ||
match Atomic.get t with | ||
| Unlocked -> | ||
if not (Atomic.compare_and_set t Unlocked (Locked [])) then | ||
lock t | ||
| Locked awaiters as before -> | ||
let dla = Domain_local_await.prepare_for_await () in | ||
let after = Locked (dla.release :: awaiters) in | ||
if Atomic.compare_and_set t before after then | ||
match dla.await () with | ||
| () -> lock t | ||
| exception cancellation_exn -> | ||
let rec cleanup () = | ||
match Atomic.get t with | ||
| Unlocked -> () | ||
| Locked awaiters as before -> | ||
if List.for_all ((==) dla.release) awaiters then | ||
let after = | ||
Locked (List.filter ((!=) dla.release) awaiters) | ||
in | ||
if not (Atomic.compare_and_set t before after) then | ||
cleanup () | ||
in | ||
cleanup (); | ||
raise cancellation_exn | ||
else | ||
lock t |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
type state = NoOp | ||
type t = state | ||
|
||
let create () = NoOp | ||
let unlock _ = () | ||
let lock _ = () |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Consider changing 'any more' to 'anymore' for clarity and consistency.
Copilot is powered by AI, so mistakes are possible. Review output carefully before use.