From: | Jeff Davis <pgsql(at)j-davis(dot)com> |
---|---|
To: | pgsql-hackers(at)postgresql(dot)org |
Subject: | Inconsistent use of "volatile" when accessing shared memory? |
Date: | 2023-11-03 06:19:03 |
Message-ID: | 784f72ac09061fe5eaa5335cc347340c367c73ac.camel@j-davis.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
I noticed that we occasionally use "volatile" to access shared memory,
but usually not; and I'm not clear on the rules for doing so. For
instance, AdvanceXLInsertBuffer() writes to XLogCtl->xlblocks[nextidx]
through a volatile pointer; but then immediately writes to XLogCtl-
>InitializedUpTo with a non-volatile pointer. There are also places in
procarray.c that make use of volatile through UINT32_ACCESS_ONCE(), and
of course there are atomics (which use volatile as well as guaranteeing
atomicity).
In theory, I think we're always supposed to access shared memory
through a volatile pointer, right? Otherwise a sufficiently smart (and
cruel) compiler could theoretically optimize away the load/store in
some surprising cases, or hold a value in a register longer than we
expect, and then any memory barriers would be useless.
But in practice we don't do that even for sensitive structures like the
one referenced by XLogCtl. My intuition up until now was that if we
access through a global pointer, then the compiler wouldn't completely
optimize away the store/load. I ran through some tests and that
assumption seems to hold up, at least in a few simple examples with gcc
at -O2, which seem to emit the loads/stores where expected.
What is the guidance here? Is the volatile pointer use in
AdvanceXLInsertBuffer() required, and if so, why not other places?
Regards,
Jeff Davis
From | Date | Subject | |
---|---|---|---|
Next Message | Richard Guo | 2023-11-03 06:46:56 | Re: Fix bogus Asserts in calc_non_nestloop_required_outer |
Previous Message | Richard Guo | 2023-11-03 06:10:45 | Re: Fix a wrong comment in setrefs.c |