"=?utf-8?B?55uP5LiA?=" <[email protected]> writes:
> The code in GetSnapshotData() that read the `xid` field of PGXACT
> struct has a dependency on code in GetNewTransactionId() that write
> `MyPgXact->xid`. It means that the store of xid should happen before the
> load of it. In C11, we can use [Release-Acquire
> ordering](https://en.cppreference.com/w/c/atomic/memory_order#Release-Acquire_ordering)
> to achieve it. But now, there is no special operation to do it(, and the
> [volatile](https://en.cppreference.com/w/c/language/volatile) keyword should
> not play any role in this situation).
> So it means that when a backend A returns from GetNewTransactionId(), the
> newval of `MyPgXact->xid` maybe just in CPU store buffer, or CPU cache
> line, so the newval is not yet visible to backend B that calling
> GetSnapshotData(). So the assumption that 'all top-level XIDs <=
> latestCompletedXid are either present in the ProcArray, or not running
> anymore' may not be safe.
You'e ignoring the memory barriers that are implicit in LWLock
acquisition and release; as well as the fact that it's transaction
end, not start, that needs to be interlocked. Please read the section
"Interlocking Transaction Begin, Transaction End, and Snapshots"
in src/backend/access/transam/README.
regards, tom lane