blob: e218ed6be599b38a65667b1fe643b3cfb36cc67e [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 {
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000021 PyObject_HEAD
22 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{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +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 }
35 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{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000041 int i = 1;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000042
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000043 if (!PyArg_ParseTuple(args, "|i:acquire", &i))
44 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000045
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000046 Py_BEGIN_ALLOW_THREADS
47 i = PyThread_acquire_lock(self->lock_lock, i);
48 Py_END_ALLOW_THREADS
Guido van Rossum1984f1e1992-08-04 12:41:02 +000049
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +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{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000067 /* Sanity check: the lock must be locked */
68 if (PyThread_acquire_lock(self->lock_lock, 0)) {
69 PyThread_release_lock(self->lock_lock);
70 PyErr_SetString(ThreadError, "release unlocked lock");
71 return NULL;
72 }
Guido van Rossum1984f1e1992-08-04 12:41:02 +000073
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000074 PyThread_release_lock(self->lock_lock);
75 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{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +000090 if (PyThread_acquire_lock(self->lock_lock, 0)) {
91 PyThread_release_lock(self->lock_lock);
92 return PyBool_FromLong(0L);
93 }
94 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[] = {
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000104 {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock,
105 METH_VARARGS, acquire_doc},
106 {"acquire", (PyCFunction)lock_PyThread_acquire_lock,
107 METH_VARARGS, acquire_doc},
108 {"release_lock", (PyCFunction)lock_PyThread_release_lock,
109 METH_NOARGS, release_doc},
110 {"release", (PyCFunction)lock_PyThread_release_lock,
111 METH_NOARGS, release_doc},
112 {"locked_lock", (PyCFunction)lock_locked_lock,
113 METH_NOARGS, locked_doc},
114 {"locked", (PyCFunction)lock_locked_lock,
115 METH_NOARGS, locked_doc},
116 {"__enter__", (PyCFunction)lock_PyThread_acquire_lock,
117 METH_VARARGS, acquire_doc},
118 {"__exit__", (PyCFunction)lock_PyThread_release_lock,
119 METH_VARARGS, release_doc},
120 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000121};
122
Barry Warsawd0c10421996-12-17 00:05:22 +0000123static PyTypeObject Locktype = {
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000124 PyVarObject_HEAD_INIT(&PyType_Type, 0)
125 "_thread.lock", /*tp_name*/
126 sizeof(lockobject), /*tp_size*/
127 0, /*tp_itemsize*/
128 /* methods */
129 (destructor)lock_dealloc, /*tp_dealloc*/
130 0, /*tp_print*/
131 0, /*tp_getattr*/
132 0, /*tp_setattr*/
133 0, /*tp_reserved*/
134 0, /*tp_repr*/
135 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{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000158 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) {
164 Py_DECREF(self);
165 PyErr_SetString(ThreadError, "can't allocate lock");
166 return NULL;
167 }
168 return self;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000169}
170
Jim Fultond15dc062004-07-14 19:11:50 +0000171/* Thread-local objects */
172
173#include "structmember.h"
174
175typedef struct {
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +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{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000186 localobject *self;
187 PyObject *tdict;
Jim Fultond15dc062004-07-14 19:11:50 +0000188
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +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
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000197 self = (localobject *)type->tp_alloc(type, 0);
198 if (self == NULL)
199 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000200
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000201 Py_XINCREF(args);
202 self->args = args;
203 Py_XINCREF(kw);
204 self->kw = kw;
205 self->dict = NULL; /* making sure */
206 self->key = PyUnicode_FromFormat("thread.local.%p", self);
207 if (self->key == NULL)
208 goto err;
Jim Fultond15dc062004-07-14 19:11:50 +0000209
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000210 self->dict = PyDict_New();
211 if (self->dict == NULL)
212 goto err;
Jim Fultond15dc062004-07-14 19:11:50 +0000213
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +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
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000221 if (PyDict_SetItem(tdict, self->key, self->dict) < 0)
222 goto err;
Jim Fultond15dc062004-07-14 19:11:50 +0000223
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000224 return (PyObject *)self;
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000225
226 err:
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000227 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{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000234 Py_VISIT(self->args);
235 Py_VISIT(self->kw);
236 Py_VISIT(self->dict);
237 return 0;
Jim Fultond15dc062004-07-14 19:11:50 +0000238}
239
240static int
241local_clear(localobject *self)
242{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +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{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +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
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000264 Py_XDECREF(self->key);
265 local_clear(self);
266 Py_TYPE(self)->tp_free((PyObject*)self);
Jim Fultond15dc062004-07-14 19:11:50 +0000267}
268
269static PyObject *
270_ldict(localobject *self)
271{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000272 PyObject *tdict, *ldict;
Jim Fultond15dc062004-07-14 19:11:50 +0000273
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000274 tdict = PyThreadState_GetDict();
275 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
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +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
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000285 if (ldict == NULL)
286 return NULL;
287 else {
288 int i = PyDict_SetItem(tdict, self->key, ldict);
289 Py_DECREF(ldict); /* now ldict is borrowed */
290 if (i < 0)
291 return NULL;
292 }
Jim Fultond15dc062004-07-14 19:11:50 +0000293
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000294 Py_CLEAR(self->dict);
295 Py_INCREF(ldict);
296 self->dict = ldict; /* still borrowed */
Jim Fultond15dc062004-07-14 19:11:50 +0000297
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000298 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
299 Py_TYPE(self)->tp_init((PyObject*)self,
300 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 }
Benjamin Peterson8a250ae2008-06-30 23:30:24 +0000307
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000308 }
Jim Fultond15dc062004-07-14 19:11:50 +0000309
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000310 /* The call to tp_init above may have caused another thread to run.
311 Install our ldict again. */
312 if (self->dict != ldict) {
313 Py_CLEAR(self->dict);
314 Py_INCREF(ldict);
315 self->dict = ldict;
316 }
317
318 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{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000324 PyObject *ldict;
Jim Fultond15dc062004-07-14 19:11:50 +0000325
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000326 ldict = _ldict(self);
327 if (ldict == NULL)
328 return -1;
329
330 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{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000336 if (self->dict == NULL) {
337 PyErr_SetString(PyExc_AttributeError, "__dict__");
338 return NULL;
339 }
Jim Fultond15dc062004-07-14 19:11:50 +0000340
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000341 Py_INCREF(self->dict);
342 return self->dict;
Jim Fultond15dc062004-07-14 19:11:50 +0000343}
344
345static PyGetSetDef local_getset[] = {
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +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 = {
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000354 PyVarObject_HEAD_INIT(NULL, 0)
355 /* tp_name */ "_thread._local",
356 /* tp_basicsize */ sizeof(localobject),
357 /* tp_itemsize */ 0,
358 /* tp_dealloc */ (destructor)local_dealloc,
359 /* tp_print */ 0,
360 /* tp_getattr */ 0,
361 /* tp_setattr */ 0,
362 /* tp_reserved */ 0,
363 /* tp_repr */ 0,
364 /* tp_as_number */ 0,
365 /* tp_as_sequence */ 0,
366 /* tp_as_mapping */ 0,
367 /* tp_hash */ 0,
368 /* tp_call */ 0,
369 /* tp_str */ 0,
370 /* 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,
374 /* tp_doc */ "Thread-local data",
375 /* tp_traverse */ (traverseproc)local_traverse,
376 /* tp_clear */ (inquiry)local_clear,
377 /* tp_richcompare */ 0,
378 /* tp_weaklistoffset */ 0,
379 /* tp_iter */ 0,
380 /* tp_iternext */ 0,
381 /* tp_methods */ 0,
382 /* tp_members */ 0,
383 /* tp_getset */ local_getset,
384 /* tp_base */ 0,
385 /* tp_dict */ 0, /* internal use */
386 /* tp_descr_get */ 0,
387 /* tp_descr_set */ 0,
388 /* tp_dictoffset */ offsetof(localobject, dict),
389 /* tp_init */ 0,
390 /* tp_alloc */ 0,
391 /* tp_new */ local_new,
392 /* tp_free */ 0, /* Low-level free-mem routine */
393 /* 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{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000399 PyObject *ldict, *value;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000400
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000401 ldict = _ldict(self);
402 if (ldict == NULL)
403 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000404
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000405 if (Py_TYPE(self) != &localtype)
406 /* use generic lookup for subtypes */
407 return PyObject_GenericGetAttr((PyObject *)self, name);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000408
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000409 /* 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);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000414
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000415 Py_INCREF(value);
416 return value;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000417}
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000418
419/* Module functions */
420
Guido van Rossuma027efa1997-05-05 20:56:21 +0000421struct bootstate {
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000422 PyInterpreterState *interp;
423 PyObject *func;
424 PyObject *args;
425 PyObject *keyw;
426 PyThreadState *tstate;
Guido van Rossuma027efa1997-05-05 20:56:21 +0000427};
428
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000429static void
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +0000430t_bootstrap(void *boot_raw)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000431{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000432 struct bootstate *boot = (struct bootstate *) boot_raw;
433 PyThreadState *tstate;
434 PyObject *res;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000435
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000436 tstate = boot->tstate;
437 tstate->thread_id = PyThread_get_thread_ident();
438 _PyThreadState_Init(tstate);
439 PyEval_AcquireThread(tstate);
440 res = PyEval_CallObjectWithKeywords(
441 boot->func, boot->args, boot->keyw);
442 if (res == NULL) {
443 if (PyErr_ExceptionMatches(PyExc_SystemExit))
444 PyErr_Clear();
445 else {
446 PyObject *file;
447 PySys_WriteStderr(
448 "Unhandled exception in thread started by ");
449 file = PySys_GetObject("stderr");
450 if (file != NULL && file != Py_None)
451 PyFile_WriteObject(boot->func, file, 0);
452 else
453 PyObject_Print(boot->func, stderr, 0);
454 PySys_WriteStderr("\n");
455 PyErr_PrintEx(0);
456 }
457 }
458 else
459 Py_DECREF(res);
460 Py_DECREF(boot->func);
461 Py_DECREF(boot->args);
462 Py_XDECREF(boot->keyw);
463 PyMem_DEL(boot_raw);
464 PyThreadState_Clear(tstate);
465 PyThreadState_DeleteCurrent();
466 PyThread_exit_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000467}
468
Barry Warsawd0c10421996-12-17 00:05:22 +0000469static PyObject *
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +0000470thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000471{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000472 PyObject *func, *args, *keyw = NULL;
473 struct bootstate *boot;
474 long ident;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000475
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000476 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
477 &func, &args, &keyw))
478 return NULL;
479 if (!PyCallable_Check(func)) {
480 PyErr_SetString(PyExc_TypeError,
481 "first arg must be callable");
482 return NULL;
483 }
484 if (!PyTuple_Check(args)) {
485 PyErr_SetString(PyExc_TypeError,
486 "2nd arg must be a tuple");
487 return NULL;
488 }
489 if (keyw != NULL && !PyDict_Check(keyw)) {
490 PyErr_SetString(PyExc_TypeError,
491 "optional 3rd arg must be a dictionary");
492 return NULL;
493 }
494 boot = PyMem_NEW(struct bootstate, 1);
495 if (boot == NULL)
496 return PyErr_NoMemory();
497 boot->interp = PyThreadState_GET()->interp;
498 boot->func = func;
499 boot->args = args;
500 boot->keyw = keyw;
501 boot->tstate = _PyThreadState_Prealloc(boot->interp);
502 if (boot->tstate == NULL) {
503 PyMem_DEL(boot);
504 return PyErr_NoMemory();
505 }
506 Py_INCREF(func);
507 Py_INCREF(args);
508 Py_XINCREF(keyw);
509 PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
510 ident = PyThread_start_new_thread(t_bootstrap, (void*) boot);
511 if (ident == -1) {
512 PyErr_SetString(ThreadError, "can't start new thread");
513 Py_DECREF(func);
514 Py_DECREF(args);
515 Py_XDECREF(keyw);
516 PyThreadState_Clear(boot->tstate);
517 PyMem_DEL(boot);
518 return NULL;
519 }
520 return PyLong_FromLong(ident);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000521}
522
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000523PyDoc_STRVAR(start_new_doc,
Andrew M. Kuchling38300c62001-10-05 12:24:15 +0000524"start_new_thread(function, args[, kwargs])\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000525(start_new() is an obsolete synonym)\n\
526\n\
Guido van Rossum3c288632001-10-16 21:13:49 +0000527Start a new thread and return its identifier. The thread will call the\n\
528function with positional arguments from the tuple args and keyword arguments\n\
529taken from the optional dictionary kwargs. The thread exits when the\n\
530function returns; the return value is ignored. The thread will also exit\n\
531when the function raises an unhandled exception; a stack trace will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000532printed unless the exception is SystemExit.\n");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000533
Barry Warsawd0c10421996-12-17 00:05:22 +0000534static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000535thread_PyThread_exit_thread(PyObject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000536{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000537 PyErr_SetNone(PyExc_SystemExit);
538 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000539}
540
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000541PyDoc_STRVAR(exit_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000542"exit()\n\
Guido van Rossum65d5b571998-12-21 19:32:43 +0000543(PyThread_exit_thread() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000544\n\
545This is synonymous to ``raise SystemExit''. It will cause the current\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000546thread to exit silently unless the exception is caught.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000547
Kurt B. Kaisera11e8462003-06-13 21:59:45 +0000548static PyObject *
Kurt B. Kaisera1ad5f62003-06-16 18:51:28 +0000549thread_PyThread_interrupt_main(PyObject * self)
Kurt B. Kaisera11e8462003-06-13 21:59:45 +0000550{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000551 PyErr_SetInterrupt();
552 Py_INCREF(Py_None);
553 return Py_None;
Kurt B. Kaisera11e8462003-06-13 21:59:45 +0000554}
555
556PyDoc_STRVAR(interrupt_doc,
557"interrupt_main()\n\
558\n\
559Raise a KeyboardInterrupt in the main thread.\n\
Kurt B. Kaisera1ad5f62003-06-16 18:51:28 +0000560A subthread can use this function to interrupt the main thread."
Kurt B. Kaisera11e8462003-06-13 21:59:45 +0000561);
562
Guido van Rossumb6775db1994-08-01 11:34:53 +0000563#ifndef NO_EXIT_PROG
Barry Warsawd0c10421996-12-17 00:05:22 +0000564static PyObject *
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +0000565thread_PyThread_exit_prog(PyObject *self, PyObject *args)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000566{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000567 int sts;
568 if (!PyArg_ParseTuple(args, "i:exit_prog", &sts))
569 return NULL;
570 Py_Exit(sts); /* Calls PyThread_exit_prog(sts) or _PyThread_exit_prog(sts) */
571 for (;;) { } /* Should not be reached */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000572}
Guido van Rossumb6775db1994-08-01 11:34:53 +0000573#endif
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000574
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000575static lockobject *newlockobject(void);
576
Barry Warsawd0c10421996-12-17 00:05:22 +0000577static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000578thread_PyThread_allocate_lock(PyObject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000579{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000580 return (PyObject *) newlockobject();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000581}
582
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000583PyDoc_STRVAR(allocate_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000584"allocate_lock() -> lock object\n\
585(allocate() is an obsolete synonym)\n\
586\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000587Create a new lock object. See LockType.__doc__ for information about locks.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000588
Barry Warsawd0c10421996-12-17 00:05:22 +0000589static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000590thread_get_ident(PyObject *self)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000591{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000592 long ident;
593 ident = PyThread_get_thread_ident();
594 if (ident == -1) {
595 PyErr_SetString(ThreadError, "no current thread ident");
596 return NULL;
597 }
598 return PyLong_FromLong(ident);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000599}
600
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000601PyDoc_STRVAR(get_ident_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000602"get_ident() -> integer\n\
603\n\
604Return a non-zero integer that uniquely identifies the current thread\n\
605amongst other threads that exist simultaneously.\n\
606This may be used to identify per-thread resources.\n\
607Even though on some platforms threads identities may appear to be\n\
608allocated consecutive numbers starting at 1, this behavior should not\n\
609be relied upon, and the number should be seen purely as a magic cookie.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000610A thread's identity may be reused for another thread after it exits.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000611
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000612static PyObject *
613thread_stack_size(PyObject *self, PyObject *args)
614{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000615 size_t old_size;
616 Py_ssize_t new_size = 0;
617 int rc;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000618
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000619 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
620 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000621
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000622 if (new_size < 0) {
623 PyErr_SetString(PyExc_ValueError,
624 "size must be 0 or a positive value");
625 return NULL;
626 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000627
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000628 old_size = PyThread_get_stacksize();
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000629
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000630 rc = PyThread_set_stacksize((size_t) new_size);
631 if (rc == -1) {
632 PyErr_Format(PyExc_ValueError,
633 "size not valid: %zd bytes",
634 new_size);
635 return NULL;
636 }
637 if (rc == -2) {
638 PyErr_SetString(ThreadError,
639 "setting stack size not supported");
640 return NULL;
641 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000642
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000643 return PyLong_FromSsize_t((Py_ssize_t) old_size);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000644}
645
646PyDoc_STRVAR(stack_size_doc,
647"stack_size([size]) -> size\n\
648\n\
649Return the thread stack size used when creating new threads. The\n\
650optional size argument specifies the stack size (in bytes) to be used\n\
651for subsequently created threads, and must be 0 (use platform or\n\
652configured default) or a positive integer value of at least 32,768 (32k).\n\
653If changing the thread stack size is unsupported, a ThreadError\n\
654exception is raised. If the specified size is invalid, a ValueError\n\
655exception is raised, and the stack size is unmodified. 32k bytes\n\
656 currently the minimum supported stack size value to guarantee\n\
657sufficient stack space for the interpreter itself.\n\
658\n\
659Note that some platforms may have particular restrictions on values for\n\
660the stack size, such as requiring a minimum stack size larger than 32kB or\n\
661requiring allocation in multiples of the system memory page size\n\
662- platform documentation should be referred to for more information\n\
663(4kB pages are common; using multiples of 4096 for the stack size is\n\
664the suggested approach in the absence of more specific information).");
665
Barry Warsawd0c10421996-12-17 00:05:22 +0000666static PyMethodDef thread_methods[] = {
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000667 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
668 METH_VARARGS,
669 start_new_doc},
670 {"start_new", (PyCFunction)thread_PyThread_start_new_thread,
671 METH_VARARGS,
672 start_new_doc},
673 {"allocate_lock", (PyCFunction)thread_PyThread_allocate_lock,
674 METH_NOARGS, allocate_doc},
675 {"allocate", (PyCFunction)thread_PyThread_allocate_lock,
676 METH_NOARGS, allocate_doc},
677 {"exit_thread", (PyCFunction)thread_PyThread_exit_thread,
678 METH_NOARGS, exit_doc},
679 {"exit", (PyCFunction)thread_PyThread_exit_thread,
680 METH_NOARGS, exit_doc},
681 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main,
682 METH_NOARGS, interrupt_doc},
683 {"get_ident", (PyCFunction)thread_get_ident,
684 METH_NOARGS, get_ident_doc},
685 {"stack_size", (PyCFunction)thread_stack_size,
686 METH_VARARGS,
687 stack_size_doc},
Guido van Rossumb6775db1994-08-01 11:34:53 +0000688#ifndef NO_EXIT_PROG
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000689 {"exit_prog", (PyCFunction)thread_PyThread_exit_prog,
690 METH_VARARGS},
Guido van Rossumb6775db1994-08-01 11:34:53 +0000691#endif
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000692 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000693};
694
695
696/* Initialization function */
697
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000698PyDoc_STRVAR(thread_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000699"This module provides primitive operations to write multi-threaded programs.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000700The 'threading' module provides a more convenient interface.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000701
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000702PyDoc_STRVAR(lock_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000703"A lock object is a synchronization primitive. To create a lock,\n\
Guido van Rossum65d5b571998-12-21 19:32:43 +0000704call the PyThread_allocate_lock() function. Methods are:\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000705\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000706acquire() -- lock the lock, possibly blocking until it can be obtained\n\
707release() -- unlock of the lock\n\
708locked() -- test whether the lock is currently locked\n\
709\n\
710A lock is not owned by the thread that locked it; another thread may\n\
711unlock it. A thread attempting to lock a lock that it has already locked\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000712will block until another thread unlocks it. Deadlocks may ensue.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000713
Martin v. Löwis1a214512008-06-11 05:26:20 +0000714static struct PyModuleDef threadmodule = {
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000715 PyModuleDef_HEAD_INIT,
716 "_thread",
717 thread_doc,
718 -1,
719 thread_methods,
720 NULL,
721 NULL,
722 NULL,
723 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000724};
725
726
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000727PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000728PyInit__thread(void)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000729{
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000730 PyObject *m, *d;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000731
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000732 /* Initialize types: */
733 if (PyType_Ready(&localtype) < 0)
734 return NULL;
735 if (PyType_Ready(&Locktype) < 0)
736 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000737
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000738 /* Create the module and add the functions */
739 m = PyModule_Create(&threadmodule);
740 if (m == NULL)
741 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000742
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000743 /* Add a symbolic constant */
744 d = PyModule_GetDict(m);
745 ThreadError = PyErr_NewException("_thread.error", NULL, NULL);
746 PyDict_SetItemString(d, "error", ThreadError);
747 Locktype.tp_doc = lock_doc;
748 Py_INCREF(&Locktype);
749 PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype);
Jim Fultond15dc062004-07-14 19:11:50 +0000750
Antoine Pitrou7f14f0d2010-05-09 16:14:21 +0000751 Py_INCREF(&localtype);
752 if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0)
753 return NULL;
754
755 /* Initialize the C thread library */
756 PyThread_init_thread();
757 return m;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000758}