6161#include "port/pg_lfind.h"
6262#include "storage/proc.h"
6363#include "storage/procarray.h"
64- #include "storage/spin.h"
6564#include "utils/acl.h"
6665#include "utils/builtins.h"
6766#include "utils/rel.h"
@@ -82,7 +81,6 @@ typedef struct ProcArrayStruct
8281 int numKnownAssignedXids ; /* current # of valid entries */
8382 int tailKnownAssignedXids ; /* index of oldest valid element */
8483 int headKnownAssignedXids ; /* index of newest element, + 1 */
85- slock_t known_assigned_xids_lck ; /* protects head/tail pointers */
8684
8785 /*
8886 * Highest subxid that has been removed from KnownAssignedXids array to
@@ -441,7 +439,6 @@ CreateSharedProcArray(void)
441439 procArray -> numKnownAssignedXids = 0 ;
442440 procArray -> tailKnownAssignedXids = 0 ;
443441 procArray -> headKnownAssignedXids = 0 ;
444- SpinLockInit (& procArray -> known_assigned_xids_lck );
445442 procArray -> lastOverflowedXid = InvalidTransactionId ;
446443 procArray -> replication_slot_xmin = InvalidTransactionId ;
447444 procArray -> replication_slot_catalog_xmin = InvalidTransactionId ;
@@ -4533,22 +4530,19 @@ KnownAssignedTransactionIdsIdleMaintenance(void)
45334530 * during normal running). Compressing unused entries out of the array
45344531 * likewise requires exclusive lock. To add XIDs to the array, we just insert
45354532 * them into slots to the right of the head pointer and then advance the head
4536- * pointer. This wouldn't require any lock at all, except that on machines
4537- * with weak memory ordering we need to be careful that other processors
4538- * see the array element changes before they see the head pointer change.
4539- * We handle this by using a spinlock to protect reads and writes of the
4540- * head/tail pointers. (We could dispense with the spinlock if we were to
4541- * create suitable memory access barrier primitives and use those instead.)
4542- * The spinlock must be taken to read or write the head/tail pointers unless
4543- * the caller holds ProcArrayLock exclusively.
4533+ * pointer. This doesn't require any lock at all, but on machines with weak
4534+ * memory ordering, we need to be careful that other processors see the array
4535+ * element changes before they see the head pointer change. We handle this by
4536+ * using memory barriers when reading or writing the head/tail pointers (unless
4537+ * the caller holds ProcArrayLock exclusively).
45444538 *
45454539 * Algorithmic analysis:
45464540 *
45474541 * If we have a maximum of M slots, with N XIDs currently spread across
45484542 * S elements then we have N <= S <= M always.
45494543 *
4550- * * Adding a new XID is O(1) and needs little locking (unless compression
4551- * must happen)
4544+ * * Adding a new XID is O(1) and needs no lock (unless compression must
4545+ * happen)
45524546 * * Compressing the array is O(S) and requires exclusive lock
45534547 * * Removing an XID is O(logS) and requires exclusive lock
45544548 * * Taking a snapshot is O(S) and requires shared lock
@@ -4778,22 +4772,15 @@ KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid,
47784772 pArray -> numKnownAssignedXids += nxids ;
47794773
47804774 /*
4781- * Now update the head pointer. We use a spinlock to protect this
4782- * pointer, not because the update is likely to be non-atomic, but to
4783- * ensure that other processors see the above array updates before they
4784- * see the head pointer change.
4785- *
4786- * If we're holding ProcArrayLock exclusively, there's no need to take the
4787- * spinlock.
4775+ * Now update the head pointer. We use a write barrier to ensure that
4776+ * other processors see the above array updates before they see the head
4777+ * pointer change. The barrier isn't required if we're holding
4778+ * ProcArrayLock exclusively.
47884779 */
4789- if (exclusive_lock )
4790- pArray -> headKnownAssignedXids = head ;
4791- else
4792- {
4793- SpinLockAcquire (& pArray -> known_assigned_xids_lck );
4794- pArray -> headKnownAssignedXids = head ;
4795- SpinLockRelease (& pArray -> known_assigned_xids_lck );
4796- }
4780+ if (!exclusive_lock )
4781+ pg_write_barrier ();
4782+
4783+ pArray -> headKnownAssignedXids = head ;
47974784}
47984785
47994786/*
@@ -4815,20 +4802,15 @@ KnownAssignedXidsSearch(TransactionId xid, bool remove)
48154802 int tail ;
48164803 int result_index = -1 ;
48174804
4818- if (remove )
4819- {
4820- /* we hold ProcArrayLock exclusively, so no need for spinlock */
4821- tail = pArray -> tailKnownAssignedXids ;
4822- head = pArray -> headKnownAssignedXids ;
4823- }
4824- else
4825- {
4826- /* take spinlock to ensure we see up-to-date array contents */
4827- SpinLockAcquire (& pArray -> known_assigned_xids_lck );
4828- tail = pArray -> tailKnownAssignedXids ;
4829- head = pArray -> headKnownAssignedXids ;
4830- SpinLockRelease (& pArray -> known_assigned_xids_lck );
4831- }
4805+ tail = pArray -> tailKnownAssignedXids ;
4806+ head = pArray -> headKnownAssignedXids ;
4807+
4808+ /*
4809+ * Only the startup process removes entries, so we don't need the read
4810+ * barrier in that case.
4811+ */
4812+ if (!remove )
4813+ pg_read_barrier (); /* pairs with KnownAssignedXidsAdd */
48324814
48334815 /*
48344816 * Standard binary search. Note we can ignore the KnownAssignedXidsValid
@@ -5066,13 +5048,11 @@ KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin,
50665048 * cannot enter and then leave the array while we hold ProcArrayLock. We
50675049 * might miss newly-added xids, but they should be >= xmax so irrelevant
50685050 * anyway.
5069- *
5070- * Must take spinlock to ensure we see up-to-date array contents.
50715051 */
5072- SpinLockAcquire (& procArray -> known_assigned_xids_lck );
50735052 tail = procArray -> tailKnownAssignedXids ;
50745053 head = procArray -> headKnownAssignedXids ;
5075- SpinLockRelease (& procArray -> known_assigned_xids_lck );
5054+
5055+ pg_read_barrier (); /* pairs with KnownAssignedXidsAdd */
50765056
50775057 for (i = tail ; i < head ; i ++ )
50785058 {
@@ -5119,10 +5099,10 @@ KnownAssignedXidsGetOldestXmin(void)
51195099 /*
51205100 * Fetch head just once, since it may change while we loop.
51215101 */
5122- SpinLockAcquire (& procArray -> known_assigned_xids_lck );
51235102 tail = procArray -> tailKnownAssignedXids ;
51245103 head = procArray -> headKnownAssignedXids ;
5125- SpinLockRelease (& procArray -> known_assigned_xids_lck );
5104+
5105+ pg_read_barrier (); /* pairs with KnownAssignedXidsAdd */
51265106
51275107 for (i = tail ; i < head ; i ++ )
51285108 {
0 commit comments