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