8000 WIP · python/cpython@1ebcb70 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1ebcb70

Browse files
committed
WIP
1 parent ce91111 commit 1ebcb70

File tree

3 files changed

+82
-5
lines changed

3 files changed

+82
-5
lines changed

Include/internal/pycore_lock.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,12 +212,12 @@ typedef struct {
212212
} _PyRWMutex;
213213

214214
// Read lock
215-
extern void _PyRWMutex_RLock(_PyRWMutex *rwmutex);
216-
extern void _PyRWMutex_RUnlock(_PyRWMutex *rwmutex);
215+
PyAPI_FUNC(void) _PyRWMutex_RLock(_PyRWMutex *rwmutex);
216+
PyAPI_FUNC(void) _PyRWMutex_RUnlock(_PyRWMutex *rwmutex);
217217

218218
// Write lock
219-
extern void _PyRWMutex_Lock(_PyRWMutex *rwmutex);
220-
extern void _PyRWMutex_Unlock(_PyRWMutex *rwmutex);
219+
PyAPI_FUNC(void) _PyRWMutex_Lock(_PyRWMutex *rwmutex);
220+
PyAPI_FUNC(void) _PyRWMutex_Unlock(_PyRWMutex *rwmutex);
221221

222222

223223
#ifdef __cplusplus

Modules/_testinternalcapi/test_lock.c

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,10 +372,85 @@ test_lock_once(PyObject *self, PyObject *obj)
372372
Py_RETURN_NONE;
373373
}
374374

375+
struct test_rwlock_data {
376+
_PyRWMutex rw;
377+
PyEvent step1;
378+
PyEvent step2;
379+
PyEvent step3;
380+
PyEvent done;
381+
};
382+
383+
static void
384+
rdlock_thread(void *arg)
385+
{
386+
struct test_rwlock_data *test_data = arg;
387+
388+
// First acquire the lock in read mode
389+
_PyRWMutex_RLock(&test_data->rw);
390+
PyEvent_Wait(&test_data->step1);
391+
printf("unlocking\n");
392+
_PyRWMutex_RUnlock(&test_data->rw);
393+
394+
_PyRWMutex_RLock(&test_data->rw);
395+
PyEvent_Wait(&test_data->step3);
396+
_PyRWMutex_RUnlock(&test_data->rw);
397+
398+
_PyEvent_Notify(&test_data->done);
399+
}
400+
static void
401+
wrlock_thread(void *arg)
402+
{
403+
struct test_rwlock_data *test_data = arg;
404+
405+
// First acquire the lock in write mode
406+
_PyRWMutex_Lock(&test_data->rw);
407+
PyEvent_Wait(&test_data->step2);
408+
_PyRWMutex_Unlock(&test_data->rw);
409+
410+
_PyEvent_Notify(&test_data->done);
411+
}
412+
413+
static void
414+
wait_until(uintptr_t *ptr, uintptr_t value)
415+
{
416+
// wait up to two seconds for *ptr == value
417+
int iters = 0;
418+
uintptr_t bits;
419+
do {
420+
pysleep(10);
421+
bits = _Py_atomic_load_uintptr(ptr);
422+
iters++;
423+
} while (bits != value && iters < 200);
424+
}
425+
375426
static PyObject *
376427
test_lock_rwlock(PyObject *self, PyObject *obj)
377428
{
378-
_PyRWMutex rwlock = {0};
429+
struct test_rwlock_data test_data = {0};
430+
431+
// Start two readers
432+
PyThread_start_new_thread(rdlock_thread, &test_data);
433+
PyThread_start_new_thread(rdlock_thread, &test_data);
434+
435+
// wait up to two seconds for the threads to attempt to read-lock "rw"
436+
wait_until(&test_data.rw.bits, 8);
437+
assert(test_data.rw.bits == 8);
438+
439+
// start writer (while readers hold lock)
440+
PyThread_start_new_thread(wrlock_thread, &test_data);
441+
wait_until(&test_data.rw.bits, 10);
442+
assert(test_data.rw.bits == 10);
443+
444+
// readers release lock, writer should re-acquire it
445+
_PyEvent_Notify(&test_data.step1);
446+
wait_until(&test_data.rw.bits, 3);
447+
assert(test_data.rw.bits == 3);
448+
449+
450+
_PyEvent_Notify(&test_data.step2);
451+
_PyEvent_Notify(&test_data.step3);
452+
PyEvent_Wait(&test_data.done);
453+
379454
Py_RETURN_NONE;
380455
}
381456

Python/pystate.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2016,6 +2016,7 @@ _PyThreadState_Park(PyThreadState *tstate)
20162016
}
20172017

20182018

2019+
#ifdef Py_GIL_DISABLED
20192020
// Interpreter for _Py_FOR_EACH_THREAD(). For global stop-the-world events,
20202021
// we start with the first interpreter and then iterate over all interpreters.
20212022
// For per-interpreter stop-the-world events, we only operate on the one
@@ -2142,6 +2143,7 @@ start_the_world(struct _stoptheworld_state *stw)
21422143
}
21432144
PyMutex_Unlock(&stw->mutex);
21442145
}
2146+
#endif // Py_GIL_DISABLED
21452147

21462148
void
21472149
_PyRuntimeState_StopTheWorld(_PyRuntimeState *runtime)

0 commit comments

Comments
 (0)
0