blob: 5181d0705ef1b8f556fe5b6b79f76c9c215bea9b [file] [log] [blame]
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001
2/* Thread module */
3/* Interface to Sjoerd's portable C thread library */
4
Barry Warsawd0c10421996-12-17 00:05:22 +00005#include "Python.h"
Guido van Rossum1984f1e1992-08-04 12:41:02 +00006
Guido van Rossumb6775db1994-08-01 11:34:53 +00007#ifndef WITH_THREAD
Guido van Rossuma027efa1997-05-05 20:56:21 +00008#error "Error! The rest of Python is not compiled with thread support."
Neal Norwitz884baa12002-09-05 21:31:04 +00009#error "Rerun configure, adding a --with-threads option."
Guido van Rossuma027efa1997-05-05 20:56:21 +000010#error "Then run `make clean' followed by `make'."
Guido van Rossumb6775db1994-08-01 11:34:53 +000011#endif
12
Guido van Rossum49b56061998-10-01 20:42:43 +000013#include "pythread.h"
Guido van Rossum1984f1e1992-08-04 12:41:02 +000014
Barry Warsawd0c10421996-12-17 00:05:22 +000015static PyObject *ThreadError;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000016
17
18/* Lock objects */
19
20typedef struct {
Barry Warsawd0c10421996-12-17 00:05:22 +000021 PyObject_HEAD
Guido van Rossum65d5b571998-12-21 19:32:43 +000022 PyThread_type_lock lock_lock;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000023} lockobject;
24
Guido van Rossum1984f1e1992-08-04 12:41:02 +000025static void
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +000026lock_dealloc(lockobject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +000027{
Victor Stinner57740432010-03-03 00:51:28 +000028 if (self->lock_lock != NULL) {
29 /* Unlock the lock so it's safe to free it */
30 PyThread_acquire_lock(self->lock_lock, 0);
31 PyThread_release_lock(self->lock_lock);
32
33 PyThread_free_lock(self->lock_lock);
34 }
Guido van Rossumb18618d2000-05-03 23:44:39 +000035 PyObject_Del(self);
Guido van Rossum1984f1e1992-08-04 12:41:02 +000036}
37
Barry Warsawd0c10421996-12-17 00:05:22 +000038static PyObject *
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +000039lock_PyThread_acquire_lock(lockobject *self, PyObject *args)
Guido van Rossum1984f1e1992-08-04 12:41:02 +000040{
Neal Norwitzba3a16c2002-03-31 15:27:00 +000041 int i = 1;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000042
Neal Norwitzba3a16c2002-03-31 15:27:00 +000043 if (!PyArg_ParseTuple(args, "|i:acquire", &i))
44 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000045
Barry Warsawd0c10421996-12-17 00:05:22 +000046 Py_BEGIN_ALLOW_THREADS
Guido van Rossum65d5b571998-12-21 19:32:43 +000047 i = PyThread_acquire_lock(self->lock_lock, i);
Barry Warsawd0c10421996-12-17 00:05:22 +000048 Py_END_ALLOW_THREADS
Guido van Rossum1984f1e1992-08-04 12:41:02 +000049
Andrew M. Kuchlinga43ece92005-06-02 17:07:11 +000050 return PyBool_FromLong((long)i);
Guido van Rossum1984f1e1992-08-04 12:41:02 +000051}
52
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000053PyDoc_STRVAR(acquire_doc,
Guido van Rossum8fdc75b2002-04-07 06:32:21 +000054"acquire([wait]) -> None or bool\n\
Guido van Rossumf6694362006-03-10 02:28:35 +000055(acquire_lock() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +000056\n\
57Lock the lock. Without argument, this blocks if the lock is already\n\
58locked (even by the same thread), waiting for another thread to release\n\
Guido van Rossum8fdc75b2002-04-07 06:32:21 +000059the lock, and return None once the lock is acquired.\n\
60With an argument, this will only block if the argument is true,\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +000061and the return value reflects whether the lock is acquired.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000062The blocking operation is not interruptible.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +000063
Barry Warsawd0c10421996-12-17 00:05:22 +000064static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +000065lock_PyThread_release_lock(lockobject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +000066{
Guido van Rossum1984f1e1992-08-04 12:41:02 +000067 /* Sanity check: the lock must be locked */
Guido van Rossum65d5b571998-12-21 19:32:43 +000068 if (PyThread_acquire_lock(self->lock_lock, 0)) {
69 PyThread_release_lock(self->lock_lock);
Barry Warsawd0c10421996-12-17 00:05:22 +000070 PyErr_SetString(ThreadError, "release unlocked lock");
Guido van Rossum1984f1e1992-08-04 12:41:02 +000071 return NULL;
72 }
73
Guido van Rossum65d5b571998-12-21 19:32:43 +000074 PyThread_release_lock(self->lock_lock);
Barry Warsawd0c10421996-12-17 00:05:22 +000075 Py_INCREF(Py_None);
76 return Py_None;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000077}
78
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000079PyDoc_STRVAR(release_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +000080"release()\n\
Guido van Rossumf6694362006-03-10 02:28:35 +000081(release_lock() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +000082\n\
83Release the lock, allowing another thread that is blocked waiting for\n\
84the lock to acquire the lock. The lock must be in the locked state,\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000085but it needn't be locked by the same thread that unlocks it.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +000086
Barry Warsawd0c10421996-12-17 00:05:22 +000087static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +000088lock_locked_lock(lockobject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +000089{
Guido van Rossum65d5b571998-12-21 19:32:43 +000090 if (PyThread_acquire_lock(self->lock_lock, 0)) {
91 PyThread_release_lock(self->lock_lock);
Guido van Rossum8fdc75b2002-04-07 06:32:21 +000092 return PyBool_FromLong(0L);
Guido van Rossum1984f1e1992-08-04 12:41:02 +000093 }
Guido van Rossum8fdc75b2002-04-07 06:32:21 +000094 return PyBool_FromLong(1L);
Guido van Rossum1984f1e1992-08-04 12:41:02 +000095}
96
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000097PyDoc_STRVAR(locked_doc,
Guido van Rossum8fdc75b2002-04-07 06:32:21 +000098"locked() -> bool\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +000099(locked_lock() is an obsolete synonym)\n\
100\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000101Return whether the lock is in the locked state.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000102
Barry Warsawd0c10421996-12-17 00:05:22 +0000103static PyMethodDef lock_methods[] = {
Andrew M. Kuchlinga1abb722000-08-03 02:34:44 +0000104 {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock,
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000105 METH_VARARGS, acquire_doc},
Andrew M. Kuchlinga1abb722000-08-03 02:34:44 +0000106 {"acquire", (PyCFunction)lock_PyThread_acquire_lock,
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000107 METH_VARARGS, acquire_doc},
Andrew M. Kuchlinga1abb722000-08-03 02:34:44 +0000108 {"release_lock", (PyCFunction)lock_PyThread_release_lock,
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000109 METH_NOARGS, release_doc},
Andrew M. Kuchlinga1abb722000-08-03 02:34:44 +0000110 {"release", (PyCFunction)lock_PyThread_release_lock,
Neal Norwitz23584252002-03-25 21:05:50 +0000111 METH_NOARGS, release_doc},
Andrew M. Kuchlinga1abb722000-08-03 02:34:44 +0000112 {"locked_lock", (PyCFunction)lock_locked_lock,
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000113 METH_NOARGS, locked_doc},
Andrew M. Kuchlinga1abb722000-08-03 02:34:44 +0000114 {"locked", (PyCFunction)lock_locked_lock,
Neal Norwitz23584252002-03-25 21:05:50 +0000115 METH_NOARGS, locked_doc},
Guido van Rossum1a5e21e2006-02-28 21:57:43 +0000116 {"__enter__", (PyCFunction)lock_PyThread_acquire_lock,
117 METH_VARARGS, acquire_doc},
Guido van Rossumf6694362006-03-10 02:28:35 +0000118 {"__exit__", (PyCFunction)lock_PyThread_release_lock,
119 METH_VARARGS, release_doc},
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000120 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000121};
122
Barry Warsawd0c10421996-12-17 00:05:22 +0000123static PyTypeObject Locktype = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000124 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Georg Brandl0a7ac7d2008-05-26 10:29:35 +0000125 "_thread.lock", /*tp_name*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000126 sizeof(lockobject), /*tp_size*/
127 0, /*tp_itemsize*/
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000128 /* methods */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000129 (destructor)lock_dealloc, /*tp_dealloc*/
130 0, /*tp_print*/
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +0000131 0, /*tp_getattr*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000132 0, /*tp_setattr*/
Mark Dickinsone94c6792009-02-02 20:36:42 +0000133 0, /*tp_reserved*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000134 0, /*tp_repr*/
Amaury Forgeot d'Arce43d33a2008-07-02 20:50:16 +0000135 0, /*tp_as_number*/
136 0, /*tp_as_sequence*/
137 0, /*tp_as_mapping*/
138 0, /*tp_hash*/
139 0, /*tp_call*/
140 0, /*tp_str*/
141 0, /*tp_getattro*/
142 0, /*tp_setattro*/
143 0, /*tp_as_buffer*/
144 Py_TPFLAGS_DEFAULT, /*tp_flags*/
145 0, /*tp_doc*/
146 0, /*tp_traverse*/
147 0, /*tp_clear*/
148 0, /*tp_richcompare*/
149 0, /*tp_weaklistoffset*/
150 0, /*tp_iter*/
151 0, /*tp_iternext*/
152 lock_methods, /*tp_methods*/
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000153};
154
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000155static lockobject *
156newlockobject(void)
157{
158 lockobject *self;
159 self = PyObject_New(lockobject, &Locktype);
160 if (self == NULL)
161 return NULL;
162 self->lock_lock = PyThread_allocate_lock();
163 if (self->lock_lock == NULL) {
Victor Stinner57740432010-03-03 00:51:28 +0000164 Py_DECREF(self);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000165 PyErr_SetString(ThreadError, "can't allocate lock");
Victor Stinner57740432010-03-03 00:51:28 +0000166 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000167 }
168 return self;
169}
170
Jim Fultond15dc062004-07-14 19:11:50 +0000171/* Thread-local objects */
172
173#include "structmember.h"
174
175typedef struct {
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000176 PyObject_HEAD
177 PyObject *key;
178 PyObject *args;
179 PyObject *kw;
180 PyObject *dict;
Jim Fultond15dc062004-07-14 19:11:50 +0000181} localobject;
182
Jim Fultond15dc062004-07-14 19:11:50 +0000183static PyObject *
184local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
185{
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000186 localobject *self;
187 PyObject *tdict;
Jim Fultond15dc062004-07-14 19:11:50 +0000188
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000189 if (type->tp_init == PyBaseObject_Type.tp_init
190 && ((args && PyObject_IsTrue(args))
191 || (kw && PyObject_IsTrue(kw)))) {
192 PyErr_SetString(PyExc_TypeError,
193 "Initialization arguments are not supported");
194 return NULL;
195 }
Jim Fultond15dc062004-07-14 19:11:50 +0000196
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000197 self = (localobject *)type->tp_alloc(type, 0);
198 if (self == NULL)
199 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000200
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000201 Py_XINCREF(args);
202 self->args = args;
203 Py_XINCREF(kw);
204 self->kw = kw;
205 self->dict = NULL; /* making sure */
Walter Dörwald4ee631e2007-06-20 14:55:01 +0000206 self->key = PyUnicode_FromFormat("thread.local.%p", self);
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000207 if (self->key == NULL)
208 goto err;
Jim Fultond15dc062004-07-14 19:11:50 +0000209
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000210 self->dict = PyDict_New();
211 if (self->dict == NULL)
212 goto err;
Jim Fultond15dc062004-07-14 19:11:50 +0000213
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000214 tdict = PyThreadState_GetDict();
215 if (tdict == NULL) {
216 PyErr_SetString(PyExc_SystemError,
217 "Couldn't get thread-state dictionary");
218 goto err;
219 }
Jim Fultond15dc062004-07-14 19:11:50 +0000220
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000221 if (PyDict_SetItem(tdict, self->key, self->dict) < 0)
222 goto err;
Jim Fultond15dc062004-07-14 19:11:50 +0000223
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000224 return (PyObject *)self;
225
226 err:
227 Py_DECREF(self);
228 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000229}
230
231static int
232local_traverse(localobject *self, visitproc visit, void *arg)
233{
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000234 Py_VISIT(self->args);
235 Py_VISIT(self->kw);
236 Py_VISIT(self->dict);
Jim Fultond15dc062004-07-14 19:11:50 +0000237 return 0;
238}
239
240static int
241local_clear(localobject *self)
242{
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000243 Py_CLEAR(self->args);
244 Py_CLEAR(self->kw);
245 Py_CLEAR(self->dict);
246 return 0;
Jim Fultond15dc062004-07-14 19:11:50 +0000247}
248
249static void
250local_dealloc(localobject *self)
251{
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000252 PyThreadState *tstate;
253 if (self->key
254 && (tstate = PyThreadState_Get())
255 && tstate->interp) {
256 for(tstate = PyInterpreterState_ThreadHead(tstate->interp);
257 tstate;
258 tstate = PyThreadState_Next(tstate))
259 if (tstate->dict &&
260 PyDict_GetItem(tstate->dict, self->key))
261 PyDict_DelItem(tstate->dict, self->key);
262 }
Jim Fultond15dc062004-07-14 19:11:50 +0000263
Philip Jenvey962b05c2009-09-29 05:03:48 +0000264 Py_XDECREF(self->key);
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000265 local_clear(self);
Christian Heimes90aa7642007-12-19 02:45:37 +0000266 Py_TYPE(self)->tp_free((PyObject*)self);
Jim Fultond15dc062004-07-14 19:11:50 +0000267}
268
269static PyObject *
270_ldict(localobject *self)
271{
272 PyObject *tdict, *ldict;
273
274 tdict = PyThreadState_GetDict();
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000275 if (tdict == NULL) {
276 PyErr_SetString(PyExc_SystemError,
277 "Couldn't get thread-state dictionary");
278 return NULL;
279 }
Jim Fultond15dc062004-07-14 19:11:50 +0000280
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000281 ldict = PyDict_GetItem(tdict, self->key);
282 if (ldict == NULL) {
283 ldict = PyDict_New(); /* we own ldict */
Jim Fultond15dc062004-07-14 19:11:50 +0000284
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000285 if (ldict == NULL)
286 return NULL;
287 else {
288 int i = PyDict_SetItem(tdict, self->key, ldict);
Georg Brandlf3c4ad12006-03-08 12:24:33 +0000289 Py_DECREF(ldict); /* now ldict is borrowed */
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000290 if (i < 0)
291 return NULL;
292 }
Jim Fultond15dc062004-07-14 19:11:50 +0000293
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000294 Py_CLEAR(self->dict);
295 Py_INCREF(ldict);
296 self->dict = ldict; /* still borrowed */
Jim Fultond15dc062004-07-14 19:11:50 +0000297
Christian Heimes90aa7642007-12-19 02:45:37 +0000298 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
299 Py_TYPE(self)->tp_init((PyObject*)self,
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000300 self->args, self->kw) < 0) {
301 /* we need to get rid of ldict from thread so
302 we create a new one the next time we do an attr
303 acces */
304 PyDict_DelItem(tdict, self->key);
305 return NULL;
306 }
307
308 }
Benjamin Peterson8a250ae2008-06-30 23:30:24 +0000309
310 /* The call to tp_init above may have caused another thread to run.
311 Install our ldict again. */
312 if (self->dict != ldict) {
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000313 Py_CLEAR(self->dict);
314 Py_INCREF(ldict);
315 self->dict = ldict;
316 }
Jim Fultond15dc062004-07-14 19:11:50 +0000317
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000318 return ldict;
Jim Fultond15dc062004-07-14 19:11:50 +0000319}
320
Jim Fultond15dc062004-07-14 19:11:50 +0000321static int
322local_setattro(localobject *self, PyObject *name, PyObject *v)
323{
324 PyObject *ldict;
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000325
326 ldict = _ldict(self);
327 if (ldict == NULL)
328 return -1;
Jim Fultond15dc062004-07-14 19:11:50 +0000329
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000330 return PyObject_GenericSetAttr((PyObject *)self, name, v);
Jim Fultond15dc062004-07-14 19:11:50 +0000331}
332
333static PyObject *
334local_getdict(localobject *self, void *closure)
335{
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000336 if (self->dict == NULL) {
337 PyErr_SetString(PyExc_AttributeError, "__dict__");
338 return NULL;
339 }
Jim Fultond15dc062004-07-14 19:11:50 +0000340
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000341 Py_INCREF(self->dict);
342 return self->dict;
Jim Fultond15dc062004-07-14 19:11:50 +0000343}
344
345static PyGetSetDef local_getset[] = {
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000346 {"__dict__", (getter)local_getdict, (setter)NULL,
347 "Local-data dictionary", NULL},
348 {NULL} /* Sentinel */
Jim Fultond15dc062004-07-14 19:11:50 +0000349};
350
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000351static PyObject *local_getattro(localobject *, PyObject *);
352
Jim Fultond15dc062004-07-14 19:11:50 +0000353static PyTypeObject localtype = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000354 PyVarObject_HEAD_INIT(NULL, 0)
Georg Brandl0a7ac7d2008-05-26 10:29:35 +0000355 /* tp_name */ "_thread._local",
Jim Fultond15dc062004-07-14 19:11:50 +0000356 /* tp_basicsize */ sizeof(localobject),
357 /* tp_itemsize */ 0,
358 /* tp_dealloc */ (destructor)local_dealloc,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000359 /* tp_print */ 0,
360 /* tp_getattr */ 0,
361 /* tp_setattr */ 0,
Mark Dickinsone94c6792009-02-02 20:36:42 +0000362 /* tp_reserved */ 0,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000363 /* tp_repr */ 0,
Jim Fultond15dc062004-07-14 19:11:50 +0000364 /* tp_as_number */ 0,
365 /* tp_as_sequence */ 0,
366 /* tp_as_mapping */ 0,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000367 /* tp_hash */ 0,
368 /* tp_call */ 0,
369 /* tp_str */ 0,
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000370 /* tp_getattro */ (getattrofunc)local_getattro,
371 /* tp_setattro */ (setattrofunc)local_setattro,
372 /* tp_as_buffer */ 0,
373 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
Jim Fultond15dc062004-07-14 19:11:50 +0000374 /* tp_doc */ "Thread-local data",
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000375 /* tp_traverse */ (traverseproc)local_traverse,
376 /* tp_clear */ (inquiry)local_clear,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000377 /* tp_richcompare */ 0,
378 /* tp_weaklistoffset */ 0,
379 /* tp_iter */ 0,
380 /* tp_iternext */ 0,
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000381 /* tp_methods */ 0,
382 /* tp_members */ 0,
383 /* tp_getset */ local_getset,
384 /* tp_base */ 0,
385 /* tp_dict */ 0, /* internal use */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000386 /* tp_descr_get */ 0,
387 /* tp_descr_set */ 0,
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000388 /* tp_dictoffset */ offsetof(localobject, dict),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000389 /* tp_init */ 0,
390 /* tp_alloc */ 0,
391 /* tp_new */ local_new,
Jim Fultond15dc062004-07-14 19:11:50 +0000392 /* tp_free */ 0, /* Low-level free-mem routine */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000393 /* tp_is_gc */ 0, /* For PyObject_IS_GC */
Jim Fultond15dc062004-07-14 19:11:50 +0000394};
395
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000396static PyObject *
397local_getattro(localobject *self, PyObject *name)
398{
399 PyObject *ldict, *value;
400
401 ldict = _ldict(self);
402 if (ldict == NULL)
403 return NULL;
404
Christian Heimes90aa7642007-12-19 02:45:37 +0000405 if (Py_TYPE(self) != &localtype)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000406 /* use generic lookup for subtypes */
407 return PyObject_GenericGetAttr((PyObject *)self, name);
408
409 /* Optimization: just look in dict ourselves */
410 value = PyDict_GetItem(ldict, name);
411 if (value == NULL)
412 /* Fall back on generic to get __class__ and __dict__ */
413 return PyObject_GenericGetAttr((PyObject *)self, name);
414
415 Py_INCREF(value);
416 return value;
417}
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000418
419/* Module functions */
420
Guido van Rossuma027efa1997-05-05 20:56:21 +0000421struct bootstate {
422 PyInterpreterState *interp;
423 PyObject *func;
424 PyObject *args;
425 PyObject *keyw;
426};
427
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000428static void
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +0000429t_bootstrap(void *boot_raw)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000430{
Guido van Rossuma027efa1997-05-05 20:56:21 +0000431 struct bootstate *boot = (struct bootstate *) boot_raw;
Michael W. Hudson188d4362005-06-20 16:52:57 +0000432 PyThreadState *tstate;
Guido van Rossuma027efa1997-05-05 20:56:21 +0000433 PyObject *res;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000434
Michael W. Hudson188d4362005-06-20 16:52:57 +0000435 tstate = PyThreadState_New(boot->interp);
436
437 PyEval_AcquireThread(tstate);
Guido van Rossuma027efa1997-05-05 20:56:21 +0000438 res = PyEval_CallObjectWithKeywords(
439 boot->func, boot->args, boot->keyw);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000440 if (res == NULL) {
Fred Drakebebc97f1998-05-28 04:35:12 +0000441 if (PyErr_ExceptionMatches(PyExc_SystemExit))
Barry Warsawd0c10421996-12-17 00:05:22 +0000442 PyErr_Clear();
Guido van Rossum385e7c61995-03-17 10:42:27 +0000443 else {
Guido van Rossum24ccca12003-04-29 19:44:05 +0000444 PyObject *file;
445 PySys_WriteStderr(
446 "Unhandled exception in thread started by ");
447 file = PySys_GetObject("stderr");
Christian Heimes2be03732007-11-15 02:26:46 +0000448 if (file != NULL && file != Py_None)
Guido van Rossum24ccca12003-04-29 19:44:05 +0000449 PyFile_WriteObject(boot->func, file, 0);
450 else
451 PyObject_Print(boot->func, stderr, 0);
452 PySys_WriteStderr("\n");
Guido van Rossum40769dd1998-02-06 22:32:08 +0000453 PyErr_PrintEx(0);
Guido van Rossum385e7c61995-03-17 10:42:27 +0000454 }
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000455 }
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000456 else
Barry Warsawd0c10421996-12-17 00:05:22 +0000457 Py_DECREF(res);
Guido van Rossum24ccca12003-04-29 19:44:05 +0000458 Py_DECREF(boot->func);
459 Py_DECREF(boot->args);
460 Py_XDECREF(boot->keyw);
461 PyMem_DEL(boot_raw);
Michael W. Hudson188d4362005-06-20 16:52:57 +0000462 PyThreadState_Clear(tstate);
463 PyThreadState_DeleteCurrent();
Guido van Rossumbcc20741998-08-04 22:53:56 +0000464 PyThread_exit_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000465}
466
Barry Warsawd0c10421996-12-17 00:05:22 +0000467static PyObject *
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +0000468thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000469{
Guido van Rossum38d45b72000-09-01 20:47:58 +0000470 PyObject *func, *args, *keyw = NULL;
Guido van Rossuma027efa1997-05-05 20:56:21 +0000471 struct bootstate *boot;
Guido van Rossum3c288632001-10-16 21:13:49 +0000472 long ident;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000473
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000474 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
475 &func, &args, &keyw))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000476 return NULL;
Guido van Rossuma027efa1997-05-05 20:56:21 +0000477 if (!PyCallable_Check(func)) {
478 PyErr_SetString(PyExc_TypeError,
479 "first arg must be callable");
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000480 return NULL;
481 }
Guido van Rossuma027efa1997-05-05 20:56:21 +0000482 if (!PyTuple_Check(args)) {
483 PyErr_SetString(PyExc_TypeError,
Guido van Rossum38d45b72000-09-01 20:47:58 +0000484 "2nd arg must be a tuple");
Guido van Rossuma027efa1997-05-05 20:56:21 +0000485 return NULL;
486 }
487 if (keyw != NULL && !PyDict_Check(keyw)) {
488 PyErr_SetString(PyExc_TypeError,
489 "optional 3rd arg must be a dictionary");
490 return NULL;
491 }
492 boot = PyMem_NEW(struct bootstate, 1);
493 if (boot == NULL)
494 return PyErr_NoMemory();
Nicholas Bastine5662ae2004-03-24 22:22:12 +0000495 boot->interp = PyThreadState_GET()->interp;
Guido van Rossuma027efa1997-05-05 20:56:21 +0000496 boot->func = func;
497 boot->args = args;
498 boot->keyw = keyw;
499 Py_INCREF(func);
500 Py_INCREF(args);
501 Py_XINCREF(keyw);
502 PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
Guido van Rossum3c288632001-10-16 21:13:49 +0000503 ident = PyThread_start_new_thread(t_bootstrap, (void*) boot);
504 if (ident == -1) {
Guido van Rossum54c273c2005-02-20 03:02:16 +0000505 PyErr_SetString(ThreadError, "can't start new thread");
Guido van Rossuma027efa1997-05-05 20:56:21 +0000506 Py_DECREF(func);
507 Py_DECREF(args);
508 Py_XDECREF(keyw);
509 PyMem_DEL(boot);
510 return NULL;
511 }
Christian Heimes217cfd12007-12-02 14:31:20 +0000512 return PyLong_FromLong(ident);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000513}
514
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000515PyDoc_STRVAR(start_new_doc,
Andrew M. Kuchling38300c62001-10-05 12:24:15 +0000516"start_new_thread(function, args[, kwargs])\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000517(start_new() is an obsolete synonym)\n\
518\n\
Guido van Rossum3c288632001-10-16 21:13:49 +0000519Start a new thread and return its identifier. The thread will call the\n\
520function with positional arguments from the tuple args and keyword arguments\n\
521taken from the optional dictionary kwargs. The thread exits when the\n\
522function returns; the return value is ignored. The thread will also exit\n\
523when the function raises an unhandled exception; a stack trace will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000524printed unless the exception is SystemExit.\n");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000525
Barry Warsawd0c10421996-12-17 00:05:22 +0000526static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000527thread_PyThread_exit_thread(PyObject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000528{
Barry Warsawd0c10421996-12-17 00:05:22 +0000529 PyErr_SetNone(PyExc_SystemExit);
Guido van Rossum385e7c61995-03-17 10:42:27 +0000530 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000531}
532
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000533PyDoc_STRVAR(exit_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000534"exit()\n\
Guido van Rossum65d5b571998-12-21 19:32:43 +0000535(PyThread_exit_thread() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000536\n\
537This is synonymous to ``raise SystemExit''. It will cause the current\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000538thread to exit silently unless the exception is caught.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000539
Kurt B. Kaisera11e8462003-06-13 21:59:45 +0000540static PyObject *
Kurt B. Kaisera1ad5f62003-06-16 18:51:28 +0000541thread_PyThread_interrupt_main(PyObject * self)
Kurt B. Kaisera11e8462003-06-13 21:59:45 +0000542{
543 PyErr_SetInterrupt();
544 Py_INCREF(Py_None);
545 return Py_None;
546}
547
548PyDoc_STRVAR(interrupt_doc,
549"interrupt_main()\n\
550\n\
551Raise a KeyboardInterrupt in the main thread.\n\
Kurt B. Kaisera1ad5f62003-06-16 18:51:28 +0000552A subthread can use this function to interrupt the main thread."
Kurt B. Kaisera11e8462003-06-13 21:59:45 +0000553);
554
Guido van Rossumb6775db1994-08-01 11:34:53 +0000555#ifndef NO_EXIT_PROG
Barry Warsawd0c10421996-12-17 00:05:22 +0000556static PyObject *
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +0000557thread_PyThread_exit_prog(PyObject *self, PyObject *args)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000558{
559 int sts;
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000560 if (!PyArg_ParseTuple(args, "i:exit_prog", &sts))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000561 return NULL;
Guido van Rossum65d5b571998-12-21 19:32:43 +0000562 Py_Exit(sts); /* Calls PyThread_exit_prog(sts) or _PyThread_exit_prog(sts) */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000563 for (;;) { } /* Should not be reached */
564}
Guido van Rossumb6775db1994-08-01 11:34:53 +0000565#endif
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000566
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000567static lockobject *newlockobject(void);
568
Barry Warsawd0c10421996-12-17 00:05:22 +0000569static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000570thread_PyThread_allocate_lock(PyObject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000571{
Barry Warsawd0c10421996-12-17 00:05:22 +0000572 return (PyObject *) newlockobject();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000573}
574
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000575PyDoc_STRVAR(allocate_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000576"allocate_lock() -> lock object\n\
577(allocate() is an obsolete synonym)\n\
578\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000579Create a new lock object. See LockType.__doc__ for information about locks.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000580
Barry Warsawd0c10421996-12-17 00:05:22 +0000581static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000582thread_get_ident(PyObject *self)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000583{
584 long ident;
Guido van Rossum65d5b571998-12-21 19:32:43 +0000585 ident = PyThread_get_thread_ident();
Guido van Rossumb6775db1994-08-01 11:34:53 +0000586 if (ident == -1) {
Barry Warsawd0c10421996-12-17 00:05:22 +0000587 PyErr_SetString(ThreadError, "no current thread ident");
Guido van Rossumb6775db1994-08-01 11:34:53 +0000588 return NULL;
589 }
Christian Heimes217cfd12007-12-02 14:31:20 +0000590 return PyLong_FromLong(ident);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000591}
592
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000593PyDoc_STRVAR(get_ident_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000594"get_ident() -> integer\n\
595\n\
596Return a non-zero integer that uniquely identifies the current thread\n\
597amongst other threads that exist simultaneously.\n\
598This may be used to identify per-thread resources.\n\
599Even though on some platforms threads identities may appear to be\n\
600allocated consecutive numbers starting at 1, this behavior should not\n\
601be relied upon, and the number should be seen purely as a magic cookie.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000602A thread's identity may be reused for another thread after it exits.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000603
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000604static PyObject *
605thread_stack_size(PyObject *self, PyObject *args)
606{
607 size_t old_size;
608 Py_ssize_t new_size = 0;
609 int rc;
610
611 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
612 return NULL;
613
614 if (new_size < 0) {
615 PyErr_SetString(PyExc_ValueError,
616 "size must be 0 or a positive value");
617 return NULL;
618 }
619
620 old_size = PyThread_get_stacksize();
621
622 rc = PyThread_set_stacksize((size_t) new_size);
623 if (rc == -1) {
624 PyErr_Format(PyExc_ValueError,
625 "size not valid: %zd bytes",
626 new_size);
627 return NULL;
628 }
629 if (rc == -2) {
630 PyErr_SetString(ThreadError,
631 "setting stack size not supported");
632 return NULL;
633 }
634
Christian Heimes217cfd12007-12-02 14:31:20 +0000635 return PyLong_FromSsize_t((Py_ssize_t) old_size);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000636}
637
638PyDoc_STRVAR(stack_size_doc,
639"stack_size([size]) -> size\n\
640\n\
641Return the thread stack size used when creating new threads. The\n\
642optional size argument specifies the stack size (in bytes) to be used\n\
643for subsequently created threads, and must be 0 (use platform or\n\
644configured default) or a positive integer value of at least 32,768 (32k).\n\
645If changing the thread stack size is unsupported, a ThreadError\n\
646exception is raised. If the specified size is invalid, a ValueError\n\
647exception is raised, and the stack size is unmodified. 32k bytes\n\
648 currently the minimum supported stack size value to guarantee\n\
649sufficient stack space for the interpreter itself.\n\
650\n\
651Note that some platforms may have particular restrictions on values for\n\
652the stack size, such as requiring a minimum stack size larger than 32kB or\n\
653requiring allocation in multiples of the system memory page size\n\
654- platform documentation should be referred to for more information\n\
655(4kB pages are common; using multiples of 4096 for the stack size is\n\
656the suggested approach in the absence of more specific information).");
657
Barry Warsawd0c10421996-12-17 00:05:22 +0000658static PyMethodDef thread_methods[] = {
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000659 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
660 METH_VARARGS,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000661 start_new_doc},
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000662 {"start_new", (PyCFunction)thread_PyThread_start_new_thread,
663 METH_VARARGS,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000664 start_new_doc},
Andrew M. Kuchlinga1abb722000-08-03 02:34:44 +0000665 {"allocate_lock", (PyCFunction)thread_PyThread_allocate_lock,
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000666 METH_NOARGS, allocate_doc},
Andrew M. Kuchlinga1abb722000-08-03 02:34:44 +0000667 {"allocate", (PyCFunction)thread_PyThread_allocate_lock,
Neal Norwitz46321172002-03-26 14:52:00 +0000668 METH_NOARGS, allocate_doc},
Andrew M. Kuchlinga1abb722000-08-03 02:34:44 +0000669 {"exit_thread", (PyCFunction)thread_PyThread_exit_thread,
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000670 METH_NOARGS, exit_doc},
Andrew M. Kuchlinga1abb722000-08-03 02:34:44 +0000671 {"exit", (PyCFunction)thread_PyThread_exit_thread,
Neal Norwitz46321172002-03-26 14:52:00 +0000672 METH_NOARGS, exit_doc},
Kurt B. Kaisera1ad5f62003-06-16 18:51:28 +0000673 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main,
Kurt B. Kaisera11e8462003-06-13 21:59:45 +0000674 METH_NOARGS, interrupt_doc},
Andrew M. Kuchlinga1abb722000-08-03 02:34:44 +0000675 {"get_ident", (PyCFunction)thread_get_ident,
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000676 METH_NOARGS, get_ident_doc},
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000677 {"stack_size", (PyCFunction)thread_stack_size,
678 METH_VARARGS,
679 stack_size_doc},
Guido van Rossumb6775db1994-08-01 11:34:53 +0000680#ifndef NO_EXIT_PROG
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000681 {"exit_prog", (PyCFunction)thread_PyThread_exit_prog,
682 METH_VARARGS},
Guido van Rossumb6775db1994-08-01 11:34:53 +0000683#endif
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000684 {NULL, NULL} /* sentinel */
685};
686
687
688/* Initialization function */
689
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000690PyDoc_STRVAR(thread_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000691"This module provides primitive operations to write multi-threaded programs.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000692The 'threading' module provides a more convenient interface.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000693
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000694PyDoc_STRVAR(lock_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000695"A lock object is a synchronization primitive. To create a lock,\n\
Guido van Rossum65d5b571998-12-21 19:32:43 +0000696call the PyThread_allocate_lock() function. Methods are:\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000697\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000698acquire() -- lock the lock, possibly blocking until it can be obtained\n\
699release() -- unlock of the lock\n\
700locked() -- test whether the lock is currently locked\n\
701\n\
702A lock is not owned by the thread that locked it; another thread may\n\
703unlock it. A thread attempting to lock a lock that it has already locked\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000704will block until another thread unlocks it. Deadlocks may ensue.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000705
Martin v. Löwis1a214512008-06-11 05:26:20 +0000706static struct PyModuleDef threadmodule = {
707 PyModuleDef_HEAD_INIT,
708 "_thread",
709 thread_doc,
710 -1,
711 thread_methods,
712 NULL,
713 NULL,
714 NULL,
715 NULL
716};
717
718
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000719PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000720PyInit__thread(void)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000721{
Barry Warsawd0c10421996-12-17 00:05:22 +0000722 PyObject *m, *d;
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000723
724 /* Initialize types: */
725 if (PyType_Ready(&localtype) < 0)
Martin v. Löwis1a214512008-06-11 05:26:20 +0000726 return NULL;
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000727 if (PyType_Ready(&Locktype) < 0)
Martin v. Löwis1a214512008-06-11 05:26:20 +0000728 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000729
730 /* Create the module and add the functions */
Martin v. Löwis1a214512008-06-11 05:26:20 +0000731 m = PyModule_Create(&threadmodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000732 if (m == NULL)
Martin v. Löwis1a214512008-06-11 05:26:20 +0000733 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000734
735 /* Add a symbolic constant */
Barry Warsawd0c10421996-12-17 00:05:22 +0000736 d = PyModule_GetDict(m);
Georg Brandl2067bfd2008-05-25 13:05:15 +0000737 ThreadError = PyErr_NewException("_thread.error", NULL, NULL);
Barry Warsawd0c10421996-12-17 00:05:22 +0000738 PyDict_SetItemString(d, "error", ThreadError);
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000739 Locktype.tp_doc = lock_doc;
740 Py_INCREF(&Locktype);
741 PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000742
Michael W. Hudson64e08142005-06-15 12:25:20 +0000743 Py_INCREF(&localtype);
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000744 if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0)
Martin v. Löwis1a214512008-06-11 05:26:20 +0000745 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000746
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000747 /* Initialize the C thread library */
Guido van Rossum65d5b571998-12-21 19:32:43 +0000748 PyThread_init_thread();
Martin v. Löwis1a214512008-06-11 05:26:20 +0000749 return m;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000750}