Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 119c23e

Browse files
Replace known_assigned_xids_lck with memory barriers.
This lock was introduced before memory barrier support was added, and it is only used to guarantee proper memory ordering when KnownAssignedXidsAdd() appends to the array without a lock. Now that such memory barrier support exists, we can remove the lock and use barriers instead. Suggested-by: Tom Lane Author: Michail Nikolaev Reviewed-by: Robert Haas Discussion: https://postgr.es/m/CANtu0oh0si%3DjG5z_fLeFtmYcETssQ08kLEa8b6TQqDm_cinroA%40mail.gmail.com
1 parent a899d07 commit 119c23e

File tree

1 file changed

+28
-48
lines changed

1 file changed

+28
-48
lines changed

src/backend/storage/ipc/procarray.c

Lines changed: 28 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@
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

Comments
 (0)