-
Notifications
You must be signed in to change notification settings - Fork 85
Improve MHP precision using ancestor locksets #1865
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
base: master
Are you sure you want to change the base?
Conversation
…ter-proc lock regression tests
Stupid question: Is that not a problem of how CL is constructed that is in principle independent of path-sensitivity and can, e.g., also arise as a result of context-sensitivity? Assuming Would Then, Afterthought: how do you deal with ambiguous creators? I guess giving up when the thread id is no longer unique? The push for a more modular solution was that I implemented something that looks somewhat similar on the surface (#1065) which turned out to cause a slow-down by a factor of 4 (#1120), which we have still not fixed. But maybe we can go with the descendant global invariant for now and then check later if it causes any slowdown we're unwilling to pay on real programs? We can still go for the more involved local solution later if this is the case? |
I haven't thought about that, but you are right, we do have the same problem here. In 1db14cb I added another test, which covers this. However, I think that the fix for the path-sensitivity problem should fix this, too, since in that case, we would again have another creation statement without the mutex locked and add it to the tainted set (or use your approach).
I was assuming initially, that the three cases in the section "Notes on non-unique thread ids" from the PR-summary are the only relevant cases, where ambiguous creators could be a problem, but thinking about it, that is a really bold claim, which I just should not make without knowing a proof for it. Checking if the descendant threads have a unique thread id wouldn't even result in a loss of precision in most cases[1], since the
I'm amazed, that is so much nicer O_O
I am going to implement the other case, too, since I am also somewhat intrigued now, how the two approaches will compare. Thanks a lot for your remarks! [1] it would if we never unlock and never join, but I think that this wouldn't be too tragic |
|
Is there a way of accessing all (must-)ancestors of a thread? Getting all threads in general or all keys of a global analysis would also work, but I don't see any of that to be possible at first glance. If that's the cas, I can add a |
The simpler version is now done (at least that's what I believe) and in sync with the PR-summary. If you want to review it already, you can do so. Otherwise, feel free to ignore the review request until the alternative solution is also implemented. |
I probably won't get around to it until some time next week, but I added it to my TODO (list / stack / multiset). |
I think in general no. However, if you only need the must ancestors of definite thread ids (which I guess is true in your case?), you can reconstruct them as the new create edge is simply appended to the sequence of the parent. Such a function |
First part of #1805.
Second case will be handled in a separate PR.
To be handled
Non-transitive version
When creating$t_1$ , $t_0$ must hold a lock $l$ . If $l$ is not released before $t_1$ is definitely joined into $t_0$ , $t_1$ is protected by $l$ .
Examples
graph TB; subgraph t1; E["..."]-->F["return;"]; end; subgraph t0; A["lock(l);"]-->B; B["create(t1);"]-->C; C["join(t1);"]-->D["unlock(l);"] end; B-.->E F-.->Cgraph TB; subgraph t1; E["..."]-->F["return;"]; end; subgraph t0; A["lock(l);"]-->B; B["create(t1);"]-->C[return;]; end; B-.->EGeneral version
Let$t_1$ be a must-ancestor of $t_0$ . When creating $t_1$ , $t_0$ must hold a lock $l$ . If $l$ is not released before $t_d$ is definitely joined into $t_0$ , $t_d$ is protected by $l$ .
Example
graph TB; subgraph td; G["..."]-->H["return;"]; end; subgraph t1; E["create(td);"]-->F["return;"]; end; subgraph t0; A["lock(l);"]-->B; B["create(t1);"]-->C; C["join(td);"]-->D["unlock(l);"] end; B-.->E E-.->G H-.->CDependency Analyses
Conditions to satisfy
create(t1)increate(t1)inunlock(l)inPossible solutions
1. Explicitly listing all descendants
MapBotContributions
create(t1):unlock(l):unlockof unknown mutex:Rules for MHP exclusion
Program points$s_1$ with $\mathcal T_1$ , $\mathcal L_1$ and $\mathcal{CL}_1$ and $s_2$ with $\mathcal T_2$ , $\mathcal L_2$ and $\mathcal{CL}_2$ cannot happen in parallel if at least one condition holds: