diff options
Diffstat (limited to 'src/backend/access')
-rw-r--r-- | src/backend/access/transam/varsup.c | 52 |
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); |