sync: preserve permit state in notify_waiters #3660
Merged
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.
Motivation
When there are no current waiters (state is EMPTY or NOTIFIED),
Notify::notify_waiters
just bumps the current generation counter and returns. But it does so non-atomically. Since the lock is held we know that the generation counter is untouched, and we cannot have entered state WAITING; we might however be overwriting NOTIFIED by EMPTY or EMPTY by NOTIFIED if we race with another thread.The former case is bad: if notify_waiters() races with notify_one(), we might overwrite NOTIFIED by EMPTY and drop a permit.
The latter case is more or less fine, because if we race with a waiter that uses up a permit we can claim to have notified it and have its permit remain. But with enough effort one can show an API contract violation.
Solution
Use an atomic increment.