blob: f6217e672f7aa6f139d0d4c1f05cccec6c4fb464 [file] [log] [blame]
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001
2/* Thread module */
3/* Interface to Sjoerd's portable C thread library */
4
Barry Warsawd0c10421996-12-17 00:05:22 +00005#include "Python.h"
Victor Stinnercd590a72019-05-28 00:39:52 +02006#include "pycore_pylifecycle.h"
Victor Stinner4a21e572020-04-15 02:35:41 +02007#include "pycore_interp.h" // _PyInterpreterState.num_threads
8#include "pycore_pystate.h" // _PyThreadState_Init()
9#include <stddef.h> // offsetof()
Victor Stinner61040132020-12-18 01:39:00 +010010#include "structmember.h" // PyMemberDef
Guido van Rossum1984f1e1992-08-04 12:41:02 +000011
Victor Stinner8203c732020-12-16 12:20:33 +010012// ThreadError is just an alias to PyExc_RuntimeError
13#define ThreadError PyExc_RuntimeError
14
15_Py_IDENTIFIER(__dict__);
Guido van Rossum1984f1e1992-08-04 12:41:02 +000016
Victor Stinnerbd303c12013-11-07 23:07:29 +010017_Py_IDENTIFIER(stderr);
Victor Stinnercd590a72019-05-28 00:39:52 +020018_Py_IDENTIFIER(flush);
Victor Stinnerbd303c12013-11-07 23:07:29 +010019
Victor Stinner8203c732020-12-16 12:20:33 +010020
Victor Stinner61040132020-12-18 01:39:00 +010021// Forward declarations
22static struct PyModuleDef thread_module;
23
24
25typedef struct {
26 PyTypeObject *lock_type;
27 PyTypeObject *local_type;
28 PyTypeObject *local_dummy_type;
29} thread_module_state;
30
31static inline thread_module_state*
32get_thread_state(PyObject *module)
33{
34 void *state = PyModule_GetState(module);
35 assert(state != NULL);
36 return (thread_module_state *)state;
37}
38
39
Guido van Rossum1984f1e1992-08-04 12:41:02 +000040/* Lock objects */
41
42typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000043 PyObject_HEAD
44 PyThread_type_lock lock_lock;
45 PyObject *in_weakreflist;
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +000046 char locked; /* for sanity checking */
Guido van Rossum1984f1e1992-08-04 12:41:02 +000047} lockobject;
48
Victor Stinner61040132020-12-18 01:39:00 +010049static int
50lock_traverse(lockobject *self, visitproc visit, void *arg)
51{
52 Py_VISIT(Py_TYPE(self));
53 return 0;
54}
55
Guido van Rossum1984f1e1992-08-04 12:41:02 +000056static void
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +000057lock_dealloc(lockobject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +000058{
Victor Stinner8203c732020-12-16 12:20:33 +010059 if (self->in_weakreflist != NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000060 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner8203c732020-12-16 12:20:33 +010061 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000062 if (self->lock_lock != NULL) {
63 /* Unlock the lock so it's safe to free it */
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +000064 if (self->locked)
65 PyThread_release_lock(self->lock_lock);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000066 PyThread_free_lock(self->lock_lock);
67 }
Victor Stinner61040132020-12-18 01:39:00 +010068 PyTypeObject *tp = Py_TYPE(self);
69 tp->tp_free((PyObject*)self);
70 Py_DECREF(tp);
Guido van Rossum1984f1e1992-08-04 12:41:02 +000071}
72
Antoine Pitrou810023d2010-12-15 22:59:16 +000073/* Helper to acquire an interruptible lock with a timeout. If the lock acquire
74 * is interrupted, signal handlers are run, and if they raise an exception,
75 * PY_LOCK_INTR is returned. Otherwise, PY_LOCK_ACQUIRED or PY_LOCK_FAILURE
Raymond Hettinger15f44ab2016-08-30 10:47:49 -070076 * are returned, depending on whether the lock can be acquired within the
Antoine Pitrou810023d2010-12-15 22:59:16 +000077 * timeout.
78 */
79static PyLockStatus
Victor Stinnerf5faad22015-03-28 03:52:05 +010080acquire_timed(PyThread_type_lock lock, _PyTime_t timeout)
Antoine Pitrou810023d2010-12-15 22:59:16 +000081{
82 PyLockStatus r;
Victor Stinnerf5faad22015-03-28 03:52:05 +010083 _PyTime_t endtime = 0;
Antoine Pitrou810023d2010-12-15 22:59:16 +000084
Victor Stinner8203c732020-12-16 12:20:33 +010085 if (timeout > 0) {
Victor Stinnerf5faad22015-03-28 03:52:05 +010086 endtime = _PyTime_GetMonotonicClock() + timeout;
Victor Stinner8203c732020-12-16 12:20:33 +010087 }
Antoine Pitrou810023d2010-12-15 22:59:16 +000088
89 do {
Victor Stinner8203c732020-12-16 12:20:33 +010090 _PyTime_t microseconds;
Victor Stinner869e1772015-03-30 03:49:14 +020091 microseconds = _PyTime_AsMicroseconds(timeout, _PyTime_ROUND_CEILING);
Victor Stinnerf5faad22015-03-28 03:52:05 +010092
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +000093 /* first a simple non-blocking try without releasing the GIL */
94 r = PyThread_acquire_lock_timed(lock, 0, 0);
95 if (r == PY_LOCK_FAILURE && microseconds != 0) {
96 Py_BEGIN_ALLOW_THREADS
97 r = PyThread_acquire_lock_timed(lock, microseconds, 1);
98 Py_END_ALLOW_THREADS
Victor Stinner357f5152013-11-05 15:10:19 +010099 }
Antoine Pitrou810023d2010-12-15 22:59:16 +0000100
101 if (r == PY_LOCK_INTR) {
102 /* Run signal handlers if we were interrupted. Propagate
103 * exceptions from signal handlers, such as KeyboardInterrupt, by
104 * passing up PY_LOCK_INTR. */
105 if (Py_MakePendingCalls() < 0) {
106 return PY_LOCK_INTR;
107 }
108
109 /* If we're using a timeout, recompute the timeout after processing
110 * signals, since those can take time. */
Victor Stinnerf5faad22015-03-28 03:52:05 +0100111 if (timeout > 0) {
112 timeout = endtime - _PyTime_GetMonotonicClock();
Antoine Pitrou810023d2010-12-15 22:59:16 +0000113
114 /* Check for negative values, since those mean block forever.
115 */
Victor Stinner6aa446c2015-03-30 21:33:51 +0200116 if (timeout < 0) {
Antoine Pitrou810023d2010-12-15 22:59:16 +0000117 r = PY_LOCK_FAILURE;
118 }
119 }
120 }
121 } while (r == PY_LOCK_INTR); /* Retry if we were interrupted. */
122
123 return r;
124}
125
Victor Stinnerf5faad22015-03-28 03:52:05 +0100126static int
127lock_acquire_parse_args(PyObject *args, PyObject *kwds,
128 _PyTime_t *timeout)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000129{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000130 char *kwlist[] = {"blocking", "timeout", NULL};
131 int blocking = 1;
Victor Stinnerf5faad22015-03-28 03:52:05 +0100132 PyObject *timeout_obj = NULL;
Victor Stinner13019fd2015-04-03 13:10:54 +0200133 const _PyTime_t unset_timeout = _PyTime_FromSeconds(-1);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000134
Victor Stinnerf5faad22015-03-28 03:52:05 +0100135 *timeout = unset_timeout ;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000136
Victor Stinnerf5faad22015-03-28 03:52:05 +0100137 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO:acquire", kwlist,
138 &blocking, &timeout_obj))
139 return -1;
140
141 if (timeout_obj
Victor Stinner869e1772015-03-30 03:49:14 +0200142 && _PyTime_FromSecondsObject(timeout,
Pablo Galindo59af94f2017-10-18 08:13:09 +0100143 timeout_obj, _PyTime_ROUND_TIMEOUT) < 0)
Victor Stinnerf5faad22015-03-28 03:52:05 +0100144 return -1;
145
146 if (!blocking && *timeout != unset_timeout ) {
147 PyErr_SetString(PyExc_ValueError,
148 "can't specify a timeout for a non-blocking call");
149 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000150 }
Victor Stinnerf5faad22015-03-28 03:52:05 +0100151 if (*timeout < 0 && *timeout != unset_timeout) {
152 PyErr_SetString(PyExc_ValueError,
153 "timeout value must be positive");
154 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000155 }
156 if (!blocking)
Victor Stinnerf5faad22015-03-28 03:52:05 +0100157 *timeout = 0;
158 else if (*timeout != unset_timeout) {
159 _PyTime_t microseconds;
160
Pablo Galindo59af94f2017-10-18 08:13:09 +0100161 microseconds = _PyTime_AsMicroseconds(*timeout, _PyTime_ROUND_TIMEOUT);
Victor Stinnerf5faad22015-03-28 03:52:05 +0100162 if (microseconds >= PY_TIMEOUT_MAX) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000163 PyErr_SetString(PyExc_OverflowError,
164 "timeout value is too large");
Victor Stinnerf5faad22015-03-28 03:52:05 +0100165 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000166 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000167 }
Victor Stinnerf5faad22015-03-28 03:52:05 +0100168 return 0;
169}
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000170
Victor Stinnerf5faad22015-03-28 03:52:05 +0100171static PyObject *
172lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds)
173{
174 _PyTime_t timeout;
Victor Stinnerf5faad22015-03-28 03:52:05 +0100175 if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
176 return NULL;
177
Victor Stinner8203c732020-12-16 12:20:33 +0100178 PyLockStatus r = acquire_timed(self->lock_lock, timeout);
Antoine Pitrou810023d2010-12-15 22:59:16 +0000179 if (r == PY_LOCK_INTR) {
180 return NULL;
181 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000182
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000183 if (r == PY_LOCK_ACQUIRED)
184 self->locked = 1;
Antoine Pitrou810023d2010-12-15 22:59:16 +0000185 return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000186}
187
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000188PyDoc_STRVAR(acquire_doc,
Berker Peksag720e6552016-05-02 12:25:35 +0300189"acquire(blocking=True, timeout=-1) -> bool\n\
Guido van Rossumf6694362006-03-10 02:28:35 +0000190(acquire_lock() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000191\n\
192Lock the lock. Without argument, this blocks if the lock is already\n\
193locked (even by the same thread), waiting for another thread to release\n\
R David Murray95b71102013-02-04 10:15:58 -0500194the lock, and return True once the lock is acquired.\n\
Guido van Rossum8fdc75b2002-04-07 06:32:21 +0000195With an argument, this will only block if the argument is true,\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000196and the return value reflects whether the lock is acquired.\n\
Antoine Pitrou810023d2010-12-15 22:59:16 +0000197The blocking operation is interruptible.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000198
Barry Warsawd0c10421996-12-17 00:05:22 +0000199static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530200lock_PyThread_release_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000201{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000202 /* Sanity check: the lock must be locked */
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000203 if (!self->locked) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000204 PyErr_SetString(ThreadError, "release unlocked lock");
205 return NULL;
206 }
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000207
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000208 PyThread_release_lock(self->lock_lock);
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000209 self->locked = 0;
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200210 Py_RETURN_NONE;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000211}
212
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000213PyDoc_STRVAR(release_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000214"release()\n\
Guido van Rossumf6694362006-03-10 02:28:35 +0000215(release_lock() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000216\n\
217Release the lock, allowing another thread that is blocked waiting for\n\
218the lock to acquire the lock. The lock must be in the locked state,\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000219but it needn't be locked by the same thread that unlocks it.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000220
Barry Warsawd0c10421996-12-17 00:05:22 +0000221static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530222lock_locked_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000223{
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000224 return PyBool_FromLong((long)self->locked);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000225}
226
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000227PyDoc_STRVAR(locked_doc,
Guido van Rossum8fdc75b2002-04-07 06:32:21 +0000228"locked() -> bool\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000229(locked_lock() is an obsolete synonym)\n\
230\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000231Return whether the lock is in the locked state.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000232
Raymond Hettinger62f4dad2014-05-25 18:22:35 -0700233static PyObject *
234lock_repr(lockobject *self)
235{
236 return PyUnicode_FromFormat("<%s %s object at %p>",
237 self->locked ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self);
238}
239
Victor Stinner87255be2020-04-07 23:11:49 +0200240#ifdef HAVE_FORK
241static PyObject *
242lock__at_fork_reinit(lockobject *self, PyObject *Py_UNUSED(args))
243{
244 if (_PyThread_at_fork_reinit(&self->lock_lock) < 0) {
245 PyErr_SetString(ThreadError, "failed to reinitialize lock at fork");
246 return NULL;
247 }
248
249 self->locked = 0;
250
251 Py_RETURN_NONE;
252}
253#endif /* HAVE_FORK */
254
255
Barry Warsawd0c10421996-12-17 00:05:22 +0000256static PyMethodDef lock_methods[] = {
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200257 {"acquire_lock", (PyCFunction)(void(*)(void))lock_PyThread_acquire_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000258 METH_VARARGS | METH_KEYWORDS, acquire_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200259 {"acquire", (PyCFunction)(void(*)(void))lock_PyThread_acquire_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000260 METH_VARARGS | METH_KEYWORDS, acquire_doc},
261 {"release_lock", (PyCFunction)lock_PyThread_release_lock,
262 METH_NOARGS, release_doc},
263 {"release", (PyCFunction)lock_PyThread_release_lock,
264 METH_NOARGS, release_doc},
265 {"locked_lock", (PyCFunction)lock_locked_lock,
266 METH_NOARGS, locked_doc},
267 {"locked", (PyCFunction)lock_locked_lock,
268 METH_NOARGS, locked_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200269 {"__enter__", (PyCFunction)(void(*)(void))lock_PyThread_acquire_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000270 METH_VARARGS | METH_KEYWORDS, acquire_doc},
271 {"__exit__", (PyCFunction)lock_PyThread_release_lock,
272 METH_VARARGS, release_doc},
Victor Stinner87255be2020-04-07 23:11:49 +0200273#ifdef HAVE_FORK
274 {"_at_fork_reinit", (PyCFunction)lock__at_fork_reinit,
275 METH_NOARGS, NULL},
276#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000277 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000278};
279
Victor Stinner8203c732020-12-16 12:20:33 +0100280PyDoc_STRVAR(lock_doc,
281"A lock object is a synchronization primitive. To create a lock,\n\
282call threading.Lock(). Methods are:\n\
283\n\
284acquire() -- lock the lock, possibly blocking until it can be obtained\n\
285release() -- unlock of the lock\n\
286locked() -- test whether the lock is currently locked\n\
287\n\
288A lock is not owned by the thread that locked it; another thread may\n\
289unlock it. A thread attempting to lock a lock that it has already locked\n\
290will block until another thread unlocks it. Deadlocks may ensue.");
291
Victor Stinner61040132020-12-18 01:39:00 +0100292static PyMemberDef lock_type_members[] = {
293 {"__weaklistoffset__", T_PYSSIZET, offsetof(lockobject, in_weakreflist), READONLY},
294 {NULL},
295};
296
297static PyType_Slot lock_type_slots[] = {
298 {Py_tp_dealloc, (destructor)lock_dealloc},
299 {Py_tp_repr, (reprfunc)lock_repr},
300 {Py_tp_doc, (void *)lock_doc},
301 {Py_tp_methods, lock_methods},
302 {Py_tp_traverse, lock_traverse},
303 {Py_tp_members, lock_type_members},
304 {0, 0}
305};
306
307static PyType_Spec lock_type_spec = {
308 .name = "_thread.lock",
309 .basicsize = sizeof(lockobject),
310 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
311 .slots = lock_type_slots,
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000312};
313
Antoine Pitrou434736a2009-11-10 18:46:01 +0000314/* Recursive lock objects */
315
316typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000317 PyObject_HEAD
318 PyThread_type_lock rlock_lock;
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200319 unsigned long rlock_owner;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000320 unsigned long rlock_count;
321 PyObject *in_weakreflist;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000322} rlockobject;
323
324static void
325rlock_dealloc(rlockobject *self)
326{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000327 if (self->in_weakreflist != NULL)
328 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner357f5152013-11-05 15:10:19 +0100329 /* self->rlock_lock can be NULL if PyThread_allocate_lock() failed
330 in rlock_new() */
331 if (self->rlock_lock != NULL) {
332 /* Unlock the lock so it's safe to free it */
333 if (self->rlock_count > 0)
334 PyThread_release_lock(self->rlock_lock);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000335
Victor Stinner357f5152013-11-05 15:10:19 +0100336 PyThread_free_lock(self->rlock_lock);
337 }
Victor Stinner61040132020-12-18 01:39:00 +0100338 PyTypeObject *tp = Py_TYPE(self);
339 tp->tp_free(self);
340 Py_DECREF(tp);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000341}
342
343static PyObject *
344rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
345{
Victor Stinnerf5faad22015-03-28 03:52:05 +0100346 _PyTime_t timeout;
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200347 unsigned long tid;
Antoine Pitrou810023d2010-12-15 22:59:16 +0000348 PyLockStatus r = PY_LOCK_ACQUIRED;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000349
Victor Stinnerf5faad22015-03-28 03:52:05 +0100350 if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000351 return NULL;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000352
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000353 tid = PyThread_get_thread_ident();
354 if (self->rlock_count > 0 && tid == self->rlock_owner) {
355 unsigned long count = self->rlock_count + 1;
356 if (count <= self->rlock_count) {
357 PyErr_SetString(PyExc_OverflowError,
358 "Internal lock count overflowed");
359 return NULL;
360 }
361 self->rlock_count = count;
362 Py_RETURN_TRUE;
363 }
Victor Stinnerf5faad22015-03-28 03:52:05 +0100364 r = acquire_timed(self->rlock_lock, timeout);
Antoine Pitrou810023d2010-12-15 22:59:16 +0000365 if (r == PY_LOCK_ACQUIRED) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000366 assert(self->rlock_count == 0);
367 self->rlock_owner = tid;
368 self->rlock_count = 1;
369 }
Antoine Pitrou810023d2010-12-15 22:59:16 +0000370 else if (r == PY_LOCK_INTR) {
371 return NULL;
372 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000373
Antoine Pitrou810023d2010-12-15 22:59:16 +0000374 return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000375}
376
377PyDoc_STRVAR(rlock_acquire_doc,
378"acquire(blocking=True) -> bool\n\
379\n\
380Lock the lock. `blocking` indicates whether we should wait\n\
381for the lock to be available or not. If `blocking` is False\n\
382and another thread holds the lock, the method will return False\n\
383immediately. If `blocking` is True and another thread holds\n\
384the lock, the method will wait for the lock to be released,\n\
385take it and then return True.\n\
Antoine Pitrou810023d2010-12-15 22:59:16 +0000386(note: the blocking operation is interruptible.)\n\
Antoine Pitrou434736a2009-11-10 18:46:01 +0000387\n\
388In all other cases, the method will return True immediately.\n\
389Precisely, if the current thread already holds the lock, its\n\
390internal counter is simply incremented. If nobody holds the lock,\n\
391the lock is taken and its internal counter initialized to 1.");
392
393static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530394rlock_release(rlockobject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou434736a2009-11-10 18:46:01 +0000395{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200396 unsigned long tid = PyThread_get_thread_ident();
Antoine Pitrou434736a2009-11-10 18:46:01 +0000397
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000398 if (self->rlock_count == 0 || self->rlock_owner != tid) {
399 PyErr_SetString(PyExc_RuntimeError,
400 "cannot release un-acquired lock");
401 return NULL;
402 }
403 if (--self->rlock_count == 0) {
404 self->rlock_owner = 0;
405 PyThread_release_lock(self->rlock_lock);
406 }
407 Py_RETURN_NONE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000408}
409
410PyDoc_STRVAR(rlock_release_doc,
411"release()\n\
412\n\
413Release the lock, allowing another thread that is blocked waiting for\n\
414the lock to acquire the lock. The lock must be in the locked state,\n\
415and must be locked by the same thread that unlocks it; otherwise a\n\
416`RuntimeError` is raised.\n\
417\n\
418Do note that if the lock was acquire()d several times in a row by the\n\
419current thread, release() needs to be called as many times for the lock\n\
420to be available for other threads.");
421
422static PyObject *
Victor Stinnere8794522014-01-02 12:47:24 +0100423rlock_acquire_restore(rlockobject *self, PyObject *args)
Antoine Pitrou434736a2009-11-10 18:46:01 +0000424{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200425 unsigned long owner;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000426 unsigned long count;
427 int r = 1;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000428
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200429 if (!PyArg_ParseTuple(args, "(kk):_acquire_restore", &count, &owner))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000430 return NULL;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000431
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000432 if (!PyThread_acquire_lock(self->rlock_lock, 0)) {
433 Py_BEGIN_ALLOW_THREADS
434 r = PyThread_acquire_lock(self->rlock_lock, 1);
435 Py_END_ALLOW_THREADS
436 }
437 if (!r) {
438 PyErr_SetString(ThreadError, "couldn't acquire lock");
439 return NULL;
440 }
441 assert(self->rlock_count == 0);
442 self->rlock_owner = owner;
443 self->rlock_count = count;
444 Py_RETURN_NONE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000445}
446
447PyDoc_STRVAR(rlock_acquire_restore_doc,
448"_acquire_restore(state) -> None\n\
449\n\
450For internal use by `threading.Condition`.");
451
452static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530453rlock_release_save(rlockobject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou434736a2009-11-10 18:46:01 +0000454{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200455 unsigned long owner;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000456 unsigned long count;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000457
Victor Stinnerc2824d42011-04-24 23:41:33 +0200458 if (self->rlock_count == 0) {
459 PyErr_SetString(PyExc_RuntimeError,
460 "cannot release un-acquired lock");
461 return NULL;
462 }
463
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000464 owner = self->rlock_owner;
465 count = self->rlock_count;
466 self->rlock_count = 0;
467 self->rlock_owner = 0;
468 PyThread_release_lock(self->rlock_lock);
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200469 return Py_BuildValue("kk", count, owner);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000470}
471
472PyDoc_STRVAR(rlock_release_save_doc,
473"_release_save() -> tuple\n\
474\n\
475For internal use by `threading.Condition`.");
476
477
478static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530479rlock_is_owned(rlockobject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou434736a2009-11-10 18:46:01 +0000480{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200481 unsigned long tid = PyThread_get_thread_ident();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000482
483 if (self->rlock_count > 0 && self->rlock_owner == tid) {
484 Py_RETURN_TRUE;
485 }
486 Py_RETURN_FALSE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000487}
488
489PyDoc_STRVAR(rlock_is_owned_doc,
490"_is_owned() -> bool\n\
491\n\
492For internal use by `threading.Condition`.");
493
494static PyObject *
495rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
496{
Victor Stinner87255be2020-04-07 23:11:49 +0200497 rlockobject *self = (rlockobject *) type->tp_alloc(type, 0);
498 if (self == NULL) {
499 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000500 }
Victor Stinner87255be2020-04-07 23:11:49 +0200501 self->in_weakreflist = NULL;
502 self->rlock_owner = 0;
503 self->rlock_count = 0;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000504
Victor Stinner87255be2020-04-07 23:11:49 +0200505 self->rlock_lock = PyThread_allocate_lock();
506 if (self->rlock_lock == NULL) {
507 Py_DECREF(self);
508 PyErr_SetString(ThreadError, "can't allocate lock");
509 return NULL;
510 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000511 return (PyObject *) self;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000512}
513
514static PyObject *
515rlock_repr(rlockobject *self)
516{
Raymond Hettinger62f4dad2014-05-25 18:22:35 -0700517 return PyUnicode_FromFormat("<%s %s object owner=%ld count=%lu at %p>",
518 self->rlock_count ? "locked" : "unlocked",
519 Py_TYPE(self)->tp_name, self->rlock_owner,
520 self->rlock_count, self);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000521}
522
523
Victor Stinner87255be2020-04-07 23:11:49 +0200524#ifdef HAVE_FORK
525static PyObject *
526rlock__at_fork_reinit(rlockobject *self, PyObject *Py_UNUSED(args))
527{
528 if (_PyThread_at_fork_reinit(&self->rlock_lock) < 0) {
529 PyErr_SetString(ThreadError, "failed to reinitialize lock at fork");
530 return NULL;
531 }
532
533 self->rlock_owner = 0;
534 self->rlock_count = 0;
535
536 Py_RETURN_NONE;
537}
538#endif /* HAVE_FORK */
539
540
Antoine Pitrou434736a2009-11-10 18:46:01 +0000541static PyMethodDef rlock_methods[] = {
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200542 {"acquire", (PyCFunction)(void(*)(void))rlock_acquire,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000543 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
544 {"release", (PyCFunction)rlock_release,
545 METH_NOARGS, rlock_release_doc},
546 {"_is_owned", (PyCFunction)rlock_is_owned,
547 METH_NOARGS, rlock_is_owned_doc},
548 {"_acquire_restore", (PyCFunction)rlock_acquire_restore,
Victor Stinnere8794522014-01-02 12:47:24 +0100549 METH_VARARGS, rlock_acquire_restore_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000550 {"_release_save", (PyCFunction)rlock_release_save,
551 METH_NOARGS, rlock_release_save_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200552 {"__enter__", (PyCFunction)(void(*)(void))rlock_acquire,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000553 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
554 {"__exit__", (PyCFunction)rlock_release,
555 METH_VARARGS, rlock_release_doc},
Victor Stinner87255be2020-04-07 23:11:49 +0200556#ifdef HAVE_FORK
557 {"_at_fork_reinit", (PyCFunction)rlock__at_fork_reinit,
558 METH_NOARGS, NULL},
559#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000560 {NULL, NULL} /* sentinel */
Antoine Pitrou434736a2009-11-10 18:46:01 +0000561};
562
563
Victor Stinner61040132020-12-18 01:39:00 +0100564static PyMemberDef rlock_type_members[] = {
565 {"__weaklistoffset__", T_PYSSIZET, offsetof(rlockobject, in_weakreflist), READONLY},
566 {NULL},
567};
568
569static PyType_Slot rlock_type_slots[] = {
570 {Py_tp_dealloc, (destructor)rlock_dealloc},
571 {Py_tp_repr, (reprfunc)rlock_repr},
572 {Py_tp_methods, rlock_methods},
573 {Py_tp_alloc, PyType_GenericAlloc},
574 {Py_tp_new, rlock_new},
575 {Py_tp_members, rlock_type_members},
576 {0, 0},
577};
578
579static PyType_Spec rlock_type_spec = {
580 .name = "_thread.RLock",
581 .basicsize = sizeof(rlockobject),
582 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
583 .slots = rlock_type_slots,
Antoine Pitrou434736a2009-11-10 18:46:01 +0000584};
585
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000586static lockobject *
Victor Stinner61040132020-12-18 01:39:00 +0100587newlockobject(PyObject *module)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000588{
Victor Stinner61040132020-12-18 01:39:00 +0100589 thread_module_state *state = get_thread_state(module);
590
591 PyTypeObject *type = state->lock_type;
592 lockobject *self = (lockobject *)type->tp_alloc(type, 0);
Victor Stinner8203c732020-12-16 12:20:33 +0100593 if (self == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000594 return NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100595 }
596
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000597 self->lock_lock = PyThread_allocate_lock();
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000598 self->locked = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000599 self->in_weakreflist = NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000601 if (self->lock_lock == NULL) {
602 Py_DECREF(self);
603 PyErr_SetString(ThreadError, "can't allocate lock");
604 return NULL;
605 }
606 return self;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000607}
608
Jim Fultond15dc062004-07-14 19:11:50 +0000609/* Thread-local objects */
610
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000611/* Quick overview:
612
613 We need to be able to reclaim reference cycles as soon as possible
614 (both when a thread is being terminated, or a thread-local object
615 becomes unreachable from user data). Constraints:
616 - it must not be possible for thread-state dicts to be involved in
617 reference cycles (otherwise the cyclic GC will refuse to consider
618 objects referenced from a reachable thread-state dict, even though
619 local_dealloc would clear them)
620 - the death of a thread-state dict must still imply destruction of the
621 corresponding local dicts in all thread-local objects.
622
623 Our implementation uses small "localdummy" objects in order to break
624 the reference chain. These trivial objects are hashable (using the
625 default scheme of identity hashing) and weakrefable.
626 Each thread-state holds a separate localdummy for each local object
627 (as a /strong reference/),
628 and each thread-local object holds a dict mapping /weak references/
629 of localdummies to local dicts.
630
631 Therefore:
632 - only the thread-state dict holds a strong reference to the dummies
633 - only the thread-local object holds a strong reference to the local dicts
634 - only outside objects (application- or library-level) hold strong
635 references to the thread-local objects
636 - as soon as a thread-state dict is destroyed, the weakref callbacks of all
637 dummies attached to that thread are called, and destroy the corresponding
638 local dicts from thread-local objects
639 - as soon as a thread-local object is destroyed, its local dicts are
640 destroyed and its dummies are manually removed from all thread states
641 - the GC can do its work correctly when a thread-local object is dangling,
642 without any interference from the thread-state dicts
643
644 As an additional optimization, each localdummy holds a borrowed reference
645 to the corresponding localdict. This borrowed reference is only used
646 by the thread-local object which has created the localdummy, which should
647 guarantee that the localdict still exists when accessed.
648*/
649
650typedef struct {
651 PyObject_HEAD
652 PyObject *localdict; /* Borrowed reference! */
653 PyObject *weakreflist; /* List of weak references to self */
654} localdummyobject;
655
656static void
657localdummy_dealloc(localdummyobject *self)
658{
659 if (self->weakreflist != NULL)
660 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner61040132020-12-18 01:39:00 +0100661 PyTypeObject *tp = Py_TYPE(self);
662 tp->tp_free((PyObject*)self);
663 Py_DECREF(tp);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000664}
665
Victor Stinner61040132020-12-18 01:39:00 +0100666static PyMemberDef local_dummy_type_members[] = {
667 {"__weaklistoffset__", T_PYSSIZET, offsetof(localdummyobject, weakreflist), READONLY},
668 {NULL},
669};
670
671static PyType_Slot local_dummy_type_slots[] = {
672 {Py_tp_dealloc, (destructor)localdummy_dealloc},
673 {Py_tp_doc, "Thread-local dummy"},
674 {Py_tp_members, local_dummy_type_members},
675 {0, 0}
676};
677
678static PyType_Spec local_dummy_type_spec = {
679 .name = "_thread._localdummy",
680 .basicsize = sizeof(localdummyobject),
681 .flags = Py_TPFLAGS_DEFAULT,
682 .slots = local_dummy_type_slots,
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000683};
684
685
Jim Fultond15dc062004-07-14 19:11:50 +0000686typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000687 PyObject_HEAD
688 PyObject *key;
689 PyObject *args;
690 PyObject *kw;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000691 PyObject *weakreflist; /* List of weak references to self */
692 /* A {localdummy weakref -> localdict} dict */
693 PyObject *dummies;
694 /* The callback for weakrefs to localdummies */
695 PyObject *wr_callback;
Jim Fultond15dc062004-07-14 19:11:50 +0000696} localobject;
697
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000698/* Forward declaration */
Victor Stinner61040132020-12-18 01:39:00 +0100699static PyObject *_ldict(localobject *self, thread_module_state *state);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000700static PyObject *_localdummy_destroyed(PyObject *meth_self, PyObject *dummyweakref);
701
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000702/* Create and register the dummy for the current thread.
703 Returns a borrowed reference of the corresponding local dict */
704static PyObject *
Victor Stinner61040132020-12-18 01:39:00 +0100705_local_create_dummy(localobject *self, thread_module_state *state)
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000706{
Victor Stinner8203c732020-12-16 12:20:33 +0100707 PyObject *ldict = NULL, *wr = NULL;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000708 localdummyobject *dummy = NULL;
Victor Stinner61040132020-12-18 01:39:00 +0100709 PyTypeObject *type = state->local_dummy_type;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000710
Victor Stinner8203c732020-12-16 12:20:33 +0100711 PyObject *tdict = PyThreadState_GetDict();
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000712 if (tdict == NULL) {
713 PyErr_SetString(PyExc_SystemError,
714 "Couldn't get thread-state dictionary");
715 goto err;
716 }
717
718 ldict = PyDict_New();
Victor Stinner8203c732020-12-16 12:20:33 +0100719 if (ldict == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000720 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100721 }
Victor Stinner61040132020-12-18 01:39:00 +0100722 dummy = (localdummyobject *) type->tp_alloc(type, 0);
Victor Stinner8203c732020-12-16 12:20:33 +0100723 if (dummy == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000724 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100725 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000726 dummy->localdict = ldict;
727 wr = PyWeakref_NewRef((PyObject *) dummy, self->wr_callback);
Victor Stinner8203c732020-12-16 12:20:33 +0100728 if (wr == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000729 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100730 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000731
732 /* As a side-effect, this will cache the weakref's hash before the
733 dummy gets deleted */
Victor Stinner8203c732020-12-16 12:20:33 +0100734 int r = PyDict_SetItem(self->dummies, wr, ldict);
735 if (r < 0) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000736 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100737 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000738 Py_CLEAR(wr);
739 r = PyDict_SetItem(tdict, self->key, (PyObject *) dummy);
Victor Stinner8203c732020-12-16 12:20:33 +0100740 if (r < 0) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000741 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100742 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000743 Py_CLEAR(dummy);
744
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000745 Py_DECREF(ldict);
746 return ldict;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000747
748err:
749 Py_XDECREF(ldict);
750 Py_XDECREF(wr);
751 Py_XDECREF(dummy);
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000752 return NULL;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000753}
754
Jim Fultond15dc062004-07-14 19:11:50 +0000755static PyObject *
756local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
757{
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000758 static PyMethodDef wr_callback_def = {
759 "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O
760 };
Jim Fultond15dc062004-07-14 19:11:50 +0000761
Serhiy Storchakafa494fd2015-05-30 17:45:22 +0300762 if (type->tp_init == PyBaseObject_Type.tp_init) {
763 int rc = 0;
764 if (args != NULL)
765 rc = PyObject_IsTrue(args);
766 if (rc == 0 && kw != NULL)
767 rc = PyObject_IsTrue(kw);
768 if (rc != 0) {
Victor Stinner8203c732020-12-16 12:20:33 +0100769 if (rc > 0) {
Serhiy Storchakafa494fd2015-05-30 17:45:22 +0300770 PyErr_SetString(PyExc_TypeError,
771 "Initialization arguments are not supported");
Victor Stinner8203c732020-12-16 12:20:33 +0100772 }
Serhiy Storchakafa494fd2015-05-30 17:45:22 +0300773 return NULL;
774 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000775 }
Jim Fultond15dc062004-07-14 19:11:50 +0000776
Victor Stinner61040132020-12-18 01:39:00 +0100777 PyObject *module = _PyType_GetModuleByDef(type, &thread_module);
778 thread_module_state *state = get_thread_state(module);
779
780 localobject *self = (localobject *)type->tp_alloc(type, 0);
Victor Stinner8203c732020-12-16 12:20:33 +0100781 if (self == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000782 return NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100783 }
Jim Fultond15dc062004-07-14 19:11:50 +0000784
Victor Stinner8203c732020-12-16 12:20:33 +0100785 self->args = Py_XNewRef(args);
786 self->kw = Py_XNewRef(kw);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000787 self->key = PyUnicode_FromFormat("thread.local.%p", self);
Victor Stinner8203c732020-12-16 12:20:33 +0100788 if (self->key == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000789 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100790 }
Jim Fultond15dc062004-07-14 19:11:50 +0000791
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000792 self->dummies = PyDict_New();
Victor Stinner8203c732020-12-16 12:20:33 +0100793 if (self->dummies == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000794 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100795 }
Jim Fultond15dc062004-07-14 19:11:50 +0000796
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000797 /* We use a weak reference to self in the callback closure
798 in order to avoid spurious reference cycles */
Victor Stinner8203c732020-12-16 12:20:33 +0100799 PyObject *wr = PyWeakref_NewRef((PyObject *) self, NULL);
800 if (wr == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000801 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100802 }
Andrew Svetlov3ba3a3e2012-12-25 13:32:35 +0200803 self->wr_callback = PyCFunction_NewEx(&wr_callback_def, wr, NULL);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000804 Py_DECREF(wr);
Victor Stinner8203c732020-12-16 12:20:33 +0100805 if (self->wr_callback == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000806 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100807 }
Victor Stinner61040132020-12-18 01:39:00 +0100808 if (_local_create_dummy(self, state) == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000809 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100810 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000811 return (PyObject *)self;
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000812
813 err:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000814 Py_DECREF(self);
815 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000816}
817
818static int
819local_traverse(localobject *self, visitproc visit, void *arg)
820{
Victor Stinner61040132020-12-18 01:39:00 +0100821 Py_VISIT(Py_TYPE(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000822 Py_VISIT(self->args);
823 Py_VISIT(self->kw);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000824 Py_VISIT(self->dummies);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000825 return 0;
Jim Fultond15dc062004-07-14 19:11:50 +0000826}
827
828static int
829local_clear(localobject *self)
830{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000831 Py_CLEAR(self->args);
832 Py_CLEAR(self->kw);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000833 Py_CLEAR(self->dummies);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000834 Py_CLEAR(self->wr_callback);
835 /* Remove all strong references to dummies from the thread states */
Victor Stinner839184f2021-02-19 15:51:36 +0100836 if (self->key) {
837 PyInterpreterState *interp = _PyInterpreterState_GET();
838 PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
839 for(; tstate; tstate = PyThreadState_Next(tstate)) {
840 if (tstate->dict == NULL) {
841 continue;
Serhiy Storchaka8905fcc2018-12-11 08:38:03 +0200842 }
Victor Stinner839184f2021-02-19 15:51:36 +0100843 PyObject *v = _PyDict_Pop(tstate->dict, self->key, Py_None);
844 if (v != NULL) {
845 Py_DECREF(v);
846 }
847 else {
848 PyErr_Clear();
849 }
850 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000851 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000852 return 0;
853}
Jim Fultond15dc062004-07-14 19:11:50 +0000854
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000855static void
856local_dealloc(localobject *self)
857{
858 /* Weakrefs must be invalidated right now, otherwise they can be used
859 from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
Victor Stinner8203c732020-12-16 12:20:33 +0100860 if (self->weakreflist != NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000861 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner8203c732020-12-16 12:20:33 +0100862 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000863
864 PyObject_GC_UnTrack(self);
865
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000866 local_clear(self);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000867 Py_XDECREF(self->key);
Victor Stinner61040132020-12-18 01:39:00 +0100868
869 PyTypeObject *tp = Py_TYPE(self);
870 tp->tp_free((PyObject*)self);
871 Py_DECREF(tp);
Jim Fultond15dc062004-07-14 19:11:50 +0000872}
873
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000874/* Returns a borrowed reference to the local dict, creating it if necessary */
Jim Fultond15dc062004-07-14 19:11:50 +0000875static PyObject *
Victor Stinner61040132020-12-18 01:39:00 +0100876_ldict(localobject *self, thread_module_state *state)
Jim Fultond15dc062004-07-14 19:11:50 +0000877{
Victor Stinner8203c732020-12-16 12:20:33 +0100878 PyObject *tdict = PyThreadState_GetDict();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000879 if (tdict == NULL) {
880 PyErr_SetString(PyExc_SystemError,
881 "Couldn't get thread-state dictionary");
882 return NULL;
883 }
Jim Fultond15dc062004-07-14 19:11:50 +0000884
Victor Stinner8203c732020-12-16 12:20:33 +0100885 PyObject *ldict;
886 PyObject *dummy = PyDict_GetItemWithError(tdict, self->key);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000887 if (dummy == NULL) {
Serhiy Storchakaa24107b2019-02-25 17:59:46 +0200888 if (PyErr_Occurred()) {
889 return NULL;
890 }
Victor Stinner61040132020-12-18 01:39:00 +0100891 ldict = _local_create_dummy(self, state);
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000892 if (ldict == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000893 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000894
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000895 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
896 Py_TYPE(self)->tp_init((PyObject*)self,
897 self->args, self->kw) < 0) {
898 /* we need to get rid of ldict from thread so
899 we create a new one the next time we do an attr
Ezio Melotti42da6632011-03-15 05:18:48 +0200900 access */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000901 PyDict_DelItem(tdict, self->key);
902 return NULL;
903 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000904 }
905 else {
Victor Stinner61040132020-12-18 01:39:00 +0100906 assert(Py_IS_TYPE(dummy, state->local_dummy_type));
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000907 ldict = ((localdummyobject *) dummy)->localdict;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000908 }
Jim Fultond15dc062004-07-14 19:11:50 +0000909
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000910 return ldict;
Jim Fultond15dc062004-07-14 19:11:50 +0000911}
912
Jim Fultond15dc062004-07-14 19:11:50 +0000913static int
914local_setattro(localobject *self, PyObject *name, PyObject *v)
915{
Victor Stinner61040132020-12-18 01:39:00 +0100916 PyObject *module = _PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
917 thread_module_state *state = get_thread_state(module);
918
919 PyObject *ldict = _ldict(self, state);
Victor Stinner8203c732020-12-16 12:20:33 +0100920 if (ldict == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000921 return -1;
Victor Stinner8203c732020-12-16 12:20:33 +0100922 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000923
Victor Stinner8203c732020-12-16 12:20:33 +0100924 PyObject *str_dict = _PyUnicode_FromId(&PyId___dict__); // borrowed ref
925 if (str_dict == NULL) {
926 return -1;
927 }
928
929 int r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
930 if (r == -1) {
931 return -1;
932 }
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000933 if (r == 1) {
934 PyErr_Format(PyExc_AttributeError,
935 "'%.50s' object attribute '%U' is read-only",
936 Py_TYPE(self)->tp_name, name);
937 return -1;
938 }
Jim Fultond15dc062004-07-14 19:11:50 +0000939
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000940 return _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict);
Jim Fultond15dc062004-07-14 19:11:50 +0000941}
942
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000943static PyObject *local_getattro(localobject *, PyObject *);
944
Victor Stinner61040132020-12-18 01:39:00 +0100945static PyMemberDef local_type_members[] = {
946 {"__weaklistoffset__", T_PYSSIZET, offsetof(localobject, weakreflist), READONLY},
947 {NULL},
948};
949
950static PyType_Slot local_type_slots[] = {
951 {Py_tp_dealloc, (destructor)local_dealloc},
952 {Py_tp_getattro, (getattrofunc)local_getattro},
953 {Py_tp_setattro, (setattrofunc)local_setattro},
954 {Py_tp_doc, "Thread-local data"},
955 {Py_tp_traverse, (traverseproc)local_traverse},
956 {Py_tp_clear, (inquiry)local_clear},
957 {Py_tp_new, local_new},
958 {Py_tp_members, local_type_members},
959 {0, 0}
960};
961
962static PyType_Spec local_type_spec = {
963 .name = "_thread._local",
964 .basicsize = sizeof(localobject),
965 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
966 .slots = local_type_slots,
Jim Fultond15dc062004-07-14 19:11:50 +0000967};
968
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000969static PyObject *
970local_getattro(localobject *self, PyObject *name)
971{
Victor Stinner61040132020-12-18 01:39:00 +0100972 PyObject *module = _PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
973 thread_module_state *state = get_thread_state(module);
974
975 PyObject *ldict = _ldict(self, state);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000976 if (ldict == NULL)
977 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000978
Victor Stinner8203c732020-12-16 12:20:33 +0100979 PyObject *str_dict = _PyUnicode_FromId(&PyId___dict__); // borrowed ref
980 if (str_dict == NULL) {
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000981 return NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100982 }
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000983
Victor Stinner8203c732020-12-16 12:20:33 +0100984 int r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
985 if (r == 1) {
986 return Py_NewRef(ldict);
987 }
988 if (r == -1) {
989 return NULL;
990 }
991
Victor Stinner61040132020-12-18 01:39:00 +0100992 if (!Py_IS_TYPE(self, state->local_type)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000993 /* use generic lookup for subtypes */
Victor Stinner8203c732020-12-16 12:20:33 +0100994 return _PyObject_GenericGetAttrWithDict((PyObject *)self, name,
995 ldict, 0);
996 }
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000997
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000998 /* Optimization: just look in dict ourselves */
Victor Stinner8203c732020-12-16 12:20:33 +0100999 PyObject *value = PyDict_GetItemWithError(ldict, name);
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001000 if (value != NULL) {
Victor Stinner8203c732020-12-16 12:20:33 +01001001 return Py_NewRef(value);
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001002 }
Victor Stinner8203c732020-12-16 12:20:33 +01001003 if (PyErr_Occurred()) {
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001004 return NULL;
1005 }
Victor Stinner8203c732020-12-16 12:20:33 +01001006
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001007 /* Fall back on generic to get __class__ and __dict__ */
1008 return _PyObject_GenericGetAttrWithDict(
1009 (PyObject *)self, name, ldict, 0);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001010}
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001011
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001012/* Called when a dummy is destroyed. */
1013static PyObject *
1014_localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
1015{
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001016 assert(PyWeakref_CheckRef(localweakref));
Victor Stinner8203c732020-12-16 12:20:33 +01001017 PyObject *obj = PyWeakref_GET_OBJECT(localweakref);
1018 if (obj == Py_None) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001019 Py_RETURN_NONE;
Victor Stinner8203c732020-12-16 12:20:33 +01001020 }
1021
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001022 /* If the thread-local object is still alive and not being cleared,
1023 remove the corresponding local dict */
Victor Stinner8203c732020-12-16 12:20:33 +01001024 localobject *self = (localobject *)Py_NewRef(obj);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001025 if (self->dummies != NULL) {
1026 PyObject *ldict;
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001027 ldict = PyDict_GetItemWithError(self->dummies, dummyweakref);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001028 if (ldict != NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001029 PyDict_DelItem(self->dummies, dummyweakref);
1030 }
1031 if (PyErr_Occurred())
1032 PyErr_WriteUnraisable(obj);
1033 }
1034 Py_DECREF(obj);
1035 Py_RETURN_NONE;
1036}
1037
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001038/* Module functions */
1039
Guido van Rossuma027efa1997-05-05 20:56:21 +00001040struct bootstate {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001041 PyInterpreterState *interp;
1042 PyObject *func;
1043 PyObject *args;
Victor Stinner8203c732020-12-16 12:20:33 +01001044 PyObject *kwargs;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001045 PyThreadState *tstate;
Joannah Nanjekye2bc43cd2019-09-05 13:06:49 -03001046 _PyRuntimeState *runtime;
Guido van Rossuma027efa1997-05-05 20:56:21 +00001047};
1048
Victor Stinner8203c732020-12-16 12:20:33 +01001049
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001050static void
Victor Stinner8203c732020-12-16 12:20:33 +01001051thread_bootstate_free(struct bootstate *boot)
1052{
1053 Py_DECREF(boot->func);
1054 Py_DECREF(boot->args);
1055 Py_XDECREF(boot->kwargs);
1056 PyMem_Free(boot);
1057}
1058
1059
1060static void
1061thread_run(void *boot_raw)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001062{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001063 struct bootstate *boot = (struct bootstate *) boot_raw;
1064 PyThreadState *tstate;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001065
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001066 tstate = boot->tstate;
1067 tstate->thread_id = PyThread_get_thread_ident();
Victor Stinner01b1cc12019-11-20 02:27:56 +01001068 _PyThreadState_Init(tstate);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001069 PyEval_AcquireThread(tstate);
Eric Snow2ebc5ce2017-09-07 23:51:28 -06001070 tstate->interp->num_threads++;
Victor Stinner8203c732020-12-16 12:20:33 +01001071
1072 PyObject *res = PyObject_Call(boot->func, boot->args, boot->kwargs);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001073 if (res == NULL) {
1074 if (PyErr_ExceptionMatches(PyExc_SystemExit))
Victor Stinner8b095002019-05-29 02:57:56 +02001075 /* SystemExit is ignored silently */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001076 PyErr_Clear();
1077 else {
Victor Stinner8b095002019-05-29 02:57:56 +02001078 _PyErr_WriteUnraisableMsg("in thread started by", boot->func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001079 }
1080 }
Victor Stinner8b095002019-05-29 02:57:56 +02001081 else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001082 Py_DECREF(res);
Victor Stinner8b095002019-05-29 02:57:56 +02001083 }
Victor Stinner8203c732020-12-16 12:20:33 +01001084
1085 thread_bootstate_free(boot);
Eric Snow2ebc5ce2017-09-07 23:51:28 -06001086 tstate->interp->num_threads--;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001087 PyThreadState_Clear(tstate);
Victor Stinner23ef89d2020-03-18 02:26:04 +01001088 _PyThreadState_DeleteCurrent(tstate);
Victor Stinner8203c732020-12-16 12:20:33 +01001089
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001090 PyThread_exit_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001091}
1092
Barry Warsawd0c10421996-12-17 00:05:22 +00001093static PyObject *
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +00001094thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001095{
Joannah Nanjekye2bc43cd2019-09-05 13:06:49 -03001096 _PyRuntimeState *runtime = &_PyRuntime;
Victor Stinner8203c732020-12-16 12:20:33 +01001097 PyObject *func, *args, *kwargs = NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001098
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001099 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
Victor Stinner8203c732020-12-16 12:20:33 +01001100 &func, &args, &kwargs))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001101 return NULL;
1102 if (!PyCallable_Check(func)) {
1103 PyErr_SetString(PyExc_TypeError,
1104 "first arg must be callable");
1105 return NULL;
1106 }
1107 if (!PyTuple_Check(args)) {
1108 PyErr_SetString(PyExc_TypeError,
1109 "2nd arg must be a tuple");
1110 return NULL;
1111 }
Victor Stinner8203c732020-12-16 12:20:33 +01001112 if (kwargs != NULL && !PyDict_Check(kwargs)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001113 PyErr_SetString(PyExc_TypeError,
1114 "optional 3rd arg must be a dictionary");
1115 return NULL;
1116 }
Victor Stinner252346a2020-05-01 11:33:44 +02001117
1118 PyInterpreterState *interp = _PyInterpreterState_GET();
1119 if (interp->config._isolated_interpreter) {
1120 PyErr_SetString(PyExc_RuntimeError,
1121 "thread is not supported for isolated subinterpreters");
1122 return NULL;
1123 }
1124
Victor Stinner8203c732020-12-16 12:20:33 +01001125 struct bootstate *boot = PyMem_NEW(struct bootstate, 1);
1126 if (boot == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001127 return PyErr_NoMemory();
Victor Stinner8203c732020-12-16 12:20:33 +01001128 }
Victor Stinner81a7be32020-04-14 15:14:01 +02001129 boot->interp = _PyInterpreterState_GET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001130 boot->tstate = _PyThreadState_Prealloc(boot->interp);
1131 if (boot->tstate == NULL) {
Victor Stinner00d7abd2020-12-01 09:56:42 +01001132 PyMem_Free(boot);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001133 return PyErr_NoMemory();
1134 }
Victor Stinner8203c732020-12-16 12:20:33 +01001135 boot->runtime = runtime;
1136 boot->func = Py_NewRef(func);
1137 boot->args = Py_NewRef(args);
1138 boot->kwargs = Py_XNewRef(kwargs);
Victor Stinner3225b9f2020-03-09 20:56:57 +01001139
Victor Stinner8203c732020-12-16 12:20:33 +01001140 unsigned long ident = PyThread_start_new_thread(thread_run, (void*) boot);
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001141 if (ident == PYTHREAD_INVALID_THREAD_ID) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001142 PyErr_SetString(ThreadError, "can't start new thread");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001143 PyThreadState_Clear(boot->tstate);
Victor Stinner8203c732020-12-16 12:20:33 +01001144 thread_bootstate_free(boot);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001145 return NULL;
1146 }
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001147 return PyLong_FromUnsignedLong(ident);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001148}
1149
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001150PyDoc_STRVAR(start_new_doc,
Andrew M. Kuchling38300c62001-10-05 12:24:15 +00001151"start_new_thread(function, args[, kwargs])\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001152(start_new() is an obsolete synonym)\n\
1153\n\
Guido van Rossum3c288632001-10-16 21:13:49 +00001154Start a new thread and return its identifier. The thread will call the\n\
1155function with positional arguments from the tuple args and keyword arguments\n\
1156taken from the optional dictionary kwargs. The thread exits when the\n\
1157function returns; the return value is ignored. The thread will also exit\n\
1158when the function raises an unhandled exception; a stack trace will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001159printed unless the exception is SystemExit.\n");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001160
Barry Warsawd0c10421996-12-17 00:05:22 +00001161static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301162thread_PyThread_exit_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001163{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001164 PyErr_SetNone(PyExc_SystemExit);
1165 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001166}
1167
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001168PyDoc_STRVAR(exit_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001169"exit()\n\
Éric Araujo9bcf8bf2011-05-31 14:08:26 +02001170(exit_thread() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001171\n\
1172This is synonymous to ``raise SystemExit''. It will cause the current\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001173thread to exit silently unless the exception is caught.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001174
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001175static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301176thread_PyThread_interrupt_main(PyObject * self, PyObject *Py_UNUSED(ignored))
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001177{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001178 PyErr_SetInterrupt();
Serhiy Storchaka228b12e2017-01-23 09:47:21 +02001179 Py_RETURN_NONE;
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001180}
1181
1182PyDoc_STRVAR(interrupt_doc,
1183"interrupt_main()\n\
1184\n\
1185Raise a KeyboardInterrupt in the main thread.\n\
Kurt B. Kaisera1ad5f62003-06-16 18:51:28 +00001186A subthread can use this function to interrupt the main thread."
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001187);
1188
Victor Stinner61040132020-12-18 01:39:00 +01001189static lockobject *newlockobject(PyObject *module);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001190
Barry Warsawd0c10421996-12-17 00:05:22 +00001191static PyObject *
Victor Stinner8203c732020-12-16 12:20:33 +01001192thread_PyThread_allocate_lock(PyObject *module, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001193{
Victor Stinner61040132020-12-18 01:39:00 +01001194 return (PyObject *) newlockobject(module);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001195}
1196
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001197PyDoc_STRVAR(allocate_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001198"allocate_lock() -> lock object\n\
1199(allocate() is an obsolete synonym)\n\
1200\n\
Berker Peksag720e6552016-05-02 12:25:35 +03001201Create a new lock object. See help(type(threading.Lock())) for\n\
1202information about locks.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001203
Barry Warsawd0c10421996-12-17 00:05:22 +00001204static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301205thread_get_ident(PyObject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossumb6775db1994-08-01 11:34:53 +00001206{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001207 unsigned long ident = PyThread_get_thread_ident();
1208 if (ident == PYTHREAD_INVALID_THREAD_ID) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001209 PyErr_SetString(ThreadError, "no current thread ident");
1210 return NULL;
1211 }
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001212 return PyLong_FromUnsignedLong(ident);
Guido van Rossumb6775db1994-08-01 11:34:53 +00001213}
1214
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001215PyDoc_STRVAR(get_ident_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001216"get_ident() -> integer\n\
1217\n\
1218Return a non-zero integer that uniquely identifies the current thread\n\
1219amongst other threads that exist simultaneously.\n\
1220This may be used to identify per-thread resources.\n\
1221Even though on some platforms threads identities may appear to be\n\
1222allocated consecutive numbers starting at 1, this behavior should not\n\
1223be relied upon, and the number should be seen purely as a magic cookie.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001224A thread's identity may be reused for another thread after it exits.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001225
Jake Teslerb121f632019-05-22 08:43:17 -07001226#ifdef PY_HAVE_THREAD_NATIVE_ID
1227static PyObject *
1228thread_get_native_id(PyObject *self, PyObject *Py_UNUSED(ignored))
1229{
1230 unsigned long native_id = PyThread_get_thread_native_id();
1231 return PyLong_FromUnsignedLong(native_id);
1232}
1233
1234PyDoc_STRVAR(get_native_id_doc,
1235"get_native_id() -> integer\n\
1236\n\
1237Return a non-negative integer identifying the thread as reported\n\
1238by the OS (kernel). This may be used to uniquely identify a\n\
1239particular thread within a system.");
1240#endif
1241
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001242static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301243thread__count(PyObject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001244{
Victor Stinner81a7be32020-04-14 15:14:01 +02001245 PyInterpreterState *interp = _PyInterpreterState_GET();
Victor Stinnercaba55b2018-08-03 15:33:52 +02001246 return PyLong_FromLong(interp->num_threads);
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001247}
1248
1249PyDoc_STRVAR(_count_doc,
1250"_count() -> integer\n\
1251\n\
Antoine Pitrou9257f5e2009-10-30 22:23:02 +00001252\
oldkaa0735f2018-02-02 16:52:55 +08001253Return the number of currently running Python threads, excluding\n\
Antoine Pitrou9257f5e2009-10-30 22:23:02 +00001254the main thread. The returned number comprises all threads created\n\
1255through `start_new_thread()` as well as `threading.Thread`, and not\n\
1256yet finished.\n\
1257\n\
1258This function is meant for internal and specialized purposes only.\n\
1259In most applications `threading.enumerate()` should be used instead.");
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001260
Antoine Pitrou7b476992013-09-07 23:38:37 +02001261static void
Victor Stinnera42de742018-11-22 10:25:22 +01001262release_sentinel(void *wr_raw)
Antoine Pitrou7b476992013-09-07 23:38:37 +02001263{
Victor Stinnera42de742018-11-22 10:25:22 +01001264 PyObject *wr = _PyObject_CAST(wr_raw);
Antoine Pitrou7b476992013-09-07 23:38:37 +02001265 /* Tricky: this function is called when the current thread state
1266 is being deleted. Therefore, only simple C code can safely
1267 execute here. */
1268 PyObject *obj = PyWeakref_GET_OBJECT(wr);
1269 lockobject *lock;
1270 if (obj != Py_None) {
Antoine Pitrou7b476992013-09-07 23:38:37 +02001271 lock = (lockobject *) obj;
1272 if (lock->locked) {
1273 PyThread_release_lock(lock->lock_lock);
1274 lock->locked = 0;
1275 }
1276 }
1277 /* Deallocating a weakref with a NULL callback only calls
1278 PyObject_GC_Del(), which can't call any Python code. */
1279 Py_DECREF(wr);
1280}
1281
1282static PyObject *
Victor Stinner8203c732020-12-16 12:20:33 +01001283thread__set_sentinel(PyObject *module, PyObject *Py_UNUSED(ignored))
Antoine Pitrou7b476992013-09-07 23:38:37 +02001284{
1285 PyObject *wr;
1286 PyThreadState *tstate = PyThreadState_Get();
1287 lockobject *lock;
1288
1289 if (tstate->on_delete_data != NULL) {
1290 /* We must support the re-creation of the lock from a
1291 fork()ed child. */
1292 assert(tstate->on_delete == &release_sentinel);
1293 wr = (PyObject *) tstate->on_delete_data;
1294 tstate->on_delete = NULL;
1295 tstate->on_delete_data = NULL;
1296 Py_DECREF(wr);
1297 }
Victor Stinner61040132020-12-18 01:39:00 +01001298 lock = newlockobject(module);
Antoine Pitrou7b476992013-09-07 23:38:37 +02001299 if (lock == NULL)
1300 return NULL;
1301 /* The lock is owned by whoever called _set_sentinel(), but the weakref
1302 hangs to the thread state. */
1303 wr = PyWeakref_NewRef((PyObject *) lock, NULL);
1304 if (wr == NULL) {
1305 Py_DECREF(lock);
1306 return NULL;
1307 }
1308 tstate->on_delete_data = (void *) wr;
1309 tstate->on_delete = &release_sentinel;
1310 return (PyObject *) lock;
1311}
1312
1313PyDoc_STRVAR(_set_sentinel_doc,
1314"_set_sentinel() -> lock\n\
1315\n\
1316Set a sentinel lock that will be released when the current thread\n\
1317state is finalized (after it is untied from the interpreter).\n\
1318\n\
1319This is a private API for the threading module.");
1320
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001321static PyObject *
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001322thread_stack_size(PyObject *self, PyObject *args)
1323{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001324 size_t old_size;
1325 Py_ssize_t new_size = 0;
1326 int rc;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001327
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001328 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
1329 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001330
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001331 if (new_size < 0) {
1332 PyErr_SetString(PyExc_ValueError,
1333 "size must be 0 or a positive value");
1334 return NULL;
1335 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001336
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001337 old_size = PyThread_get_stacksize();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001338
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001339 rc = PyThread_set_stacksize((size_t) new_size);
1340 if (rc == -1) {
1341 PyErr_Format(PyExc_ValueError,
1342 "size not valid: %zd bytes",
1343 new_size);
1344 return NULL;
1345 }
1346 if (rc == -2) {
1347 PyErr_SetString(ThreadError,
1348 "setting stack size not supported");
1349 return NULL;
1350 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001351
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 return PyLong_FromSsize_t((Py_ssize_t) old_size);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001353}
1354
1355PyDoc_STRVAR(stack_size_doc,
1356"stack_size([size]) -> size\n\
1357\n\
1358Return the thread stack size used when creating new threads. The\n\
1359optional size argument specifies the stack size (in bytes) to be used\n\
1360for subsequently created threads, and must be 0 (use platform or\n\
1361configured default) or a positive integer value of at least 32,768 (32k).\n\
1362If changing the thread stack size is unsupported, a ThreadError\n\
1363exception is raised. If the specified size is invalid, a ValueError\n\
1364exception is raised, and the stack size is unmodified. 32k bytes\n\
1365 currently the minimum supported stack size value to guarantee\n\
1366sufficient stack space for the interpreter itself.\n\
1367\n\
1368Note that some platforms may have particular restrictions on values for\n\
Victor Stinner8c663fd2017-11-08 14:44:44 -08001369the stack size, such as requiring a minimum stack size larger than 32 KiB or\n\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001370requiring allocation in multiples of the system memory page size\n\
1371- platform documentation should be referred to for more information\n\
Victor Stinner8c663fd2017-11-08 14:44:44 -08001372(4 KiB pages are common; using multiples of 4096 for the stack size is\n\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001373the suggested approach in the absence of more specific information).");
1374
Victor Stinnercd590a72019-05-28 00:39:52 +02001375static int
1376thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
1377 PyObject *exc_traceback, PyObject *thread)
1378{
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001379 _Py_IDENTIFIER(name);
Victor Stinnercd590a72019-05-28 00:39:52 +02001380 /* print(f"Exception in thread {thread.name}:", file=file) */
1381 if (PyFile_WriteString("Exception in thread ", file) < 0) {
1382 return -1;
1383 }
1384
1385 PyObject *name = NULL;
1386 if (thread != Py_None) {
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001387 if (_PyObject_LookupAttrId(thread, &PyId_name, &name) < 0) {
1388 return -1;
1389 }
Victor Stinnercd590a72019-05-28 00:39:52 +02001390 }
1391 if (name != NULL) {
1392 if (PyFile_WriteObject(name, file, Py_PRINT_RAW) < 0) {
1393 Py_DECREF(name);
1394 return -1;
1395 }
1396 Py_DECREF(name);
1397 }
1398 else {
Victor Stinnercd590a72019-05-28 00:39:52 +02001399 unsigned long ident = PyThread_get_thread_ident();
1400 PyObject *str = PyUnicode_FromFormat("%lu", ident);
1401 if (str != NULL) {
1402 if (PyFile_WriteObject(str, file, Py_PRINT_RAW) < 0) {
1403 Py_DECREF(str);
1404 return -1;
1405 }
1406 Py_DECREF(str);
1407 }
1408 else {
1409 PyErr_Clear();
1410
1411 if (PyFile_WriteString("<failed to get thread name>", file) < 0) {
1412 return -1;
1413 }
1414 }
1415 }
1416
1417 if (PyFile_WriteString(":\n", file) < 0) {
1418 return -1;
1419 }
1420
1421 /* Display the traceback */
1422 _PyErr_Display(file, exc_type, exc_value, exc_traceback);
1423
1424 /* Call file.flush() */
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001425 PyObject *res = _PyObject_CallMethodIdNoArgs(file, &PyId_flush);
Victor Stinnercd590a72019-05-28 00:39:52 +02001426 if (!res) {
1427 return -1;
1428 }
1429 Py_DECREF(res);
1430
1431 return 0;
1432}
1433
1434
1435PyDoc_STRVAR(ExceptHookArgs__doc__,
1436"ExceptHookArgs\n\
1437\n\
1438Type used to pass arguments to threading.excepthook.");
1439
1440static PyTypeObject ExceptHookArgsType;
1441
1442static PyStructSequence_Field ExceptHookArgs_fields[] = {
1443 {"exc_type", "Exception type"},
1444 {"exc_value", "Exception value"},
1445 {"exc_traceback", "Exception traceback"},
1446 {"thread", "Thread"},
1447 {0}
1448};
1449
1450static PyStructSequence_Desc ExceptHookArgs_desc = {
Victor Stinner8203c732020-12-16 12:20:33 +01001451 .name = "_thread._ExceptHookArgs",
Victor Stinnercd590a72019-05-28 00:39:52 +02001452 .doc = ExceptHookArgs__doc__,
1453 .fields = ExceptHookArgs_fields,
1454 .n_in_sequence = 4
1455};
1456
1457
1458static PyObject *
1459thread_excepthook(PyObject *self, PyObject *args)
1460{
Andy Lester55728702020-03-06 16:53:17 -06001461 if (!Py_IS_TYPE(args, &ExceptHookArgsType)) {
Victor Stinnercd590a72019-05-28 00:39:52 +02001462 PyErr_SetString(PyExc_TypeError,
1463 "_thread.excepthook argument type "
1464 "must be ExceptHookArgs");
1465 return NULL;
1466 }
1467
1468 /* Borrowed reference */
1469 PyObject *exc_type = PyStructSequence_GET_ITEM(args, 0);
1470 if (exc_type == PyExc_SystemExit) {
1471 /* silently ignore SystemExit */
1472 Py_RETURN_NONE;
1473 }
1474
1475 /* Borrowed references */
1476 PyObject *exc_value = PyStructSequence_GET_ITEM(args, 1);
1477 PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2);
1478 PyObject *thread = PyStructSequence_GET_ITEM(args, 3);
1479
1480 PyObject *file = _PySys_GetObjectId(&PyId_stderr);
1481 if (file == NULL || file == Py_None) {
1482 if (thread == Py_None) {
1483 /* do nothing if sys.stderr is None and thread is None */
1484 Py_RETURN_NONE;
1485 }
1486
1487 file = PyObject_GetAttrString(thread, "_stderr");
1488 if (file == NULL) {
1489 return NULL;
1490 }
1491 if (file == Py_None) {
1492 Py_DECREF(file);
1493 /* do nothing if sys.stderr is None and sys.stderr was None
1494 when the thread was created */
1495 Py_RETURN_NONE;
1496 }
1497 }
1498 else {
1499 Py_INCREF(file);
1500 }
1501
1502 int res = thread_excepthook_file(file, exc_type, exc_value, exc_tb,
1503 thread);
1504 Py_DECREF(file);
1505 if (res < 0) {
1506 return NULL;
1507 }
1508
1509 Py_RETURN_NONE;
1510}
1511
1512PyDoc_STRVAR(excepthook_doc,
1513"excepthook(exc_type, exc_value, exc_traceback, thread)\n\
1514\n\
1515Handle uncaught Thread.run() exception.");
1516
Barry Warsawd0c10421996-12-17 00:05:22 +00001517static PyMethodDef thread_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001518 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
Victor Stinner754851f2011-04-19 23:58:51 +02001519 METH_VARARGS, start_new_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001520 {"start_new", (PyCFunction)thread_PyThread_start_new_thread,
Victor Stinner754851f2011-04-19 23:58:51 +02001521 METH_VARARGS, start_new_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301522 {"allocate_lock", thread_PyThread_allocate_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001523 METH_NOARGS, allocate_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301524 {"allocate", thread_PyThread_allocate_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001525 METH_NOARGS, allocate_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301526 {"exit_thread", thread_PyThread_exit_thread,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001527 METH_NOARGS, exit_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301528 {"exit", thread_PyThread_exit_thread,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001529 METH_NOARGS, exit_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301530 {"interrupt_main", thread_PyThread_interrupt_main,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001531 METH_NOARGS, interrupt_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301532 {"get_ident", thread_get_ident,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001533 METH_NOARGS, get_ident_doc},
Jake Teslerb121f632019-05-22 08:43:17 -07001534#ifdef PY_HAVE_THREAD_NATIVE_ID
1535 {"get_native_id", thread_get_native_id,
1536 METH_NOARGS, get_native_id_doc},
1537#endif
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301538 {"_count", thread__count,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001539 METH_NOARGS, _count_doc},
1540 {"stack_size", (PyCFunction)thread_stack_size,
Victor Stinner754851f2011-04-19 23:58:51 +02001541 METH_VARARGS, stack_size_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301542 {"_set_sentinel", thread__set_sentinel,
Antoine Pitrou7b476992013-09-07 23:38:37 +02001543 METH_NOARGS, _set_sentinel_doc},
Victor Stinnercd590a72019-05-28 00:39:52 +02001544 {"_excepthook", thread_excepthook,
1545 METH_O, excepthook_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001546 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001547};
1548
1549
1550/* Initialization function */
1551
Victor Stinner8203c732020-12-16 12:20:33 +01001552static int
Victor Stinner61040132020-12-18 01:39:00 +01001553thread_module_exec(PyObject *module)
Victor Stinner8203c732020-12-16 12:20:33 +01001554{
Victor Stinner61040132020-12-18 01:39:00 +01001555 thread_module_state *state = get_thread_state(module);
1556 PyObject *d = PyModule_GetDict(module);
1557
Victor Stinner8203c732020-12-16 12:20:33 +01001558 // Initialize the C thread library
1559 PyThread_init_thread();
1560
Victor Stinner61040132020-12-18 01:39:00 +01001561 // Lock
1562 state->lock_type = (PyTypeObject *)PyType_FromSpec(&lock_type_spec);
1563 if (state->lock_type == NULL) {
Victor Stinner8203c732020-12-16 12:20:33 +01001564 return -1;
1565 }
Victor Stinner61040132020-12-18 01:39:00 +01001566 if (PyDict_SetItemString(d, "LockType", (PyObject *)state->lock_type) < 0) {
Victor Stinner8203c732020-12-16 12:20:33 +01001567 return -1;
1568 }
Victor Stinner61040132020-12-18 01:39:00 +01001569
1570 // RLock
1571 PyTypeObject *rlock_type = (PyTypeObject *)PyType_FromSpec(&rlock_type_spec);
1572 if (rlock_type == NULL) {
Victor Stinner8203c732020-12-16 12:20:33 +01001573 return -1;
1574 }
Victor Stinner61040132020-12-18 01:39:00 +01001575 if (PyModule_AddType(module, rlock_type) < 0) {
1576 Py_DECREF(rlock_type);
1577 return -1;
1578 }
1579 Py_DECREF(rlock_type);
1580
1581 // Local dummy
1582 state->local_dummy_type = (PyTypeObject *)PyType_FromSpec(&local_dummy_type_spec);
1583 if (state->local_dummy_type == NULL) {
1584 return -1;
1585 }
1586
1587 // Local
1588 state->local_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &local_type_spec, NULL);
1589 if (state->local_type == NULL) {
1590 return -1;
1591 }
1592 if (PyModule_AddType(module, state->local_type) < 0) {
1593 return -1;
1594 }
1595
Victor Stinner8203c732020-12-16 12:20:33 +01001596 if (ExceptHookArgsType.tp_name == NULL) {
1597 if (PyStructSequence_InitType2(&ExceptHookArgsType,
1598 &ExceptHookArgs_desc) < 0) {
1599 return -1;
1600 }
1601 }
1602
1603 // Add module attributes
Victor Stinner8203c732020-12-16 12:20:33 +01001604 if (PyDict_SetItemString(d, "error", ThreadError) < 0) {
1605 return -1;
1606 }
Victor Stinner8203c732020-12-16 12:20:33 +01001607 if (PyModule_AddType(module, &ExceptHookArgsType) < 0) {
1608 return -1;
1609 }
1610
1611 // TIMEOUT_MAX
1612 double timeout_max = (_PyTime_t)PY_TIMEOUT_MAX * 1e-6;
1613 double time_max = _PyTime_AsSecondsDouble(_PyTime_MAX);
1614 timeout_max = Py_MIN(timeout_max, time_max);
1615 // Round towards minus infinity
1616 timeout_max = floor(timeout_max);
1617
1618 if (PyModule_AddObject(module, "TIMEOUT_MAX",
1619 PyFloat_FromDouble(timeout_max)) < 0) {
1620 return -1;
1621 }
1622
1623 return 0;
1624}
1625
1626
Victor Stinner61040132020-12-18 01:39:00 +01001627static int
1628thread_module_traverse(PyObject *module, visitproc visit, void *arg)
1629{
1630 thread_module_state *state = get_thread_state(module);
1631 Py_VISIT(state->lock_type);
1632 Py_VISIT(state->local_type);
1633 Py_VISIT(state->local_dummy_type);
1634 return 0;
1635}
1636
1637static int
1638thread_module_clear(PyObject *module)
1639{
1640 thread_module_state *state = get_thread_state(module);
1641 Py_CLEAR(state->lock_type);
1642 Py_CLEAR(state->local_type);
1643 Py_CLEAR(state->local_dummy_type);
1644 return 0;
1645}
1646
1647static void
1648thread_module_free(void *module)
1649{
1650 thread_module_clear((PyObject *)module);
1651}
1652
1653
1654
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001655PyDoc_STRVAR(thread_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001656"This module provides primitive operations to write multi-threaded programs.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001657The 'threading' module provides a more convenient interface.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001658
Victor Stinner61040132020-12-18 01:39:00 +01001659static PyModuleDef_Slot thread_module_slots[] = {
1660 {Py_mod_exec, thread_module_exec},
1661 {0, NULL}
1662};
1663
1664static struct PyModuleDef thread_module = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001665 PyModuleDef_HEAD_INIT,
Victor Stinner8203c732020-12-16 12:20:33 +01001666 .m_name = "_thread",
1667 .m_doc = thread_doc,
Victor Stinner61040132020-12-18 01:39:00 +01001668 .m_size = sizeof(thread_module_state),
Victor Stinner8203c732020-12-16 12:20:33 +01001669 .m_methods = thread_methods,
Victor Stinner61040132020-12-18 01:39:00 +01001670 .m_traverse = thread_module_traverse,
1671 .m_clear = thread_module_clear,
1672 .m_free = thread_module_free,
1673 .m_slots = thread_module_slots,
Martin v. Löwis1a214512008-06-11 05:26:20 +00001674};
1675
Mark Hammondfe51c6d2002-08-02 02:27:13 +00001676PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001677PyInit__thread(void)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001678{
Victor Stinner61040132020-12-18 01:39:00 +01001679 return PyModuleDef_Init(&thread_module);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001680}