-
Notifications
You must be signed in to change notification settings - Fork 76
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
Improve history thread ID may_create
#1561
base: master
Are you sure you want to change the base?
Conversation
I wonder how often (if at all) any of this actually hits: As soon as the creator is not the must-parent, it's already game over: Lines 55 to 60 in b9caf63
|
Indeed, since those are our only usages of I did a test run with coverage locally and (even to by surprise) all lines and branches are covered. But the actual usefulness of this will become clear when I try to construct regression test programs around these hypothetical improvements. |
I managed to simplify and optimize it to something reasonable by using a simple (but efficient) P.equal p (P.common_suffix p p') which is very roundabout: it constructs the common prefix (via list reversals) just to check for equality (which goes through the entire list again). In many cases the check S.subset (S.union (S.of_list p) s) (S.union (S.of_list p') s') does capture everything that's needed, but it's far from obvious that it's all that's needed (for optimality). I've now realized that the naming of the two functions is also a bit weird. I would rename:
|
aa3fb6d
to
cc7a76a
Compare
I went through all the unit tests for the improved cases and tried to construct a real program for each one. Five of them have a corresponding regression test now that also checks for the improved precision from this. For others I documented why a real program for data race regression testing at least isn't possible. |
A before vs after benchmark run on SV-COMP ConcurrencySafety with 60s timeout gives zero verdict differences and performance differences are also just within measurement noise. As to the over-approximated |
I saw you have a pending thesis on verifying the correctness of this. Do we want to wait for this or should I attempt to review it such that we can then merge it? |
I offered a thesis topic on formally verifying this but there's no student working on it (and I'm not sure if there ever will be), so we shouldn't wait for that. I've left a lot of comments for the various cases along with tests, so I hope that's sufficiently clear and convincing that this should be right. |
assert_equal true (may_be_ancestor (main >> a >> b >> b) (main >> b >> b >> a)); | ||
assert_equal true (may_be_ancestor (main >> a >> b >> b) (main >> b >> a >> b)); | ||
|
||
(* 4f6a7637b8d0dc723fe382f94bed6c822cd4a2ce passes all... *) |
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.
Why this comment?
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.
I think the reason was that there are at least two improvements after that commit (dbd4874 and c2c596f) which are supposed to improve precision, but they're not observed by the tests. That might possibly be related to the other unit test TODOs about certain cases being untestable by construction.
Since then I refactored the code, so perhaps it's no longer true. At least according to code coverage, all cases seem to be covered by something.
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.
Then we can maybe just remove the comment?
assert_equal false (may_be_ancestor (main >> a >> b >> b) (main >> b >> b)); (* from prefix *) (* infeasible for race: definitely_not_started requires (main >> a or main >> a >> b), where this must happen, to be must parent for (main >> b >> b), which it is not *) | ||
(* non-unique creates non-unique: removed elements and set must be in new set *) | ||
(* assert_equal false (may_be_ancestor (main >> a >> b >> c >> c) (main >> a >> c >> c)); *) | ||
(* TODO: cannot test due because by construction after prefix check? *) |
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.
What is the plan with this TODO?
assert_equal true (may_be_ancestor main (main >> a >> a)); | ||
assert_equal true (may_be_ancestor main (main >> a >> b >> b)); | ||
assert_equal true (may_be_ancestor (main >> a) (main >> a >> b >> b)); | ||
(* TODO: added elements condition always true by construction in tests? *) |
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.
What is the plan with this TODO?
Co-authored-by: Michael Schwarz <[email protected]>
The
may_create
function for our history-based thread IDs from the ESOP paper is quite conservative.After thinking about it for a while (in comparison to
is_must_parent
, I noticed many cases wheremay_create
can be more precise and incrementally implemented them here.I haven't constructed programs where all these thread IDs and their improvements would actually show up and matter, so these may be very obscure (or even infeasible for some other reasons I didn't notice).
Also, I'm not sure if it is now optimal, possibly not yet in the "both are non-unique" case.
TODO