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