Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitebf6d13

Browse files
gh-134745: Change PyThread_allocate_lock() implementation to PyMutex (#134747)
Co-authored-by: Sam Gross <colesbury@gmail.com>
1 parent45c6c48 commitebf6d13

File tree

7 files changed

+86
-491
lines changed

7 files changed

+86
-491
lines changed

‎Include/internal/pycore_lock.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ typedef enum _PyLockFlags {
4848

4949
// Handle signals if interrupted while waiting on the lock.
5050
_PY_LOCK_HANDLE_SIGNALS =2,
51+
52+
// Fail if interrupted by a signal while waiting on the lock.
53+
_PY_FAIL_IF_INTERRUPTED =4,
5154
} _PyLockFlags;
5255

5356
// Lock a mutex with an optional timeout and additional options. See

‎Lib/test/test_sys.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,7 @@ def test_thread_info(self):
729729
info=sys.thread_info
730730
self.assertEqual(len(info),3)
731731
self.assertIn(info.name, ('nt','pthread','pthread-stubs','solaris',None))
732-
self.assertIn(info.lock, ('semaphore','mutex+cond',None))
732+
self.assertIn(info.lock, ('pymutex',None))
733733
ifsys.platform.startswith(("linux","android","freebsd")):
734734
self.assertEqual(info.name,"pthread")
735735
elifsys.platform=="win32":
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Change:c:func:`!PyThread_allocate_lock` implementation to ``PyMutex``.
2+
On Windows,:c:func:`!PyThread_acquire_lock_timed` now supports the *intr_flag*
3+
parameter: it can be interrupted. Patch by Victor Stinner.

‎Python/lock.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ _PyMutex_LockTimed(PyMutex *m, PyTime_t timeout, _PyLockFlags flags)
119119
returnPY_LOCK_INTR;
120120
}
121121
}
122+
elseif (ret==Py_PARK_INTR&& (flags&_PY_FAIL_IF_INTERRUPTED)) {
123+
returnPY_LOCK_INTR;
124+
}
122125
elseif (ret==Py_PARK_TIMEOUT) {
123126
assert(timeout >=0);
124127
returnPY_LOCK_FAILURE;

‎Python/thread.c

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939
constlong longPY_TIMEOUT_MAX=PY_TIMEOUT_MAX_VALUE;
4040

4141

42-
staticvoidPyThread__init_thread(void);/* Forward */
42+
/* Forward declaration */
43+
staticvoidPyThread__init_thread(void);
4344

4445
#defineinitialized _PyRuntime.threads.initialized
4546

@@ -71,6 +72,79 @@ PyThread_init_thread(void)
7172
#endif
7273

7374

75+
/*
76+
* Lock support.
77+
*/
78+
79+
PyThread_type_lock
80+
PyThread_allocate_lock(void)
81+
{
82+
if (!initialized) {
83+
PyThread_init_thread();
84+
}
85+
86+
PyMutex*lock= (PyMutex*)PyMem_RawMalloc(sizeof(PyMutex));
87+
if (lock) {
88+
*lock= (PyMutex){0};
89+
}
90+
91+
return (PyThread_type_lock)lock;
92+
}
93+
94+
void
95+
PyThread_free_lock(PyThread_type_locklock)
96+
{
97+
PyMem_RawFree(lock);
98+
}
99+
100+
PyLockStatus
101+
PyThread_acquire_lock_timed(PyThread_type_locklock,PY_TIMEOUT_Tmicroseconds,
102+
intintr_flag)
103+
{
104+
PyTime_ttimeout;// relative timeout
105+
if (microseconds >=0) {
106+
// bpo-41710: PyThread_acquire_lock_timed() cannot report timeout
107+
// overflow to the caller, so clamp the timeout to
108+
// [PyTime_MIN, PyTime_MAX].
109+
//
110+
// PyTime_MAX nanoseconds is around 292.3 years.
111+
//
112+
// _thread.Lock.acquire() and _thread.RLock.acquire() raise an
113+
// OverflowError if microseconds is greater than PY_TIMEOUT_MAX.
114+
timeout=_PyTime_FromMicrosecondsClamp(microseconds);
115+
}
116+
else {
117+
timeout=-1;
118+
}
119+
120+
_PyLockFlagsflags=_Py_LOCK_DONT_DETACH;
121+
if (intr_flag) {
122+
flags |=_PY_FAIL_IF_INTERRUPTED;
123+
}
124+
125+
return_PyMutex_LockTimed((PyMutex*)lock,timeout,flags);
126+
}
127+
128+
void
129+
PyThread_release_lock(PyThread_type_locklock)
130+
{
131+
PyMutex_Unlock((PyMutex*)lock);
132+
}
133+
134+
int
135+
_PyThread_at_fork_reinit(PyThread_type_lock*lock)
136+
{
137+
_PyMutex_at_fork_reinit((PyMutex*)lock);
138+
return0;
139+
}
140+
141+
int
142+
PyThread_acquire_lock(PyThread_type_locklock,intwaitflag)
143+
{
144+
returnPyThread_acquire_lock_timed(lock,waitflag ?-1 :0,/*intr_flag=*/0);
145+
}
146+
147+
74148
/* return the current thread stack size */
75149
size_t
76150
PyThread_get_stacksize(void)
@@ -261,11 +335,7 @@ PyThread_GetInfo(void)
261335
#ifdefHAVE_PTHREAD_STUBS
262336
value=Py_NewRef(Py_None);
263337
#elif defined(_POSIX_THREADS)
264-
#ifdefUSE_SEMAPHORES
265-
value=PyUnicode_FromString("semaphore");
266-
#else
267-
value=PyUnicode_FromString("mutex+cond");
268-
#endif
338+
value=PyUnicode_FromString("pymutex");
269339
if (value==NULL) {
270340
Py_DECREF(threadinfo);
271341
returnNULL;

‎Python/thread_nt.h

Lines changed: 0 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -300,98 +300,6 @@ PyThread_hang_thread(void)
300300
}
301301
}
302302

303-
/*
304-
* Lock support. It has to be implemented as semaphores.
305-
* I [Dag] tried to implement it with mutex but I could find a way to
306-
* tell whether a thread already own the lock or not.
307-
*/
308-
PyThread_type_lock
309-
PyThread_allocate_lock(void)
310-
{
311-
PNRMUTEXmutex;
312-
313-
if (!initialized)
314-
PyThread_init_thread();
315-
316-
mutex=AllocNonRecursiveMutex() ;
317-
318-
PyThread_type_lockaLock= (PyThread_type_lock)mutex;
319-
assert(aLock);
320-
321-
returnaLock;
322-
}
323-
324-
void
325-
PyThread_free_lock(PyThread_type_lockaLock)
326-
{
327-
FreeNonRecursiveMutex(aLock) ;
328-
}
329-
330-
// WaitForSingleObject() accepts timeout in milliseconds in the range
331-
// [0; 0xFFFFFFFE] (DWORD type). INFINITE value (0xFFFFFFFF) means no
332-
// timeout. 0xFFFFFFFE milliseconds is around 49.7 days.
333-
constDWORDTIMEOUT_MS_MAX=0xFFFFFFFE;
334-
335-
/*
336-
* Return 1 on success if the lock was acquired
337-
*
338-
* and 0 if the lock was not acquired. This means a 0 is returned
339-
* if the lock has already been acquired by this thread!
340-
*/
341-
PyLockStatus
342-
PyThread_acquire_lock_timed(PyThread_type_lockaLock,
343-
PY_TIMEOUT_Tmicroseconds,intintr_flag)
344-
{
345-
assert(aLock);
346-
347-
/* Fow now, intr_flag does nothing on Windows, and lock acquires are
348-
* uninterruptible. */
349-
PyLockStatussuccess;
350-
PY_TIMEOUT_Tmilliseconds;
351-
352-
if (microseconds >=0) {
353-
milliseconds=microseconds /1000;
354-
// Round milliseconds away from zero
355-
if (microseconds %1000>0) {
356-
milliseconds++;
357-
}
358-
if (milliseconds> (PY_TIMEOUT_T)TIMEOUT_MS_MAX) {
359-
// bpo-41710: PyThread_acquire_lock_timed() cannot report timeout
360-
// overflow to the caller, so clamp the timeout to
361-
// [0, TIMEOUT_MS_MAX] milliseconds.
362-
//
363-
// _thread.Lock.acquire() and _thread.RLock.acquire() raise an
364-
// OverflowError if microseconds is greater than PY_TIMEOUT_MAX.
365-
milliseconds=TIMEOUT_MS_MAX;
366-
}
367-
assert(milliseconds!=INFINITE);
368-
}
369-
else {
370-
milliseconds=INFINITE;
371-
}
372-
373-
if (EnterNonRecursiveMutex((PNRMUTEX)aLock,
374-
(DWORD)milliseconds)==WAIT_OBJECT_0) {
375-
success=PY_LOCK_ACQUIRED;
376-
}
377-
else {
378-
success=PY_LOCK_FAILURE;
379-
}
380-
381-
returnsuccess;
382-
}
383-
int
384-
PyThread_acquire_lock(PyThread_type_lockaLock,intwaitflag)
385-
{
386-
returnPyThread_acquire_lock_timed(aLock,waitflag ?-1 :0,0);
387-
}
388-
389-
void
390-
PyThread_release_lock(PyThread_type_lockaLock)
391-
{
392-
assert(aLock);
393-
(void)LeaveNonRecursiveMutex((PNRMUTEX)aLock);
394-
}
395303

396304
/* minimum/maximum thread stack sizes supported */
397305
#defineTHREAD_MIN_STACKSIZE 0x8000/* 32 KiB */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp