Skip to content

Commit d2f4649

Browse files
authored
gh-145685: Remove _PySeqLock that is not used anymore (gh-155243)
1 parent 2dcb32b commit d2f4649

3 files changed

Lines changed: 0 additions & 110 deletions

File tree

Include/internal/pycore_lock.h

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -212,40 +212,6 @@ PyAPI_FUNC(void) _PyRWMutex_RUnlock(_PyRWMutex *rwmutex);
212212
PyAPI_FUNC(void) _PyRWMutex_Lock(_PyRWMutex *rwmutex);
213213
PyAPI_FUNC(void) _PyRWMutex_Unlock(_PyRWMutex *rwmutex);
214214

215-
// Similar to linux seqlock: https://en.wikipedia.org/wiki/Seqlock
216-
// We use a sequence number to lock the writer, an even sequence means we're unlocked, an odd
217-
// sequence means we're locked. Readers will read the sequence before attempting to read the
218-
// underlying data and then read the sequence number again after reading the data. If the
219-
// sequence has not changed the data is valid.
220-
//
221-
// Differs a little bit in that we use CAS on sequence as the lock, instead of a separate spin lock.
222-
// The writer can also detect that the undelering data has not changed and abandon the write
223-
// and restore the previous sequence.
224-
typedef struct {
225-
uint32_t sequence;
226-
} _PySeqLock;
227-
228-
// Lock the sequence lock for the writer
229-
PyAPI_FUNC(void) _PySeqLock_LockWrite(_PySeqLock *seqlock);
230-
231-
// Unlock the sequence lock and move to the next sequence number.
232-
PyAPI_FUNC(void) _PySeqLock_UnlockWrite(_PySeqLock *seqlock);
233-
234-
// Abandon the current update indicating that no mutations have occurred
235-
// and restore the previous sequence value.
236-
PyAPI_FUNC(void) _PySeqLock_AbandonWrite(_PySeqLock *seqlock);
237-
238-
// Begin a read operation and return the current sequence number.
239-
PyAPI_FUNC(uint32_t) _PySeqLock_BeginRead(_PySeqLock *seqlock);
240-
241-
// End the read operation and confirm that the sequence number has not changed.
242-
// Returns 1 if the read was successful or 0 if the read should be retried.
243-
PyAPI_FUNC(int) _PySeqLock_EndRead(_PySeqLock *seqlock, uint32_t previous);
244-
245-
// Check if the lock was held during a fork and clear the lock. Returns 1
246-
// if the lock was held and any associated data should be cleared.
247-
PyAPI_FUNC(int) _PySeqLock_AfterFork(_PySeqLock *seqlock);
248-
249215
#ifdef __cplusplus
250216
}
251217
#endif

Objects/typeobject.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#include "pycore_dict.h" // _PyDict_KeysSize()
99
#include "pycore_function.h" // _PyFunction_GetVersionForCurrentState()
1010
#include "pycore_interpframe.h" // _PyInterpreterFrame
11-
#include "pycore_lock.h" // _PySeqLock_*
1211
#include "pycore_long.h" // _PyLong_IsNegative(), _PyLong_GetOne()
1312
#include "pycore_memoryobject.h" // _PyMemoryView_FromBufferProc()
1413
#include "pycore_modsupport.h" // _PyArg_NoKwnames()

Python/lock.c

Lines changed: 0 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -574,81 +574,6 @@ _PyRWMutex_Unlock(_PyRWMutex *rwmutex)
574574
}
575575
}
576576

577-
#define SEQLOCK_IS_UPDATING(sequence) (sequence & 0x01)
578-
579-
void _PySeqLock_LockWrite(_PySeqLock *seqlock)
580-
{
581-
// lock by moving to an odd sequence number
582-
uint32_t prev = _Py_atomic_load_uint32_relaxed(&seqlock->sequence);
583-
while (1) {
584-
if (SEQLOCK_IS_UPDATING(prev)) {
585-
// Someone else is currently updating the cache
586-
_Py_yield();
587-
prev = _Py_atomic_load_uint32_relaxed(&seqlock->sequence);
588-
}
589-
else if (_Py_atomic_compare_exchange_uint32(&seqlock->sequence, &prev, prev + 1)) {
590-
// We've locked the cache
591-
_Py_atomic_fence_release();
592-
break;
593-
}
594-
else {
595-
_Py_yield();
596-
}
597-
}
598-
}
599-
600-
void _PySeqLock_AbandonWrite(_PySeqLock *seqlock)
601-
{
602-
uint32_t new_seq = _Py_atomic_load_uint32_relaxed(&seqlock->sequence) - 1;
603-
assert(!SEQLOCK_IS_UPDATING(new_seq));
604-
_Py_atomic_store_uint32(&seqlock->sequence, new_seq);
605-
}
606-
607-
void _PySeqLock_UnlockWrite(_PySeqLock *seqlock)
608-
{
609-
uint32_t new_seq = _Py_atomic_load_uint32_relaxed(&seqlock->sequence) + 1;
610-
assert(!SEQLOCK_IS_UPDATING(new_seq));
611-
_Py_atomic_store_uint32(&seqlock->sequence, new_seq);
612-
}
613-
614-
uint32_t _PySeqLock_BeginRead(_PySeqLock *seqlock)
615-
{
616-
uint32_t sequence = _Py_atomic_load_uint32_acquire(&seqlock->sequence);
617-
while (SEQLOCK_IS_UPDATING(sequence)) {
618-
_Py_yield();
619-
sequence = _Py_atomic_load_uint32_acquire(&seqlock->sequence);
620-
}
621-
622-
return sequence;
623-
}
624-
625-
int _PySeqLock_EndRead(_PySeqLock *seqlock, uint32_t previous)
626-
{
627-
// gh-121368: We need an explicit acquire fence here to ensure that
628-
// this load of the sequence number is not reordered before any loads
629-
// within the read lock.
630-
_Py_atomic_fence_acquire();
631-
632-
if (_Py_atomic_load_uint32_relaxed(&seqlock->sequence) == previous) {
633-
return 1;
634-
}
635-
636-
_Py_yield();
637-
return 0;
638-
}
639-
640-
int _PySeqLock_AfterFork(_PySeqLock *seqlock)
641-
{
642-
// Synchronize again and validate that the entry hasn't been updated
643-
// while we were readying the values.
644-
if (SEQLOCK_IS_UPDATING(seqlock->sequence)) {
645-
seqlock->sequence = 0;
646-
return 1;
647-
}
648-
649-
return 0;
650-
}
651-
652577
#undef PyMutex_Lock
653578
void
654579
PyMutex_Lock(PyMutex *m)

0 commit comments

Comments
 (0)