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

Commitdc3581e

Browse files
committed
gh-134745: Change PyThread_allocate_lock() implementation to PyMutex
1 parentf6f4e8a commitdc3581e

File tree

4 files changed

+96
-491
lines changed

4 files changed

+96
-491
lines changed

‎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":

‎Python/thread.c

Lines changed: 95 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,98 @@ 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_LOCK_HANDLE_SIGNALS;
123+
}
124+
125+
if (timeout<0) {
126+
PyMutex_Lock((PyMutex*)lock);
127+
returnPY_LOCK_ACQUIRED;
128+
}
129+
else {
130+
return_PyMutex_LockTimed((PyMutex*)lock,timeout,flags);
131+
}
132+
}
133+
134+
void
135+
PyThread_release_lock(PyThread_type_locklock)
136+
{
137+
PyMutex_Unlock((PyMutex*)lock);
138+
}
139+
140+
int
141+
_PyThread_at_fork_reinit(PyThread_type_lock*lock)
142+
{
143+
PyThread_type_locknew_lock=PyThread_allocate_lock();
144+
if (new_lock==NULL) {
145+
return-1;
146+
}
147+
148+
/* bpo-6721, bpo-40089: The old lock can be in an inconsistent state.
149+
fork() can be called in the middle of an operation on the lock done by
150+
another thread. So don't call PyThread_free_lock(*lock).
151+
152+
Leak memory on purpose. Don't release the memory either since the
153+
address of a mutex is relevant. Putting two mutexes at the same address
154+
can lead to problems. */
155+
156+
*lock=new_lock;
157+
return0;
158+
}
159+
160+
int
161+
PyThread_acquire_lock(PyThread_type_locklock,intwaitflag)
162+
{
163+
returnPyThread_acquire_lock_timed(lock,waitflag ?-1 :0,/*intr_flag=*/0);
164+
}
165+
166+
74167
/* return the current thread stack size */
75168
size_t
76169
PyThread_get_stacksize(void)
@@ -261,11 +354,7 @@ PyThread_GetInfo(void)
261354
#ifdefHAVE_PTHREAD_STUBS
262355
value=Py_NewRef(Py_None);
263356
#elif defined(_POSIX_THREADS)
264-
#ifdefUSE_SEMAPHORES
265-
value=PyUnicode_FromString("semaphore");
266-
#else
267-
value=PyUnicode_FromString("mutex+cond");
268-
#endif
357+
value=PyUnicode_FromString("pymutex");
269358
if (value==NULL) {
270359
Py_DECREF(threadinfo);
271360
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