Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
410840a
gh-108724: Add PyMutex and _PyParkingLot APIs
colesbury Aug 24, 2023
6db39dc
Add news entry
colesbury Sep 12, 2023
e624733
Revert change to Modules/_testcapi/parts.h
colesbury Sep 12, 2023
83e60fb
Update Tools/c-analyzer/cpython/ignored.tsv
colesbury Sep 12, 2023
3161e17
Fix _Py_atomic_store_ptr_release on winarm64
colesbury Sep 12, 2023
3ab7110
Support pthread_stubs.h and require threads for lock tests
colesbury Sep 12, 2023
153a0b3
Clean-up Windows includes and ifdefs
colesbury Sep 12, 2023
f963fd8
Fix Raspbian build
colesbury Sep 12, 2023
6f49ae7
Fix wasm tests.
colesbury Sep 13, 2023
779a401
Fix indentation
colesbury Sep 13, 2023
3200ef5
Rename PyEvent_TimedWait and _PyMutex_LockTimed
colesbury Sep 14, 2023
880a263
more_waiters -> has_more_waiters
colesbury Sep 14, 2023
717b3c9
Remove _PyMutex_State typedef
colesbury Sep 14, 2023
23b91b0
Update docs
colesbury Sep 14, 2023
279c56a
Include cpython/pyatomic.h via pyatomic.h
colesbury Sep 14, 2023
8d8035c
Use compound initializer in test_lock.c
colesbury Sep 14, 2023
417e754
Apply suggestions from code review
colesbury Sep 14, 2023
3ee97b1
Changes from review:
colesbury Sep 14, 2023
95b0d87
Remove thread-local data in parking_lot.c
colesbury Sep 15, 2023
3d1d2e1
Add doc for NUM_BUCKETS
colesbury Sep 15, 2023
e043a8e
Make use of Py_PARK_INTR more explicit in _PySemaphore_PlatformWait
colesbury Sep 15, 2023
6b1d8f9
Statically initialize buckets in parking_lot.c
colesbury Sep 15, 2023
1af0bff
Rename validate_addr to atomic_memcmp
colesbury Sep 15, 2023
f2073d0
Add is_unparking to struct wait_entry in parking_lot.c
colesbury Sep 15, 2023
8f1645b
Use callback in _PyParkingLot_Unpark
colesbury Sep 15, 2023
a0261c1
Simplify _PySemaphore_Wait.
colesbury Sep 15, 2023
6d4565d
check-c-globals: increase limit for parking_lot.c
colesbury Sep 15, 2023
a8ce6be
Changes from review
colesbury Sep 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Changes from review
  • Loading branch information
colesbury committed Sep 18, 2023
commit a8ce6be7026f14f9f8e788bc2380eb58cd8ad7ef
22 changes: 11 additions & 11 deletions Python/lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ static const int MAX_SPIN_COUNT = 0;
#endif

struct mutex_entry {
// The time at which the thread should be handed off the lock. Written by
// the waiting thread.
// The time after which the unlocking thread should hand off lock ownership
// directly to the waiting thread. Written by the waiting thread.
_PyTime_t time_to_be_fair;

// Set to 1 if the lock was handed off. Written by the unlocking thread.
int handoff;
int handed_off;
};

static void
Expand All @@ -56,7 +56,7 @@ PyLockStatus
_PyMutex_LockTimed(PyMutex *m, _PyTime_t timeout, _PyLockFlags flags)
{
uint8_t v = _Py_atomic_load_uint8_relaxed(&m->v);
if ((v & _Py_LOCKED) == _Py_UNLOCKED) {
if ((v & _Py_LOCKED) == 0) {
if (_Py_atomic_compare_exchange_uint8(&m->v, &v, v|_Py_LOCKED)) {
return PY_LOCK_ACQUIRED;
}
Expand All @@ -73,12 +73,12 @@ _PyMutex_LockTimed(PyMutex *m, _PyTime_t timeout, _PyLockFlags flags)

struct mutex_entry entry = {
.time_to_be_fair = now + TIME_TO_BE_FAIR_NS,
.handoff = 0,
.handed_off = 0,
};

Py_ssize_t spin_count = 0;
for (;;) {
if (!(v & _Py_LOCKED)) {
if ((v & _Py_LOCKED) == 0) {
// The lock is unlocked. Try to grab it.
if (_Py_atomic_compare_exchange_uint8(&m->v, &v, v|_Py_LOCKED)) {
return PY_LOCK_ACQUIRED;
Expand Down Expand Up @@ -109,7 +109,7 @@ _PyMutex_LockTimed(PyMutex *m, _PyTime_t timeout, _PyLockFlags flags)
int ret = _PyParkingLot_Park(&m->v, &newv, sizeof(newv), timeout,
&entry, (flags & _PY_LOCK_DETACH) != 0);
if (ret == Py_PARK_OK) {
if (entry.handoff) {
if (entry.handed_off) {
// We own the lock now.
assert(_Py_atomic_load_uint8_relaxed(&m->v) & _Py_LOCKED);
return PY_LOCK_ACQUIRED;
Expand Down Expand Up @@ -145,7 +145,7 @@ mutex_unpark(PyMutex *m, struct mutex_entry *entry, int has_more_waiters)
_PyTime_t now = _PyTime_GetMonotonicClock();
int should_be_fair = now > entry->time_to_be_fair;

entry->handoff = should_be_fair;
entry->handed_off = should_be_fair;
if (should_be_fair) {
v |= _Py_LOCKED;
}
Expand All @@ -161,7 +161,7 @@ _PyMutex_TryUnlock(PyMutex *m)
{
uint8_t v = _Py_atomic_load_uint8(&m->v);
for (;;) {
if ((v & _Py_LOCKED) == _Py_UNLOCKED) {
if ((v & _Py_LOCKED) == 0) {
// error: the mutex is not locked
return -1;
}
Expand Down Expand Up @@ -200,7 +200,7 @@ _PyRawMutex_LockSlow(_PyRawMutex *m)

uintptr_t v = _Py_atomic_load_uintptr(&m->v);
for (;;) {
if ((v & _Py_LOCKED) == _Py_UNLOCKED) {
if ((v & _Py_LOCKED) == 0) {
// Unlocked: try to grab it (even if it has a waiter).
if (_Py_atomic_compare_exchange_uintptr(&m->v, &v, v|_Py_LOCKED)) {
break;
Expand Down Expand Up @@ -228,7 +228,7 @@ _PyRawMutex_UnlockSlow(_PyRawMutex *m)
{
uintptr_t v = _Py_atomic_load_uintptr(&m->v);
for (;;) {
if ((v & _Py_LOCKED) == _Py_UNLOCKED) {
if ((v & _Py_LOCKED) == 0) {
Py_FatalError("unlocking mutex that is not locked");
}

Expand Down