Re: [PATCH 1/1] Fix: trace sched switch start/stop racy updates
From: Mathieu Desnoyers
Date: Fri Aug 16 2019 - 21:36:55 EST
----- On Aug 16, 2019, at 5:04 PM, Linus Torvalds torvalds@xxxxxxxxxxxxxxxxxxxx wrote:
> On Fri, Aug 16, 2019 at 1:49 PM Thomas Gleixner <tglx@xxxxxxxxxxxxx> wrote:
>> Can we finally put a foot down and tell compiler and standard committee
>> people to stop this insanity?
> It's already effectively done.
> Yes, values can be read from memory multiple times if they need
> reloading. So "READ_ONCE()" when the value can change is a damn good
> But it should only be used if the value *can* change. Inside a locked
> region it is actively pointless and misleading.
> Similarly, WRITE_ONCE() should only be used if you have a _reason_ for
> using it (notably if you're not holding a lock).
> If people use READ_ONCE/WRITE_ONCE when there are locks that prevent
> the values from changing, they are only making the code illegible.
> Don't do it.
I agree with your argument in the case where both read-side and write-side
are protected by the same lock: READ/WRITE_ONCE are useless then. However,
in the scenario we have here, only the write-side is protected by the lock
against concurrent updates, but reads don't take any lock.
If WRITE_ONCE has any use at all (protecting against store tearing and
invented stores), it should be used even with a lock held in this
scenario, because the lock does not prevent READ_ONCE() from observing
transient states caused by lack of WRITE_ONCE() for the update.
So why does WRITE_ONCE exist in the first place ? Is it for documentation
purposes only or are there actual situations where omitting it can cause
bugs with real-life compilers ?
In terms of code change, should we favor only introducing WRITE_ONCE
in new code, or should existing code matching those conditions be
moved to WRITE_ONCE as bug fixes ?
> But in the *absence* of locking, READ_ONCE/WRITE_ONCE is usually a
> good thing. The READ_ONCE actually tends to matter, because even if
> the value is used only once at a source level, the compiler *could*
> decide to do something else.
> The WRITE_ONCE() may or may not matter (afaik, thanks to concurrency,
> modern C standard does not allow optimistic writes anyway, and we
> wouldn't really accept such a compiler option if it did).
> But if the write is done without locking, it's good practice just to
> show you are aware of the whole "done without locking" part.