• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* Thread module */
3 /* Interface to Sjoerd's portable C thread library */
4 
5 #include "Python.h"
6 #include "structmember.h" /* offsetof */
7 
8 #ifndef WITH_THREAD
9 #error "Error!  The rest of Python is not compiled with thread support."
10 #error "Rerun configure, adding a --with-threads option."
11 #error "Then run `make clean' followed by `make'."
12 #endif
13 
14 #include "pythread.h"
15 
16 static PyObject *ThreadError;
17 static long nb_threads = 0;
18 static PyObject *str_dict;
19 
20 _Py_IDENTIFIER(stderr);
21 
22 /* Lock objects */
23 
24 typedef struct {
25     PyObject_HEAD
26     PyThread_type_lock lock_lock;
27     PyObject *in_weakreflist;
28     char locked; /* for sanity checking */
29 } lockobject;
30 
31 static void
lock_dealloc(lockobject * self)32 lock_dealloc(lockobject *self)
33 {
34     if (self->in_weakreflist != NULL)
35         PyObject_ClearWeakRefs((PyObject *) self);
36     if (self->lock_lock != NULL) {
37         /* Unlock the lock so it's safe to free it */
38         if (self->locked)
39             PyThread_release_lock(self->lock_lock);
40         PyThread_free_lock(self->lock_lock);
41     }
42     PyObject_Del(self);
43 }
44 
45 /* Helper to acquire an interruptible lock with a timeout.  If the lock acquire
46  * is interrupted, signal handlers are run, and if they raise an exception,
47  * PY_LOCK_INTR is returned.  Otherwise, PY_LOCK_ACQUIRED or PY_LOCK_FAILURE
48  * are returned, depending on whether the lock can be acquired within the
49  * timeout.
50  */
51 static PyLockStatus
acquire_timed(PyThread_type_lock lock,_PyTime_t timeout)52 acquire_timed(PyThread_type_lock lock, _PyTime_t timeout)
53 {
54     PyLockStatus r;
55     _PyTime_t endtime = 0;
56     _PyTime_t microseconds;
57 
58     if (timeout > 0)
59         endtime = _PyTime_GetMonotonicClock() + timeout;
60 
61     do {
62         microseconds = _PyTime_AsMicroseconds(timeout, _PyTime_ROUND_CEILING);
63 
64         /* first a simple non-blocking try without releasing the GIL */
65         r = PyThread_acquire_lock_timed(lock, 0, 0);
66         if (r == PY_LOCK_FAILURE && microseconds != 0) {
67             Py_BEGIN_ALLOW_THREADS
68             r = PyThread_acquire_lock_timed(lock, microseconds, 1);
69             Py_END_ALLOW_THREADS
70         }
71 
72         if (r == PY_LOCK_INTR) {
73             /* Run signal handlers if we were interrupted.  Propagate
74              * exceptions from signal handlers, such as KeyboardInterrupt, by
75              * passing up PY_LOCK_INTR.  */
76             if (Py_MakePendingCalls() < 0) {
77                 return PY_LOCK_INTR;
78             }
79 
80             /* If we're using a timeout, recompute the timeout after processing
81              * signals, since those can take time.  */
82             if (timeout > 0) {
83                 timeout = endtime - _PyTime_GetMonotonicClock();
84 
85                 /* Check for negative values, since those mean block forever.
86                  */
87                 if (timeout < 0) {
88                     r = PY_LOCK_FAILURE;
89                 }
90             }
91         }
92     } while (r == PY_LOCK_INTR);  /* Retry if we were interrupted. */
93 
94     return r;
95 }
96 
97 static int
lock_acquire_parse_args(PyObject * args,PyObject * kwds,_PyTime_t * timeout)98 lock_acquire_parse_args(PyObject *args, PyObject *kwds,
99                         _PyTime_t *timeout)
100 {
101     char *kwlist[] = {"blocking", "timeout", NULL};
102     int blocking = 1;
103     PyObject *timeout_obj = NULL;
104     const _PyTime_t unset_timeout = _PyTime_FromSeconds(-1);
105 
106     *timeout = unset_timeout ;
107 
108     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO:acquire", kwlist,
109                                      &blocking, &timeout_obj))
110         return -1;
111 
112     if (timeout_obj
113         && _PyTime_FromSecondsObject(timeout,
114                                      timeout_obj, _PyTime_ROUND_CEILING) < 0)
115         return -1;
116 
117     if (!blocking && *timeout != unset_timeout ) {
118         PyErr_SetString(PyExc_ValueError,
119                         "can't specify a timeout for a non-blocking call");
120         return -1;
121     }
122     if (*timeout < 0 && *timeout != unset_timeout) {
123         PyErr_SetString(PyExc_ValueError,
124                         "timeout value must be positive");
125         return -1;
126     }
127     if (!blocking)
128         *timeout = 0;
129     else if (*timeout != unset_timeout) {
130         _PyTime_t microseconds;
131 
132         microseconds = _PyTime_AsMicroseconds(*timeout, _PyTime_ROUND_CEILING);
133         if (microseconds >= PY_TIMEOUT_MAX) {
134             PyErr_SetString(PyExc_OverflowError,
135                             "timeout value is too large");
136             return -1;
137         }
138     }
139     return 0;
140 }
141 
142 static PyObject *
lock_PyThread_acquire_lock(lockobject * self,PyObject * args,PyObject * kwds)143 lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds)
144 {
145     _PyTime_t timeout;
146     PyLockStatus r;
147 
148     if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
149         return NULL;
150 
151     r = acquire_timed(self->lock_lock, timeout);
152     if (r == PY_LOCK_INTR) {
153         return NULL;
154     }
155 
156     if (r == PY_LOCK_ACQUIRED)
157         self->locked = 1;
158     return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
159 }
160 
161 PyDoc_STRVAR(acquire_doc,
162 "acquire(blocking=True, timeout=-1) -> bool\n\
163 (acquire_lock() is an obsolete synonym)\n\
164 \n\
165 Lock the lock.  Without argument, this blocks if the lock is already\n\
166 locked (even by the same thread), waiting for another thread to release\n\
167 the lock, and return True once the lock is acquired.\n\
168 With an argument, this will only block if the argument is true,\n\
169 and the return value reflects whether the lock is acquired.\n\
170 The blocking operation is interruptible.");
171 
172 static PyObject *
lock_PyThread_release_lock(lockobject * self)173 lock_PyThread_release_lock(lockobject *self)
174 {
175     /* Sanity check: the lock must be locked */
176     if (!self->locked) {
177         PyErr_SetString(ThreadError, "release unlocked lock");
178         return NULL;
179     }
180 
181     PyThread_release_lock(self->lock_lock);
182     self->locked = 0;
183     Py_INCREF(Py_None);
184     return Py_None;
185 }
186 
187 PyDoc_STRVAR(release_doc,
188 "release()\n\
189 (release_lock() is an obsolete synonym)\n\
190 \n\
191 Release the lock, allowing another thread that is blocked waiting for\n\
192 the lock to acquire the lock.  The lock must be in the locked state,\n\
193 but it needn't be locked by the same thread that unlocks it.");
194 
195 static PyObject *
lock_locked_lock(lockobject * self)196 lock_locked_lock(lockobject *self)
197 {
198     return PyBool_FromLong((long)self->locked);
199 }
200 
201 PyDoc_STRVAR(locked_doc,
202 "locked() -> bool\n\
203 (locked_lock() is an obsolete synonym)\n\
204 \n\
205 Return whether the lock is in the locked state.");
206 
207 static PyObject *
lock_repr(lockobject * self)208 lock_repr(lockobject *self)
209 {
210     return PyUnicode_FromFormat("<%s %s object at %p>",
211         self->locked ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self);
212 }
213 
214 static PyMethodDef lock_methods[] = {
215     {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock,
216      METH_VARARGS | METH_KEYWORDS, acquire_doc},
217     {"acquire",      (PyCFunction)lock_PyThread_acquire_lock,
218      METH_VARARGS | METH_KEYWORDS, acquire_doc},
219     {"release_lock", (PyCFunction)lock_PyThread_release_lock,
220      METH_NOARGS, release_doc},
221     {"release",      (PyCFunction)lock_PyThread_release_lock,
222      METH_NOARGS, release_doc},
223     {"locked_lock",  (PyCFunction)lock_locked_lock,
224      METH_NOARGS, locked_doc},
225     {"locked",       (PyCFunction)lock_locked_lock,
226      METH_NOARGS, locked_doc},
227     {"__enter__",    (PyCFunction)lock_PyThread_acquire_lock,
228      METH_VARARGS | METH_KEYWORDS, acquire_doc},
229     {"__exit__",    (PyCFunction)lock_PyThread_release_lock,
230      METH_VARARGS, release_doc},
231     {NULL,           NULL}              /* sentinel */
232 };
233 
234 static PyTypeObject Locktype = {
235     PyVarObject_HEAD_INIT(&PyType_Type, 0)
236     "_thread.lock",                     /*tp_name*/
237     sizeof(lockobject),                 /*tp_size*/
238     0,                                  /*tp_itemsize*/
239     /* methods */
240     (destructor)lock_dealloc,           /*tp_dealloc*/
241     0,                                  /*tp_print*/
242     0,                                  /*tp_getattr*/
243     0,                                  /*tp_setattr*/
244     0,                                  /*tp_reserved*/
245     (reprfunc)lock_repr,                /*tp_repr*/
246     0,                                  /*tp_as_number*/
247     0,                                  /*tp_as_sequence*/
248     0,                                  /*tp_as_mapping*/
249     0,                                  /*tp_hash*/
250     0,                                  /*tp_call*/
251     0,                                  /*tp_str*/
252     0,                                  /*tp_getattro*/
253     0,                                  /*tp_setattro*/
254     0,                                  /*tp_as_buffer*/
255     Py_TPFLAGS_DEFAULT,                 /*tp_flags*/
256     0,                                  /*tp_doc*/
257     0,                                  /*tp_traverse*/
258     0,                                  /*tp_clear*/
259     0,                                  /*tp_richcompare*/
260     offsetof(lockobject, in_weakreflist), /*tp_weaklistoffset*/
261     0,                                  /*tp_iter*/
262     0,                                  /*tp_iternext*/
263     lock_methods,                       /*tp_methods*/
264 };
265 
266 /* Recursive lock objects */
267 
268 typedef struct {
269     PyObject_HEAD
270     PyThread_type_lock rlock_lock;
271     long rlock_owner;
272     unsigned long rlock_count;
273     PyObject *in_weakreflist;
274 } rlockobject;
275 
276 static void
rlock_dealloc(rlockobject * self)277 rlock_dealloc(rlockobject *self)
278 {
279     if (self->in_weakreflist != NULL)
280         PyObject_ClearWeakRefs((PyObject *) self);
281     /* self->rlock_lock can be NULL if PyThread_allocate_lock() failed
282        in rlock_new() */
283     if (self->rlock_lock != NULL) {
284         /* Unlock the lock so it's safe to free it */
285         if (self->rlock_count > 0)
286             PyThread_release_lock(self->rlock_lock);
287 
288         PyThread_free_lock(self->rlock_lock);
289     }
290     Py_TYPE(self)->tp_free(self);
291 }
292 
293 static PyObject *
rlock_acquire(rlockobject * self,PyObject * args,PyObject * kwds)294 rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
295 {
296     _PyTime_t timeout;
297     long tid;
298     PyLockStatus r = PY_LOCK_ACQUIRED;
299 
300     if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
301         return NULL;
302 
303     tid = PyThread_get_thread_ident();
304     if (self->rlock_count > 0 && tid == self->rlock_owner) {
305         unsigned long count = self->rlock_count + 1;
306         if (count <= self->rlock_count) {
307             PyErr_SetString(PyExc_OverflowError,
308                             "Internal lock count overflowed");
309             return NULL;
310         }
311         self->rlock_count = count;
312         Py_RETURN_TRUE;
313     }
314     r = acquire_timed(self->rlock_lock, timeout);
315     if (r == PY_LOCK_ACQUIRED) {
316         assert(self->rlock_count == 0);
317         self->rlock_owner = tid;
318         self->rlock_count = 1;
319     }
320     else if (r == PY_LOCK_INTR) {
321         return NULL;
322     }
323 
324     return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
325 }
326 
327 PyDoc_STRVAR(rlock_acquire_doc,
328 "acquire(blocking=True) -> bool\n\
329 \n\
330 Lock the lock.  `blocking` indicates whether we should wait\n\
331 for the lock to be available or not.  If `blocking` is False\n\
332 and another thread holds the lock, the method will return False\n\
333 immediately.  If `blocking` is True and another thread holds\n\
334 the lock, the method will wait for the lock to be released,\n\
335 take it and then return True.\n\
336 (note: the blocking operation is interruptible.)\n\
337 \n\
338 In all other cases, the method will return True immediately.\n\
339 Precisely, if the current thread already holds the lock, its\n\
340 internal counter is simply incremented. If nobody holds the lock,\n\
341 the lock is taken and its internal counter initialized to 1.");
342 
343 static PyObject *
rlock_release(rlockobject * self)344 rlock_release(rlockobject *self)
345 {
346     long tid = PyThread_get_thread_ident();
347 
348     if (self->rlock_count == 0 || self->rlock_owner != tid) {
349         PyErr_SetString(PyExc_RuntimeError,
350                         "cannot release un-acquired lock");
351         return NULL;
352     }
353     if (--self->rlock_count == 0) {
354         self->rlock_owner = 0;
355         PyThread_release_lock(self->rlock_lock);
356     }
357     Py_RETURN_NONE;
358 }
359 
360 PyDoc_STRVAR(rlock_release_doc,
361 "release()\n\
362 \n\
363 Release the lock, allowing another thread that is blocked waiting for\n\
364 the lock to acquire the lock.  The lock must be in the locked state,\n\
365 and must be locked by the same thread that unlocks it; otherwise a\n\
366 `RuntimeError` is raised.\n\
367 \n\
368 Do note that if the lock was acquire()d several times in a row by the\n\
369 current thread, release() needs to be called as many times for the lock\n\
370 to be available for other threads.");
371 
372 static PyObject *
rlock_acquire_restore(rlockobject * self,PyObject * args)373 rlock_acquire_restore(rlockobject *self, PyObject *args)
374 {
375     long owner;
376     unsigned long count;
377     int r = 1;
378 
379     if (!PyArg_ParseTuple(args, "(kl):_acquire_restore", &count, &owner))
380         return NULL;
381 
382     if (!PyThread_acquire_lock(self->rlock_lock, 0)) {
383         Py_BEGIN_ALLOW_THREADS
384         r = PyThread_acquire_lock(self->rlock_lock, 1);
385         Py_END_ALLOW_THREADS
386     }
387     if (!r) {
388         PyErr_SetString(ThreadError, "couldn't acquire lock");
389         return NULL;
390     }
391     assert(self->rlock_count == 0);
392     self->rlock_owner = owner;
393     self->rlock_count = count;
394     Py_RETURN_NONE;
395 }
396 
397 PyDoc_STRVAR(rlock_acquire_restore_doc,
398 "_acquire_restore(state) -> None\n\
399 \n\
400 For internal use by `threading.Condition`.");
401 
402 static PyObject *
rlock_release_save(rlockobject * self)403 rlock_release_save(rlockobject *self)
404 {
405     long owner;
406     unsigned long count;
407 
408     if (self->rlock_count == 0) {
409         PyErr_SetString(PyExc_RuntimeError,
410                         "cannot release un-acquired lock");
411         return NULL;
412     }
413 
414     owner = self->rlock_owner;
415     count = self->rlock_count;
416     self->rlock_count = 0;
417     self->rlock_owner = 0;
418     PyThread_release_lock(self->rlock_lock);
419     return Py_BuildValue("kl", count, owner);
420 }
421 
422 PyDoc_STRVAR(rlock_release_save_doc,
423 "_release_save() -> tuple\n\
424 \n\
425 For internal use by `threading.Condition`.");
426 
427 
428 static PyObject *
rlock_is_owned(rlockobject * self)429 rlock_is_owned(rlockobject *self)
430 {
431     long tid = PyThread_get_thread_ident();
432 
433     if (self->rlock_count > 0 && self->rlock_owner == tid) {
434         Py_RETURN_TRUE;
435     }
436     Py_RETURN_FALSE;
437 }
438 
439 PyDoc_STRVAR(rlock_is_owned_doc,
440 "_is_owned() -> bool\n\
441 \n\
442 For internal use by `threading.Condition`.");
443 
444 static PyObject *
rlock_new(PyTypeObject * type,PyObject * args,PyObject * kwds)445 rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
446 {
447     rlockobject *self;
448 
449     self = (rlockobject *) type->tp_alloc(type, 0);
450     if (self != NULL) {
451         self->in_weakreflist = NULL;
452         self->rlock_owner = 0;
453         self->rlock_count = 0;
454 
455         self->rlock_lock = PyThread_allocate_lock();
456         if (self->rlock_lock == NULL) {
457             Py_DECREF(self);
458             PyErr_SetString(ThreadError, "can't allocate lock");
459             return NULL;
460         }
461     }
462 
463     return (PyObject *) self;
464 }
465 
466 static PyObject *
rlock_repr(rlockobject * self)467 rlock_repr(rlockobject *self)
468 {
469     return PyUnicode_FromFormat("<%s %s object owner=%ld count=%lu at %p>",
470         self->rlock_count ? "locked" : "unlocked",
471         Py_TYPE(self)->tp_name, self->rlock_owner,
472         self->rlock_count, self);
473 }
474 
475 
476 static PyMethodDef rlock_methods[] = {
477     {"acquire",      (PyCFunction)rlock_acquire,
478      METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
479     {"release",      (PyCFunction)rlock_release,
480      METH_NOARGS, rlock_release_doc},
481     {"_is_owned",     (PyCFunction)rlock_is_owned,
482      METH_NOARGS, rlock_is_owned_doc},
483     {"_acquire_restore", (PyCFunction)rlock_acquire_restore,
484      METH_VARARGS, rlock_acquire_restore_doc},
485     {"_release_save", (PyCFunction)rlock_release_save,
486      METH_NOARGS, rlock_release_save_doc},
487     {"__enter__",    (PyCFunction)rlock_acquire,
488      METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
489     {"__exit__",    (PyCFunction)rlock_release,
490      METH_VARARGS, rlock_release_doc},
491     {NULL,           NULL}              /* sentinel */
492 };
493 
494 
495 static PyTypeObject RLocktype = {
496     PyVarObject_HEAD_INIT(&PyType_Type, 0)
497     "_thread.RLock",                    /*tp_name*/
498     sizeof(rlockobject),                /*tp_size*/
499     0,                                  /*tp_itemsize*/
500     /* methods */
501     (destructor)rlock_dealloc,          /*tp_dealloc*/
502     0,                                  /*tp_print*/
503     0,                                  /*tp_getattr*/
504     0,                                  /*tp_setattr*/
505     0,                                  /*tp_reserved*/
506     (reprfunc)rlock_repr,               /*tp_repr*/
507     0,                                  /*tp_as_number*/
508     0,                                  /*tp_as_sequence*/
509     0,                                  /*tp_as_mapping*/
510     0,                                  /*tp_hash*/
511     0,                                  /*tp_call*/
512     0,                                  /*tp_str*/
513     0,                                  /*tp_getattro*/
514     0,                                  /*tp_setattro*/
515     0,                                  /*tp_as_buffer*/
516     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
517     0,                                  /*tp_doc*/
518     0,                                  /*tp_traverse*/
519     0,                                  /*tp_clear*/
520     0,                                  /*tp_richcompare*/
521     offsetof(rlockobject, in_weakreflist), /*tp_weaklistoffset*/
522     0,                                  /*tp_iter*/
523     0,                                  /*tp_iternext*/
524     rlock_methods,                      /*tp_methods*/
525     0,                                  /* tp_members */
526     0,                                  /* tp_getset */
527     0,                                  /* tp_base */
528     0,                                  /* tp_dict */
529     0,                                  /* tp_descr_get */
530     0,                                  /* tp_descr_set */
531     0,                                  /* tp_dictoffset */
532     0,                                  /* tp_init */
533     PyType_GenericAlloc,                /* tp_alloc */
534     rlock_new                           /* tp_new */
535 };
536 
537 static lockobject *
newlockobject(void)538 newlockobject(void)
539 {
540     lockobject *self;
541     self = PyObject_New(lockobject, &Locktype);
542     if (self == NULL)
543         return NULL;
544     self->lock_lock = PyThread_allocate_lock();
545     self->locked = 0;
546     self->in_weakreflist = NULL;
547     if (self->lock_lock == NULL) {
548         Py_DECREF(self);
549         PyErr_SetString(ThreadError, "can't allocate lock");
550         return NULL;
551     }
552     return self;
553 }
554 
555 /* Thread-local objects */
556 
557 #include "structmember.h"
558 
559 /* Quick overview:
560 
561    We need to be able to reclaim reference cycles as soon as possible
562    (both when a thread is being terminated, or a thread-local object
563     becomes unreachable from user data).  Constraints:
564    - it must not be possible for thread-state dicts to be involved in
565      reference cycles (otherwise the cyclic GC will refuse to consider
566      objects referenced from a reachable thread-state dict, even though
567      local_dealloc would clear them)
568    - the death of a thread-state dict must still imply destruction of the
569      corresponding local dicts in all thread-local objects.
570 
571    Our implementation uses small "localdummy" objects in order to break
572    the reference chain. These trivial objects are hashable (using the
573    default scheme of identity hashing) and weakrefable.
574    Each thread-state holds a separate localdummy for each local object
575    (as a /strong reference/),
576    and each thread-local object holds a dict mapping /weak references/
577    of localdummies to local dicts.
578 
579    Therefore:
580    - only the thread-state dict holds a strong reference to the dummies
581    - only the thread-local object holds a strong reference to the local dicts
582    - only outside objects (application- or library-level) hold strong
583      references to the thread-local objects
584    - as soon as a thread-state dict is destroyed, the weakref callbacks of all
585      dummies attached to that thread are called, and destroy the corresponding
586      local dicts from thread-local objects
587    - as soon as a thread-local object is destroyed, its local dicts are
588      destroyed and its dummies are manually removed from all thread states
589    - the GC can do its work correctly when a thread-local object is dangling,
590      without any interference from the thread-state dicts
591 
592    As an additional optimization, each localdummy holds a borrowed reference
593    to the corresponding localdict.  This borrowed reference is only used
594    by the thread-local object which has created the localdummy, which should
595    guarantee that the localdict still exists when accessed.
596 */
597 
598 typedef struct {
599     PyObject_HEAD
600     PyObject *localdict;        /* Borrowed reference! */
601     PyObject *weakreflist;      /* List of weak references to self */
602 } localdummyobject;
603 
604 static void
localdummy_dealloc(localdummyobject * self)605 localdummy_dealloc(localdummyobject *self)
606 {
607     if (self->weakreflist != NULL)
608         PyObject_ClearWeakRefs((PyObject *) self);
609     Py_TYPE(self)->tp_free((PyObject*)self);
610 }
611 
612 static PyTypeObject localdummytype = {
613     PyVarObject_HEAD_INIT(NULL, 0)
614     /* tp_name           */ "_thread._localdummy",
615     /* tp_basicsize      */ sizeof(localdummyobject),
616     /* tp_itemsize       */ 0,
617     /* tp_dealloc        */ (destructor)localdummy_dealloc,
618     /* tp_print          */ 0,
619     /* tp_getattr        */ 0,
620     /* tp_setattr        */ 0,
621     /* tp_reserved       */ 0,
622     /* tp_repr           */ 0,
623     /* tp_as_number      */ 0,
624     /* tp_as_sequence    */ 0,
625     /* tp_as_mapping     */ 0,
626     /* tp_hash           */ 0,
627     /* tp_call           */ 0,
628     /* tp_str            */ 0,
629     /* tp_getattro       */ 0,
630     /* tp_setattro       */ 0,
631     /* tp_as_buffer      */ 0,
632     /* tp_flags          */ Py_TPFLAGS_DEFAULT,
633     /* tp_doc            */ "Thread-local dummy",
634     /* tp_traverse       */ 0,
635     /* tp_clear          */ 0,
636     /* tp_richcompare    */ 0,
637     /* tp_weaklistoffset */ offsetof(localdummyobject, weakreflist)
638 };
639 
640 
641 typedef struct {
642     PyObject_HEAD
643     PyObject *key;
644     PyObject *args;
645     PyObject *kw;
646     PyObject *weakreflist;      /* List of weak references to self */
647     /* A {localdummy weakref -> localdict} dict */
648     PyObject *dummies;
649     /* The callback for weakrefs to localdummies */
650     PyObject *wr_callback;
651 } localobject;
652 
653 /* Forward declaration */
654 static PyObject *_ldict(localobject *self);
655 static PyObject *_localdummy_destroyed(PyObject *meth_self, PyObject *dummyweakref);
656 
657 /* Create and register the dummy for the current thread.
658    Returns a borrowed reference of the corresponding local dict */
659 static PyObject *
_local_create_dummy(localobject * self)660 _local_create_dummy(localobject *self)
661 {
662     PyObject *tdict, *ldict = NULL, *wr = NULL;
663     localdummyobject *dummy = NULL;
664     int r;
665 
666     tdict = PyThreadState_GetDict();
667     if (tdict == NULL) {
668         PyErr_SetString(PyExc_SystemError,
669                         "Couldn't get thread-state dictionary");
670         goto err;
671     }
672 
673     ldict = PyDict_New();
674     if (ldict == NULL)
675         goto err;
676     dummy = (localdummyobject *) localdummytype.tp_alloc(&localdummytype, 0);
677     if (dummy == NULL)
678         goto err;
679     dummy->localdict = ldict;
680     wr = PyWeakref_NewRef((PyObject *) dummy, self->wr_callback);
681     if (wr == NULL)
682         goto err;
683 
684     /* As a side-effect, this will cache the weakref's hash before the
685        dummy gets deleted */
686     r = PyDict_SetItem(self->dummies, wr, ldict);
687     if (r < 0)
688         goto err;
689     Py_CLEAR(wr);
690     r = PyDict_SetItem(tdict, self->key, (PyObject *) dummy);
691     if (r < 0)
692         goto err;
693     Py_CLEAR(dummy);
694 
695     Py_DECREF(ldict);
696     return ldict;
697 
698 err:
699     Py_XDECREF(ldict);
700     Py_XDECREF(wr);
701     Py_XDECREF(dummy);
702     return NULL;
703 }
704 
705 static PyObject *
local_new(PyTypeObject * type,PyObject * args,PyObject * kw)706 local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
707 {
708     localobject *self;
709     PyObject *wr;
710     static PyMethodDef wr_callback_def = {
711         "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O
712     };
713 
714     if (type->tp_init == PyBaseObject_Type.tp_init) {
715         int rc = 0;
716         if (args != NULL)
717             rc = PyObject_IsTrue(args);
718         if (rc == 0 && kw != NULL)
719             rc = PyObject_IsTrue(kw);
720         if (rc != 0) {
721             if (rc > 0)
722                 PyErr_SetString(PyExc_TypeError,
723                           "Initialization arguments are not supported");
724             return NULL;
725         }
726     }
727 
728     self = (localobject *)type->tp_alloc(type, 0);
729     if (self == NULL)
730         return NULL;
731 
732     Py_XINCREF(args);
733     self->args = args;
734     Py_XINCREF(kw);
735     self->kw = kw;
736     self->key = PyUnicode_FromFormat("thread.local.%p", self);
737     if (self->key == NULL)
738         goto err;
739 
740     self->dummies = PyDict_New();
741     if (self->dummies == NULL)
742         goto err;
743 
744     /* We use a weak reference to self in the callback closure
745        in order to avoid spurious reference cycles */
746     wr = PyWeakref_NewRef((PyObject *) self, NULL);
747     if (wr == NULL)
748         goto err;
749     self->wr_callback = PyCFunction_NewEx(&wr_callback_def, wr, NULL);
750     Py_DECREF(wr);
751     if (self->wr_callback == NULL)
752         goto err;
753 
754     if (_local_create_dummy(self) == NULL)
755         goto err;
756 
757     return (PyObject *)self;
758 
759   err:
760     Py_DECREF(self);
761     return NULL;
762 }
763 
764 static int
local_traverse(localobject * self,visitproc visit,void * arg)765 local_traverse(localobject *self, visitproc visit, void *arg)
766 {
767     Py_VISIT(self->args);
768     Py_VISIT(self->kw);
769     Py_VISIT(self->dummies);
770     return 0;
771 }
772 
773 static int
local_clear(localobject * self)774 local_clear(localobject *self)
775 {
776     PyThreadState *tstate;
777     Py_CLEAR(self->args);
778     Py_CLEAR(self->kw);
779     Py_CLEAR(self->dummies);
780     Py_CLEAR(self->wr_callback);
781     /* Remove all strong references to dummies from the thread states */
782     if (self->key
783         && (tstate = PyThreadState_Get())
784         && tstate->interp) {
785         for(tstate = PyInterpreterState_ThreadHead(tstate->interp);
786             tstate;
787             tstate = PyThreadState_Next(tstate))
788             if (tstate->dict &&
789                 PyDict_GetItem(tstate->dict, self->key))
790                 PyDict_DelItem(tstate->dict, self->key);
791     }
792     return 0;
793 }
794 
795 static void
local_dealloc(localobject * self)796 local_dealloc(localobject *self)
797 {
798     /* Weakrefs must be invalidated right now, otherwise they can be used
799        from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
800     if (self->weakreflist != NULL)
801         PyObject_ClearWeakRefs((PyObject *) self);
802 
803     PyObject_GC_UnTrack(self);
804 
805     local_clear(self);
806     Py_XDECREF(self->key);
807     Py_TYPE(self)->tp_free((PyObject*)self);
808 }
809 
810 /* Returns a borrowed reference to the local dict, creating it if necessary */
811 static PyObject *
_ldict(localobject * self)812 _ldict(localobject *self)
813 {
814     PyObject *tdict, *ldict, *dummy;
815 
816     tdict = PyThreadState_GetDict();
817     if (tdict == NULL) {
818         PyErr_SetString(PyExc_SystemError,
819                         "Couldn't get thread-state dictionary");
820         return NULL;
821     }
822 
823     dummy = PyDict_GetItem(tdict, self->key);
824     if (dummy == NULL) {
825         ldict = _local_create_dummy(self);
826         if (ldict == NULL)
827             return NULL;
828 
829         if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
830             Py_TYPE(self)->tp_init((PyObject*)self,
831                                    self->args, self->kw) < 0) {
832             /* we need to get rid of ldict from thread so
833                we create a new one the next time we do an attr
834                access */
835             PyDict_DelItem(tdict, self->key);
836             return NULL;
837         }
838     }
839     else {
840         assert(Py_TYPE(dummy) == &localdummytype);
841         ldict = ((localdummyobject *) dummy)->localdict;
842     }
843 
844     return ldict;
845 }
846 
847 static int
local_setattro(localobject * self,PyObject * name,PyObject * v)848 local_setattro(localobject *self, PyObject *name, PyObject *v)
849 {
850     PyObject *ldict;
851     int r;
852 
853     ldict = _ldict(self);
854     if (ldict == NULL)
855         return -1;
856 
857     r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
858     if (r == 1) {
859         PyErr_Format(PyExc_AttributeError,
860                      "'%.50s' object attribute '%U' is read-only",
861                      Py_TYPE(self)->tp_name, name);
862         return -1;
863     }
864     if (r == -1)
865         return -1;
866 
867     return _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict);
868 }
869 
870 static PyObject *local_getattro(localobject *, PyObject *);
871 
872 static PyTypeObject localtype = {
873     PyVarObject_HEAD_INIT(NULL, 0)
874     /* tp_name           */ "_thread._local",
875     /* tp_basicsize      */ sizeof(localobject),
876     /* tp_itemsize       */ 0,
877     /* tp_dealloc        */ (destructor)local_dealloc,
878     /* tp_print          */ 0,
879     /* tp_getattr        */ 0,
880     /* tp_setattr        */ 0,
881     /* tp_reserved       */ 0,
882     /* tp_repr           */ 0,
883     /* tp_as_number      */ 0,
884     /* tp_as_sequence    */ 0,
885     /* tp_as_mapping     */ 0,
886     /* tp_hash           */ 0,
887     /* tp_call           */ 0,
888     /* tp_str            */ 0,
889     /* tp_getattro       */ (getattrofunc)local_getattro,
890     /* tp_setattro       */ (setattrofunc)local_setattro,
891     /* tp_as_buffer      */ 0,
892     /* tp_flags          */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
893                                                | Py_TPFLAGS_HAVE_GC,
894     /* tp_doc            */ "Thread-local data",
895     /* tp_traverse       */ (traverseproc)local_traverse,
896     /* tp_clear          */ (inquiry)local_clear,
897     /* tp_richcompare    */ 0,
898     /* tp_weaklistoffset */ offsetof(localobject, weakreflist),
899     /* tp_iter           */ 0,
900     /* tp_iternext       */ 0,
901     /* tp_methods        */ 0,
902     /* tp_members        */ 0,
903     /* tp_getset         */ 0,
904     /* tp_base           */ 0,
905     /* tp_dict           */ 0, /* internal use */
906     /* tp_descr_get      */ 0,
907     /* tp_descr_set      */ 0,
908     /* tp_dictoffset     */ 0,
909     /* tp_init           */ 0,
910     /* tp_alloc          */ 0,
911     /* tp_new            */ local_new,
912     /* tp_free           */ 0, /* Low-level free-mem routine */
913     /* tp_is_gc          */ 0, /* For PyObject_IS_GC */
914 };
915 
916 static PyObject *
local_getattro(localobject * self,PyObject * name)917 local_getattro(localobject *self, PyObject *name)
918 {
919     PyObject *ldict, *value;
920     int r;
921 
922     ldict = _ldict(self);
923     if (ldict == NULL)
924         return NULL;
925 
926     r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
927     if (r == 1) {
928         Py_INCREF(ldict);
929         return ldict;
930     }
931     if (r == -1)
932         return NULL;
933 
934     if (Py_TYPE(self) != &localtype)
935         /* use generic lookup for subtypes */
936         return _PyObject_GenericGetAttrWithDict((PyObject *)self, name, ldict);
937 
938     /* Optimization: just look in dict ourselves */
939     value = PyDict_GetItem(ldict, name);
940     if (value == NULL)
941         /* Fall back on generic to get __class__ and __dict__ */
942         return _PyObject_GenericGetAttrWithDict((PyObject *)self, name, ldict);
943 
944     Py_INCREF(value);
945     return value;
946 }
947 
948 /* Called when a dummy is destroyed. */
949 static PyObject *
_localdummy_destroyed(PyObject * localweakref,PyObject * dummyweakref)950 _localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
951 {
952     PyObject *obj;
953     localobject *self;
954     assert(PyWeakref_CheckRef(localweakref));
955     obj = PyWeakref_GET_OBJECT(localweakref);
956     if (obj == Py_None)
957         Py_RETURN_NONE;
958     Py_INCREF(obj);
959     assert(PyObject_TypeCheck(obj, &localtype));
960     /* If the thread-local object is still alive and not being cleared,
961        remove the corresponding local dict */
962     self = (localobject *) obj;
963     if (self->dummies != NULL) {
964         PyObject *ldict;
965         ldict = PyDict_GetItem(self->dummies, dummyweakref);
966         if (ldict != NULL) {
967             PyDict_DelItem(self->dummies, dummyweakref);
968         }
969         if (PyErr_Occurred())
970             PyErr_WriteUnraisable(obj);
971     }
972     Py_DECREF(obj);
973     Py_RETURN_NONE;
974 }
975 
976 /* Module functions */
977 
978 struct bootstate {
979     PyInterpreterState *interp;
980     PyObject *func;
981     PyObject *args;
982     PyObject *keyw;
983     PyThreadState *tstate;
984 };
985 
986 static void
t_bootstrap(void * boot_raw)987 t_bootstrap(void *boot_raw)
988 {
989     struct bootstate *boot = (struct bootstate *) boot_raw;
990     PyThreadState *tstate;
991     PyObject *res;
992 
993     tstate = boot->tstate;
994     tstate->thread_id = PyThread_get_thread_ident();
995     _PyThreadState_Init(tstate);
996     PyEval_AcquireThread(tstate);
997     nb_threads++;
998     res = PyEval_CallObjectWithKeywords(
999         boot->func, boot->args, boot->keyw);
1000     if (res == NULL) {
1001         if (PyErr_ExceptionMatches(PyExc_SystemExit))
1002             PyErr_Clear();
1003         else {
1004             PyObject *file;
1005             PyObject *exc, *value, *tb;
1006             PySys_WriteStderr(
1007                 "Unhandled exception in thread started by ");
1008             PyErr_Fetch(&exc, &value, &tb);
1009             file = _PySys_GetObjectId(&PyId_stderr);
1010             if (file != NULL && file != Py_None)
1011                 PyFile_WriteObject(boot->func, file, 0);
1012             else
1013                 PyObject_Print(boot->func, stderr, 0);
1014             PySys_WriteStderr("\n");
1015             PyErr_Restore(exc, value, tb);
1016             PyErr_PrintEx(0);
1017         }
1018     }
1019     else
1020         Py_DECREF(res);
1021     Py_DECREF(boot->func);
1022     Py_DECREF(boot->args);
1023     Py_XDECREF(boot->keyw);
1024     PyMem_DEL(boot_raw);
1025     nb_threads--;
1026     PyThreadState_Clear(tstate);
1027     PyThreadState_DeleteCurrent();
1028     PyThread_exit_thread();
1029 }
1030 
1031 static PyObject *
thread_PyThread_start_new_thread(PyObject * self,PyObject * fargs)1032 thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
1033 {
1034     PyObject *func, *args, *keyw = NULL;
1035     struct bootstate *boot;
1036     long ident;
1037 
1038     if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
1039                            &func, &args, &keyw))
1040         return NULL;
1041     if (!PyCallable_Check(func)) {
1042         PyErr_SetString(PyExc_TypeError,
1043                         "first arg must be callable");
1044         return NULL;
1045     }
1046     if (!PyTuple_Check(args)) {
1047         PyErr_SetString(PyExc_TypeError,
1048                         "2nd arg must be a tuple");
1049         return NULL;
1050     }
1051     if (keyw != NULL && !PyDict_Check(keyw)) {
1052         PyErr_SetString(PyExc_TypeError,
1053                         "optional 3rd arg must be a dictionary");
1054         return NULL;
1055     }
1056     boot = PyMem_NEW(struct bootstate, 1);
1057     if (boot == NULL)
1058         return PyErr_NoMemory();
1059     boot->interp = PyThreadState_GET()->interp;
1060     boot->func = func;
1061     boot->args = args;
1062     boot->keyw = keyw;
1063     boot->tstate = _PyThreadState_Prealloc(boot->interp);
1064     if (boot->tstate == NULL) {
1065         PyMem_DEL(boot);
1066         return PyErr_NoMemory();
1067     }
1068     Py_INCREF(func);
1069     Py_INCREF(args);
1070     Py_XINCREF(keyw);
1071     PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
1072     ident = PyThread_start_new_thread(t_bootstrap, (void*) boot);
1073     if (ident == -1) {
1074         PyErr_SetString(ThreadError, "can't start new thread");
1075         Py_DECREF(func);
1076         Py_DECREF(args);
1077         Py_XDECREF(keyw);
1078         PyThreadState_Clear(boot->tstate);
1079         PyMem_DEL(boot);
1080         return NULL;
1081     }
1082     return PyLong_FromLong(ident);
1083 }
1084 
1085 PyDoc_STRVAR(start_new_doc,
1086 "start_new_thread(function, args[, kwargs])\n\
1087 (start_new() is an obsolete synonym)\n\
1088 \n\
1089 Start a new thread and return its identifier.  The thread will call the\n\
1090 function with positional arguments from the tuple args and keyword arguments\n\
1091 taken from the optional dictionary kwargs.  The thread exits when the\n\
1092 function returns; the return value is ignored.  The thread will also exit\n\
1093 when the function raises an unhandled exception; a stack trace will be\n\
1094 printed unless the exception is SystemExit.\n");
1095 
1096 static PyObject *
thread_PyThread_exit_thread(PyObject * self)1097 thread_PyThread_exit_thread(PyObject *self)
1098 {
1099     PyErr_SetNone(PyExc_SystemExit);
1100     return NULL;
1101 }
1102 
1103 PyDoc_STRVAR(exit_doc,
1104 "exit()\n\
1105 (exit_thread() is an obsolete synonym)\n\
1106 \n\
1107 This is synonymous to ``raise SystemExit''.  It will cause the current\n\
1108 thread to exit silently unless the exception is caught.");
1109 
1110 static PyObject *
thread_PyThread_interrupt_main(PyObject * self)1111 thread_PyThread_interrupt_main(PyObject * self)
1112 {
1113     PyErr_SetInterrupt();
1114     Py_INCREF(Py_None);
1115     return Py_None;
1116 }
1117 
1118 PyDoc_STRVAR(interrupt_doc,
1119 "interrupt_main()\n\
1120 \n\
1121 Raise a KeyboardInterrupt in the main thread.\n\
1122 A subthread can use this function to interrupt the main thread."
1123 );
1124 
1125 static lockobject *newlockobject(void);
1126 
1127 static PyObject *
thread_PyThread_allocate_lock(PyObject * self)1128 thread_PyThread_allocate_lock(PyObject *self)
1129 {
1130     return (PyObject *) newlockobject();
1131 }
1132 
1133 PyDoc_STRVAR(allocate_doc,
1134 "allocate_lock() -> lock object\n\
1135 (allocate() is an obsolete synonym)\n\
1136 \n\
1137 Create a new lock object. See help(type(threading.Lock())) for\n\
1138 information about locks.");
1139 
1140 static PyObject *
thread_get_ident(PyObject * self)1141 thread_get_ident(PyObject *self)
1142 {
1143     long ident;
1144     ident = PyThread_get_thread_ident();
1145     if (ident == -1) {
1146         PyErr_SetString(ThreadError, "no current thread ident");
1147         return NULL;
1148     }
1149     return PyLong_FromLong(ident);
1150 }
1151 
1152 PyDoc_STRVAR(get_ident_doc,
1153 "get_ident() -> integer\n\
1154 \n\
1155 Return a non-zero integer that uniquely identifies the current thread\n\
1156 amongst other threads that exist simultaneously.\n\
1157 This may be used to identify per-thread resources.\n\
1158 Even though on some platforms threads identities may appear to be\n\
1159 allocated consecutive numbers starting at 1, this behavior should not\n\
1160 be relied upon, and the number should be seen purely as a magic cookie.\n\
1161 A thread's identity may be reused for another thread after it exits.");
1162 
1163 static PyObject *
thread__count(PyObject * self)1164 thread__count(PyObject *self)
1165 {
1166     return PyLong_FromLong(nb_threads);
1167 }
1168 
1169 PyDoc_STRVAR(_count_doc,
1170 "_count() -> integer\n\
1171 \n\
1172 \
1173 Return the number of currently running Python threads, excluding \n\
1174 the main thread. The returned number comprises all threads created\n\
1175 through `start_new_thread()` as well as `threading.Thread`, and not\n\
1176 yet finished.\n\
1177 \n\
1178 This function is meant for internal and specialized purposes only.\n\
1179 In most applications `threading.enumerate()` should be used instead.");
1180 
1181 static void
release_sentinel(void * wr)1182 release_sentinel(void *wr)
1183 {
1184     /* Tricky: this function is called when the current thread state
1185        is being deleted.  Therefore, only simple C code can safely
1186        execute here. */
1187     PyObject *obj = PyWeakref_GET_OBJECT(wr);
1188     lockobject *lock;
1189     if (obj != Py_None) {
1190         assert(Py_TYPE(obj) == &Locktype);
1191         lock = (lockobject *) obj;
1192         if (lock->locked) {
1193             PyThread_release_lock(lock->lock_lock);
1194             lock->locked = 0;
1195         }
1196     }
1197     /* Deallocating a weakref with a NULL callback only calls
1198        PyObject_GC_Del(), which can't call any Python code. */
1199     Py_DECREF(wr);
1200 }
1201 
1202 static PyObject *
thread__set_sentinel(PyObject * self)1203 thread__set_sentinel(PyObject *self)
1204 {
1205     PyObject *wr;
1206     PyThreadState *tstate = PyThreadState_Get();
1207     lockobject *lock;
1208 
1209     if (tstate->on_delete_data != NULL) {
1210         /* We must support the re-creation of the lock from a
1211            fork()ed child. */
1212         assert(tstate->on_delete == &release_sentinel);
1213         wr = (PyObject *) tstate->on_delete_data;
1214         tstate->on_delete = NULL;
1215         tstate->on_delete_data = NULL;
1216         Py_DECREF(wr);
1217     }
1218     lock = newlockobject();
1219     if (lock == NULL)
1220         return NULL;
1221     /* The lock is owned by whoever called _set_sentinel(), but the weakref
1222        hangs to the thread state. */
1223     wr = PyWeakref_NewRef((PyObject *) lock, NULL);
1224     if (wr == NULL) {
1225         Py_DECREF(lock);
1226         return NULL;
1227     }
1228     tstate->on_delete_data = (void *) wr;
1229     tstate->on_delete = &release_sentinel;
1230     return (PyObject *) lock;
1231 }
1232 
1233 PyDoc_STRVAR(_set_sentinel_doc,
1234 "_set_sentinel() -> lock\n\
1235 \n\
1236 Set a sentinel lock that will be released when the current thread\n\
1237 state is finalized (after it is untied from the interpreter).\n\
1238 \n\
1239 This is a private API for the threading module.");
1240 
1241 static PyObject *
thread_stack_size(PyObject * self,PyObject * args)1242 thread_stack_size(PyObject *self, PyObject *args)
1243 {
1244     size_t old_size;
1245     Py_ssize_t new_size = 0;
1246     int rc;
1247 
1248     if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
1249         return NULL;
1250 
1251     if (new_size < 0) {
1252         PyErr_SetString(PyExc_ValueError,
1253                         "size must be 0 or a positive value");
1254         return NULL;
1255     }
1256 
1257     old_size = PyThread_get_stacksize();
1258 
1259     rc = PyThread_set_stacksize((size_t) new_size);
1260     if (rc == -1) {
1261         PyErr_Format(PyExc_ValueError,
1262                      "size not valid: %zd bytes",
1263                      new_size);
1264         return NULL;
1265     }
1266     if (rc == -2) {
1267         PyErr_SetString(ThreadError,
1268                         "setting stack size not supported");
1269         return NULL;
1270     }
1271 
1272     return PyLong_FromSsize_t((Py_ssize_t) old_size);
1273 }
1274 
1275 PyDoc_STRVAR(stack_size_doc,
1276 "stack_size([size]) -> size\n\
1277 \n\
1278 Return the thread stack size used when creating new threads.  The\n\
1279 optional size argument specifies the stack size (in bytes) to be used\n\
1280 for subsequently created threads, and must be 0 (use platform or\n\
1281 configured default) or a positive integer value of at least 32,768 (32k).\n\
1282 If changing the thread stack size is unsupported, a ThreadError\n\
1283 exception is raised.  If the specified size is invalid, a ValueError\n\
1284 exception is raised, and the stack size is unmodified.  32k bytes\n\
1285  currently the minimum supported stack size value to guarantee\n\
1286 sufficient stack space for the interpreter itself.\n\
1287 \n\
1288 Note that some platforms may have particular restrictions on values for\n\
1289 the stack size, such as requiring a minimum stack size larger than 32kB or\n\
1290 requiring allocation in multiples of the system memory page size\n\
1291 - platform documentation should be referred to for more information\n\
1292 (4kB pages are common; using multiples of 4096 for the stack size is\n\
1293 the suggested approach in the absence of more specific information).");
1294 
1295 static PyMethodDef thread_methods[] = {
1296     {"start_new_thread",        (PyCFunction)thread_PyThread_start_new_thread,
1297      METH_VARARGS, start_new_doc},
1298     {"start_new",               (PyCFunction)thread_PyThread_start_new_thread,
1299      METH_VARARGS, start_new_doc},
1300     {"allocate_lock",           (PyCFunction)thread_PyThread_allocate_lock,
1301      METH_NOARGS, allocate_doc},
1302     {"allocate",                (PyCFunction)thread_PyThread_allocate_lock,
1303      METH_NOARGS, allocate_doc},
1304     {"exit_thread",             (PyCFunction)thread_PyThread_exit_thread,
1305      METH_NOARGS, exit_doc},
1306     {"exit",                    (PyCFunction)thread_PyThread_exit_thread,
1307      METH_NOARGS, exit_doc},
1308     {"interrupt_main",          (PyCFunction)thread_PyThread_interrupt_main,
1309      METH_NOARGS, interrupt_doc},
1310     {"get_ident",               (PyCFunction)thread_get_ident,
1311      METH_NOARGS, get_ident_doc},
1312     {"_count",                  (PyCFunction)thread__count,
1313      METH_NOARGS, _count_doc},
1314     {"stack_size",              (PyCFunction)thread_stack_size,
1315      METH_VARARGS, stack_size_doc},
1316     {"_set_sentinel",           (PyCFunction)thread__set_sentinel,
1317      METH_NOARGS, _set_sentinel_doc},
1318     {NULL,                      NULL}           /* sentinel */
1319 };
1320 
1321 
1322 /* Initialization function */
1323 
1324 PyDoc_STRVAR(thread_doc,
1325 "This module provides primitive operations to write multi-threaded programs.\n\
1326 The 'threading' module provides a more convenient interface.");
1327 
1328 PyDoc_STRVAR(lock_doc,
1329 "A lock object is a synchronization primitive.  To create a lock,\n\
1330 call threading.Lock().  Methods are:\n\
1331 \n\
1332 acquire() -- lock the lock, possibly blocking until it can be obtained\n\
1333 release() -- unlock of the lock\n\
1334 locked() -- test whether the lock is currently locked\n\
1335 \n\
1336 A lock is not owned by the thread that locked it; another thread may\n\
1337 unlock it.  A thread attempting to lock a lock that it has already locked\n\
1338 will block until another thread unlocks it.  Deadlocks may ensue.");
1339 
1340 static struct PyModuleDef threadmodule = {
1341     PyModuleDef_HEAD_INIT,
1342     "_thread",
1343     thread_doc,
1344     -1,
1345     thread_methods,
1346     NULL,
1347     NULL,
1348     NULL,
1349     NULL
1350 };
1351 
1352 
1353 PyMODINIT_FUNC
PyInit__thread(void)1354 PyInit__thread(void)
1355 {
1356     PyObject *m, *d, *v;
1357     double time_max;
1358     double timeout_max;
1359 
1360     /* Initialize types: */
1361     if (PyType_Ready(&localdummytype) < 0)
1362         return NULL;
1363     if (PyType_Ready(&localtype) < 0)
1364         return NULL;
1365     if (PyType_Ready(&Locktype) < 0)
1366         return NULL;
1367     if (PyType_Ready(&RLocktype) < 0)
1368         return NULL;
1369 
1370     /* Create the module and add the functions */
1371     m = PyModule_Create(&threadmodule);
1372     if (m == NULL)
1373         return NULL;
1374 
1375     timeout_max = PY_TIMEOUT_MAX / 1000000;
1376     time_max = floor(_PyTime_AsSecondsDouble(_PyTime_MAX));
1377     timeout_max = Py_MIN(timeout_max, time_max);
1378 
1379     v = PyFloat_FromDouble(timeout_max);
1380     if (!v)
1381         return NULL;
1382     if (PyModule_AddObject(m, "TIMEOUT_MAX", v) < 0)
1383         return NULL;
1384 
1385     /* Add a symbolic constant */
1386     d = PyModule_GetDict(m);
1387     ThreadError = PyExc_RuntimeError;
1388     Py_INCREF(ThreadError);
1389 
1390     PyDict_SetItemString(d, "error", ThreadError);
1391     Locktype.tp_doc = lock_doc;
1392     Py_INCREF(&Locktype);
1393     PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype);
1394 
1395     Py_INCREF(&RLocktype);
1396     if (PyModule_AddObject(m, "RLock", (PyObject *)&RLocktype) < 0)
1397         return NULL;
1398 
1399     Py_INCREF(&localtype);
1400     if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0)
1401         return NULL;
1402 
1403     nb_threads = 0;
1404 
1405     str_dict = PyUnicode_InternFromString("__dict__");
1406     if (str_dict == NULL)
1407         return NULL;
1408 
1409     /* Initialize the C thread library */
1410     PyThread_init_thread();
1411     return m;
1412 }
1413