-
Notifications
You must be signed in to change notification settings - Fork 352
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
Continuation of #3054: enable spurious reads in TB #3067
Conversation
@rustbot author |
@rustbot ready |
@rustbot author |
The |
@rustbot ready |
@rustbot author |
// which asserts that | ||
// retag x | ||
// read y | ||
// write x | ||
// is UB. |
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.
Here it's not clear which operation happens in which thread.
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.
In fact the comments in this file are not coherent... first it says
// read x || retag y (&mut, protect)
// -- sync --
// || write y
but later it says
// read y
// retag x
// write x
Is this mixing up x
and y
? Something doesn't check out.
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.
Oops, I was planning to make the names consistent across read_retag_no_race
and spurious_read
(x
in thread 1, y
in thread 2, x
gets read, y
gets written), but it looks like I started in and didn't finish the process.
Great, thanks. :) |
Reserved loses permissions too quickly. Adding more fine-grained behavior of Reserved lets it lose write permissions only temporarily. Protected tags receive a read access on initialized locations.
62feb30
to
f95bcbb
Compare
Looking great! |
☀️ Test successful - checks-actions |
…, r=RalfJung TB: Refine protector end semantics Tree Borrows has protector end tag semantics, namely that protectors ending cause a [special implicit read](https://perso.crans.org/vanille/treebor/diff.0.html) on all locations protected by that protector that have actually been accessed. See also #3067. While this is enough for ensuring protectors allow adding/reordering reads, it does not prove that one can reorder writes. For this, we need to make this stronger, by making this implicit read be a write in cases when there was a write to the location protected by that protector, i.e. if the permission is `Active`. There is a test that shows why this behavior is necessary, see `tests/fail/tree_borrows/protector-write-lazy.rs`.
The last additions to the test suite of TB left some unresolved
#[should_panic]
that these new modifications solve.Problem
Recall that the issues were arising from the interleavings that follow.
A.
Reserved -> Frozen
has visible effects after function exitThe transition
Reserved -> Frozen
irreversibly blocks write accesses to the tag, so in the interleaving belowy
initiallyReserved
becomesFrozen
only in the target where a spurious read throughx
is inserted. This makes the later write throughy
UB only in the target and not in the source.B. Protectors only announce their presence on retag
There is a read-on-reborrow for protected locations, but if the retag of
x
occurs before that ofy
and there is no explicit access throughx
, theny
is unaware of the existence ofx
. This is problematic because a spurious read inserted throughx
between the retag ofy
and the return of the function protectingx
is a noalias violation in the target without UB in the source.Step 1: Finer behavior for
Reserved
Since one problem is that
Reserved -> Frozen
has consequences beyond function exit, we decide to remove this transition entirely. To replace it we introduce a new subtype ofReserved
with the extra booleanaliased
set.Reserved { aliased: true }
forbids child accesses, but only temporarily: it has no effect on activation once the tag is no longer protected.This makes the semantics of Tree Borrows slightly weaker in favor of being more similar to noalias.
This solves interleaving A., but B. is still a problem and the exhaustive tests do not pass yet.
Step 2: Read on function exit
Protected tags issue a "reminder" that they are protected until this instant inclusive, in the form of an implicit read (symmetrically to the implicit read on retag). This ensures that if the periods on which two tags
x
andy
are protected overlap then no matter the interleaving of retags and returns, there is either a protector currently active or a read that has been emitted, both of which temporarily block activation.This makes the exhaustive test designed previously pass, but it has an effect on the ability to return an activated pointer that I had not foreseen before implementing it.
Step 2': Do not propagate to children
A naive implementation of Step 2 makes the following code UB:
This is unacceptable, and a simple fix is to make this implicit read visible only to foreign tags.
We still lack hindsight on the ramifications of this decision, and the fact that the problematic pattern was only discovered because it occured in one completely unrelated test (with a cryptic error message) is worrying. We should be vigilant as to how this interacts with the rest of the model.
TODO
As of commit #281c30, the data race model has not been fully updated.
We have removed the reborrow of mutable references counting as a write access, but we still need the implicit read of function exit to count as a read.