61
61
#include "port/pg_lfind.h"
62
62
#include "storage/proc.h"
63
63
#include "storage/procarray.h"
64
- #include "storage/spin.h"
65
64
#include "utils/acl.h"
66
65
#include "utils/builtins.h"
67
66
#include "utils/rel.h"
@@ -82,7 +81,6 @@ typedef struct ProcArrayStruct
82
81
int numKnownAssignedXids ; /* current # of valid entries */
83
82
int tailKnownAssignedXids ; /* index of oldest valid element */
84
83
int headKnownAssignedXids ; /* index of newest element, + 1 */
85
- slock_t known_assigned_xids_lck ; /* protects head/tail pointers */
86
84
87
85
/*
88
86
* Highest subxid that has been removed from KnownAssignedXids array to
@@ -441,7 +439,6 @@ CreateSharedProcArray(void)
441
439
procArray -> numKnownAssignedXids = 0 ;
442
440
procArray -> tailKnownAssignedXids = 0 ;
443
441
procArray -> headKnownAssignedXids = 0 ;
444
- SpinLockInit (& procArray -> known_assigned_xids_lck );
445
442
procArray -> lastOverflowedXid = InvalidTransactionId ;
446
443
procArray -> replication_slot_xmin = InvalidTransactionId ;
447
444
procArray -> replication_slot_catalog_xmin = InvalidTransactionId ;
@@ -4533,22 +4530,19 @@ KnownAssignedTransactionIdsIdleMaintenance(void)
4533
4530
* during normal running). Compressing unused entries out of the array
4534
4531
* likewise requires exclusive lock. To add XIDs to the array, we just insert
4535
4532
* 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).
4544
4538
*
4545
4539
* Algorithmic analysis:
4546
4540
*
4547
4541
* If we have a maximum of M slots, with N XIDs currently spread across
4548
4542
* S elements then we have N <= S <= M always.
4549
4543
*
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)
4552
4546
* * Compressing the array is O(S) and requires exclusive lock
4553
4547
* * Removing an XID is O(logS) and requires exclusive lock
4554
4548
* * Taking a snapshot is O(S) and requires shared lock
@@ -4778,22 +4772,15 @@ KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid,
4778
4772
pArray -> numKnownAssignedXids += nxids ;
4779
4773
4780
4774
/*
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.
4788
4779
*/
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 ;
4797
4784
}
4798
4785
4799
4786
/*
@@ -4815,20 +4802,15 @@ KnownAssignedXidsSearch(TransactionId xid, bool remove)
4815
4802
int tail ;
4816
4803
int result_index = -1 ;
4817
4804
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 */
4832
4814
4833
4815
/*
4834
4816
* Standard binary search. Note we can ignore the KnownAssignedXidsValid
@@ -5066,13 +5048,11 @@ KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin,
5066
5048
* cannot enter and then leave the array while we hold ProcArrayLock. We
5067
5049
* might miss newly-added xids, but they should be >= xmax so irrelevant
5068
5050
* anyway.
5069
- *
5070
- * Must take spinlock to ensure we see up-to-date array contents.
5071
5051
*/
5072
- SpinLockAcquire (& procArray -> known_assigned_xids_lck );
5073
5052
tail = procArray -> tailKnownAssignedXids ;
5074
5053
head = procArray -> headKnownAssignedXids ;
5075
- SpinLockRelease (& procArray -> known_assigned_xids_lck );
5054
+
5055
+ pg_read_barrier (); /* pairs with KnownAssignedXidsAdd */
5076
5056
5077
5057
for (i = tail ; i < head ; i ++ )
5078
5058
{
@@ -5119,10 +5099,10 @@ KnownAssignedXidsGetOldestXmin(void)
5119
5099
/*
5120
5100
* Fetch head just once, since it may change while we loop.
5121
5101
*/
5122
- SpinLockAcquire (& procArray -> known_assigned_xids_lck );
5123
5102
tail = procArray -> tailKnownAssignedXids ;
5124
5103
head = procArray -> headKnownAssignedXids ;
5125
- SpinLockRelease (& procArray -> known_assigned_xids_lck );
5104
+
5105
+ pg_read_barrier (); /* pairs with KnownAssignedXidsAdd */
5126
5106
5127
5107
for (i = tail ; i < head ; i ++ )
5128
5108
{
0 commit comments