aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access')
-rw-r--r--src/backend/access/transam/varsup.c52
1 files changed, 22 insertions, 30 deletions
diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c
index cede579d731..664735b3814 100644
--- a/src/backend/access/transam/varsup.c
+++ b/src/backend/access/transam/varsup.c
@@ -186,20 +186,23 @@ GetNewTransactionId(bool isSubXact)
* latestCompletedXid is present in the ProcArray, which is essential for
* correct OldestXmin tracking; see src/backend/access/transam/README.
*
- * XXX by storing xid into MyPgXact without acquiring ProcArrayLock, we
- * are relying on fetch/store of an xid to be atomic, else other backends
- * might see a partially-set xid here. But holding both locks at once
- * would be a nasty concurrency hit. So for now, assume atomicity.
- *
* Note that readers of PGXACT xid fields should be careful to fetch the
* value only once, rather than assume they can read a value multiple
- * times and get the same answer each time.
+ * times and get the same answer each time. Note we are assuming that
+ * TransactionId and int fetch/store are atomic.
*
* The same comments apply to the subxact xid count and overflow fields.
*
- * A solution to the atomic-store problem would be to give each PGXACT its
- * own spinlock used only for fetching/storing that PGXACT's xid and
- * related fields.
+ * Use of a write barrier prevents dangerous code rearrangement in this
+ * function; other backends could otherwise e.g. be examining my subxids
+ * info concurrently, and we don't want them to see an invalid
+ * intermediate state, such as an incremented nxids before the array entry
+ * is filled.
+ *
+ * Other processes that read nxids should do so before reading xids
+ * elements with a pg_read_barrier() in between, so that they can be sure
+ * not to read an uninitialized array element; see
+ * src/backend/storage/lmgr/README.barrier.
*
* If there's no room to fit a subtransaction XID into PGPROC, set the
* cache-overflowed flag instead. This forces readers to look in
@@ -211,31 +214,20 @@ GetNewTransactionId(bool isSubXact)
* window *will* include the parent XID, so they will deliver the correct
* answer later on when someone does have a reason to inquire.)
*/
+ if (!isSubXact)
+ MyPgXact->xid = xid; /* LWLockRelease acts as barrier */
+ else
{
- /*
- * Use volatile pointer to prevent code rearrangement; other backends
- * could be examining my subxids info concurrently, and we don't want
- * them to see an invalid intermediate state, such as incrementing
- * nxids before filling the array entry. Note we are assuming that
- * TransactionId and int fetch/store are atomic.
- */
- volatile PGPROC *myproc = MyProc;
- volatile PGXACT *mypgxact = MyPgXact;
+ int nxids = MyPgXact->nxids;
- if (!isSubXact)
- mypgxact->xid = xid;
- else
+ if (nxids < PGPROC_MAX_CACHED_SUBXIDS)
{
- int nxids = mypgxact->nxids;
-
- if (nxids < PGPROC_MAX_CACHED_SUBXIDS)
- {
- myproc->subxids.xids[nxids] = xid;
- mypgxact->nxids = nxids + 1;
- }
- else
- mypgxact->overflowed = true;
+ MyProc->subxids.xids[nxids] = xid;
+ pg_write_barrier();
+ MyPgXact->nxids = nxids + 1;
}
+ else
+ MyPgXact->overflowed = true;
}
LWLockRelease(XidGenLock);