-
Notifications
You must be signed in to change notification settings - Fork 86
Analysis of pthread_barriers
#1652
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
Merged
Merged
Changes from 24 commits
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
0a880fe
First steps
michael-schwarz 2a95bec
Record capacity
michael-schwarz 148055c
Add first checks
michael-schwarz acfaf99
Use MHP information
michael-schwarz 298d345
More involved MHP check
michael-schwarz 0d7468c
Rm spurious variable
michael-schwarz 58d0ceb
Document pthread barriers
michael-schwarz bfcdef9
Add `NOMAC` option
michael-schwarz e6c97ba
Remark that `os` gem is needed
michael-schwarz 9d5e594
Make sound for multiprocess
michael-schwarz 5a1fbc1
Fix indentation
michael-schwarz 0f4bf4e
Also consider locks
michael-schwarz 15f7f8b
Minimal race handling
michael-schwarz c869024
Fix pairwise MHP check
michael-schwarz 6633584
Add case for more waiters
michael-schwarz c7b57b1
Get rid of overcomplicated logic
michael-schwarz 933882e
Cleanup
michael-schwarz b8ae5fc
Fix `List.length` call
michael-schwarz 459797c
Use Seq instead of constructing from scratch
michael-schwarz ef85413
Add further non-racy example
michael-schwarz 844f3ed
Barriers: Move to separate folder
michael-schwarz 4e04bc7
docs workflow: do not install os gem
michael-schwarz e864728
Include goblint header
michael-schwarz e62092e
Do not crash if `os` gem is not installed, but just skip mac tests
michael-schwarz 46ab1b7
Add comment by Simmo on connection k-clique problem
michael-schwarz 30c444f
Mark as tailcall
michael-schwarz b4a50f2
Merge branch 'master' into issue_1651
michael-schwarz 3ef29c5
Disjoint domain: Remark on why `to_seq` is not efficient
michael-schwarz 6caafab
Typo
michael-schwarz b9a045c
Simplify naming
michael-schwarz ee8ea09
Use MCPAccess.A for MHP check instead of custom construct
michael-schwarz 627e9c8
Add barrierception examples
michael-schwarz f70b193
Remove spurious annotation
michael-schwarz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,167 @@ | ||
| (** Must have waited barriers for Pthread barriers ([pthreadBarriers]). *) | ||
|
|
||
| open GoblintCil | ||
| open Analyses | ||
| module LF = LibraryFunctions | ||
|
|
||
| module Spec = | ||
| struct | ||
| module Barriers = struct | ||
| include SetDomain.ToppedSet (ValueDomain.Addr) (struct let topname = "All barriers" end) | ||
| let name () = "mayBarriers" | ||
| end | ||
|
|
||
| module MustBarriers = struct | ||
| include Lattice.Reverse (Barriers) | ||
| let name () = "mustBarriers" | ||
| end | ||
|
|
||
| module Capacity = Queries.ID | ||
|
|
||
| include Analyses.IdentitySpec | ||
| module V = VarinfoV | ||
|
|
||
| module TID = ThreadIdDomain.ThreadLifted | ||
|
|
||
| module MHPplusLock = struct | ||
| module Locks = LockDomain.MustLockset | ||
|
|
||
| include Printable.Prod (MHP) (Locks) | ||
| let name () = "MHPplusLock" | ||
|
|
||
| let mhp (mhp1, l1) (mhp2, l2) = | ||
| MHP.may_happen_in_parallel mhp1 mhp2 && Locks.is_empty (Locks.inter l1 l2) | ||
|
|
||
| let tid ((mhp:MHP.t), _) = mhp.tid | ||
|
|
||
| let may_be_non_unique_thread (mhp, _) = MHP.may_be_non_unique_thread mhp | ||
| end | ||
|
|
||
| module Waiters = SetDomain.ToppedSet (MHPplusLock) (struct let topname = "All MHP" end) | ||
| module Multiprocess = BoolDomain.MayBool | ||
| module G = Lattice.Prod3 (Multiprocess) (Capacity) (Waiters) | ||
|
|
||
| let name () = "pthreadBarriers" | ||
|
|
||
| module MustObserved = MapDomain.MapTop_LiftBot (TID) (MustBarriers) | ||
| module D = Lattice.Prod (Barriers) (MustObserved) | ||
|
|
||
| include Analyses.ValueContexts(D) | ||
|
|
||
| let possible_vinfos (a: Queries.ask) barrier = | ||
| Queries.AD.to_var_may (a.f (Queries.MayPointTo barrier)) | ||
sim642 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| let special man (lval: lval option) (f:varinfo) (arglist:exp list) : D.t = | ||
| let exists_k pred k waiters = | ||
| let k_product elems = | ||
| let rec doit k = | ||
| if k = 1 then | ||
| Seq.map (Seq.return) elems | ||
| else | ||
| let arg = doit (k-1) in | ||
| Seq.map_product (Seq.cons) elems arg | ||
| in | ||
| doit k | ||
| in | ||
| Seq.exists pred (k_product (Waiters.to_seq waiters)) | ||
| in | ||
| let desc = LF.find f in | ||
| match desc.special arglist with | ||
| | BarrierWait barrier -> | ||
| let ask = Analyses.ask_of_man man in | ||
| let may, must = man.local in | ||
| let barriers = possible_vinfos ask barrier in | ||
| let mhp = MHP.current ask in | ||
| let handle_one b = | ||
| try | ||
| let locks = man.ask (Queries.MustLockset) in | ||
| man.sideg b (Multiprocess.bot (), Capacity.bot (), Waiters.singleton (mhp, locks)); | ||
| let addr = ValueDomain.Addr.of_var b in | ||
| let (multiprocess, capacity, waiters) = man.global b in | ||
| let may = Barriers.add addr may in | ||
| if multiprocess then | ||
| (may, must) | ||
| else | ||
| let relevant_waiters = Waiters.filter (fun other -> MHPplusLock.mhp (mhp, locks) other) waiters in | ||
| if Waiters.exists MHPplusLock.may_be_non_unique_thread relevant_waiters then | ||
| (may, must) | ||
| else | ||
| match capacity with | ||
| | `Top | `Bot -> (may, must) | ||
| | `Lifted c -> | ||
| let count = Waiters.cardinal relevant_waiters in | ||
| (* Add 1 as the thread calling wait at the moment will not be MHP with itself *) | ||
| let min_cap = (BatOption.default Z.zero (Capacity.I.minimal c)) in | ||
| if Z.leq min_cap Z.one then | ||
| (may, must) | ||
| else if Z.geq (Z.of_int (count + 1)) min_cap then | ||
| (* This is quite a cute problem: Do (min_cap-1) elements exist in the set such that | ||
| MHP is pairwise true? This solution is a sledgehammer, there should be something much | ||
| better algorithmically (beyond just laziness) *) | ||
michael-schwarz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| let must = | ||
| let waiters = Waiters.elements relevant_waiters in | ||
| let min_cap = Z.to_int min_cap in | ||
| let can_proceed_pred seq = | ||
| let rec doit seq = match Seq.uncons seq with | ||
| | None -> true | ||
| | Some (h, t) -> Seq.for_all (MHPplusLock.mhp h) t && doit t | ||
michael-schwarz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| in | ||
| doit seq | ||
| in | ||
| let can_proceed = exists_k can_proceed_pred (min_cap - 1) relevant_waiters in | ||
| if not can_proceed then raise Analyses.Deadcode; | ||
| (* limit to this case to avoid having to construct all permutations above *) | ||
| if BatList.compare_length_with waiters (min_cap - 1) = 0 then | ||
| List.fold_left (fun acc elem -> | ||
| let tid = MHPplusLock.tid elem in | ||
| let curr = MustObserved.find tid acc in | ||
| let must' = MustObserved.add tid (Barriers.add addr curr) acc in | ||
| must' | ||
| ) must waiters | ||
| else | ||
| must | ||
| in | ||
| (may, must) | ||
| else | ||
| raise Analyses.Deadcode; | ||
| with Analyses.Deadcode -> D.bot () | ||
| in | ||
| let (may, must) = List.fold_left (fun acc b-> D.join acc (handle_one b)) (D.bot ()) barriers in | ||
| if Barriers.is_empty may then raise Analyses.Deadcode; | ||
| (may, must) | ||
| | BarrierInit { barrier; attr; count } -> | ||
| let multitprocess = not @@ Queries.AD.is_null @@ man.ask (Queries.MayPointTo attr) in | ||
| if multitprocess then M.warn "Barrier initialized with a non-NULL attr argument. Handled as if PTHREAD_PROCESS_SHARED potentially set."; | ||
| let count = man.ask (Queries.EvalInt count) in | ||
| let publish_one b = man.sideg b (multitprocess, count, Waiters.bot ()) in | ||
| let barriers = possible_vinfos (Analyses.ask_of_man man) barrier in | ||
| List.iter publish_one barriers; | ||
| man.local | ||
| | _ -> man.local | ||
|
|
||
| let startstate v = (Barriers.empty (), MustObserved.empty ()) | ||
| let threadenter man ~multiple lval f args = [man.local] | ||
| let exitstate v = (Barriers.empty (), MustObserved.empty ()) | ||
|
|
||
| module A = | ||
| struct | ||
| include Lattice.Prod3 (Barriers) (MustObserved) (TID) | ||
| let name () = "barriers" | ||
| let may_race (may_await_t1, must_observed_by_t1, t1) (may_await_t2, must_observed_by_t2, t2) = | ||
| let observed_from_t2 = MustObserved.find t2 must_observed_by_t1 in | ||
| if not (Barriers.subset observed_from_t2 may_await_t2) then | ||
| false | ||
| else | ||
| let observed_from_t1 = MustObserved.find t1 must_observed_by_t2 in | ||
| Barriers.subset observed_from_t1 may_await_t1 | ||
| let should_print f = true | ||
| end | ||
|
|
||
| let access man (a: Queries.access) = | ||
| let (may,must) = man.local in | ||
| let mhp = MHP.current (Analyses.ask_of_man man) in | ||
| (may, must, mhp.tid) | ||
| end | ||
|
|
||
| let _ = | ||
| MCP.register_analysis (module Spec : MCPSpec) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| // NOMAC PARAM: --set ana.activated[+] 'pthreadBarriers' | ||
| #include<pthread.h> | ||
| #include<stdio.h> | ||
| #include<unistd.h> | ||
| #include<goblint.h> | ||
|
|
||
| int g; | ||
|
|
||
| pthread_barrier_t barrier; | ||
|
|
||
|
|
||
| int main(int argc, char const *argv[]) | ||
| { | ||
| int top; | ||
| int i = 0; | ||
|
|
||
| pthread_barrier_init(&barrier, NULL, 2); | ||
|
|
||
| if(top) { | ||
| pthread_barrier_wait(&barrier); | ||
| // Unreachable | ||
| i = 1; | ||
| } | ||
|
|
||
| __goblint_check(i == 0); | ||
michael-schwarz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return 0; | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.