blob: 99ca4afc911882ace387f62e35b55ccc1abb56b2 [file] [log] [blame]
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001/***********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossum1984f1e1992-08-04 12:41:02 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossum1984f1e1992-08-04 12:41:02 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossum1984f1e1992-08-04 12:41:02 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossum1984f1e1992-08-04 12:41:02 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossum1984f1e1992-08-04 12:41:02 +000029
30******************************************************************/
31
32/* Thread module */
33/* Interface to Sjoerd's portable C thread library */
34
Barry Warsawd0c10421996-12-17 00:05:22 +000035#include "Python.h"
Guido van Rossum1984f1e1992-08-04 12:41:02 +000036
Guido van Rossumb6775db1994-08-01 11:34:53 +000037#ifndef WITH_THREAD
Guido van Rossuma027efa1997-05-05 20:56:21 +000038#error "Error! The rest of Python is not compiled with thread support."
39#error "Rerun configure, adding a --with-thread option."
40#error "Then run `make clean' followed by `make'."
Guido van Rossumb6775db1994-08-01 11:34:53 +000041#endif
42
Guido van Rossum1984f1e1992-08-04 12:41:02 +000043#include "thread.h"
44
Barry Warsawd0c10421996-12-17 00:05:22 +000045static PyObject *ThreadError;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000046
47
48/* Lock objects */
49
50typedef struct {
Barry Warsawd0c10421996-12-17 00:05:22 +000051 PyObject_HEAD
Guido van Rossum1984f1e1992-08-04 12:41:02 +000052 type_lock lock_lock;
53} lockobject;
54
Barry Warsawd0c10421996-12-17 00:05:22 +000055staticforward PyTypeObject Locktype;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000056
57#define is_lockobject(v) ((v)->ob_type == &Locktype)
58
Sjoerd Mullendered59d201993-01-06 13:36:38 +000059type_lock
60getlocklock(lock)
Barry Warsawd0c10421996-12-17 00:05:22 +000061 PyObject *lock;
Sjoerd Mullendered59d201993-01-06 13:36:38 +000062{
63 if (lock == NULL || !is_lockobject(lock))
64 return NULL;
65 else
66 return ((lockobject *) lock)->lock_lock;
67}
68
Guido van Rossum1984f1e1992-08-04 12:41:02 +000069static lockobject *
70newlockobject()
71{
72 lockobject *self;
Barry Warsawd0c10421996-12-17 00:05:22 +000073 self = PyObject_NEW(lockobject, &Locktype);
Guido van Rossum1984f1e1992-08-04 12:41:02 +000074 if (self == NULL)
75 return NULL;
76 self->lock_lock = allocate_lock();
77 if (self->lock_lock == NULL) {
Barry Warsawd0c10421996-12-17 00:05:22 +000078 PyMem_DEL(self);
Guido van Rossum1984f1e1992-08-04 12:41:02 +000079 self = NULL;
Barry Warsawd0c10421996-12-17 00:05:22 +000080 PyErr_SetString(ThreadError, "can't allocate lock");
Guido van Rossum1984f1e1992-08-04 12:41:02 +000081 }
82 return self;
83}
84
85static void
86lock_dealloc(self)
87 lockobject *self;
88{
89 /* Unlock the lock so it's safe to free it */
90 acquire_lock(self->lock_lock, 0);
91 release_lock(self->lock_lock);
92
93 free_lock(self->lock_lock);
Barry Warsawd0c10421996-12-17 00:05:22 +000094 PyMem_DEL(self);
Guido van Rossum1984f1e1992-08-04 12:41:02 +000095}
96
Barry Warsawd0c10421996-12-17 00:05:22 +000097static PyObject *
Guido van Rossum1984f1e1992-08-04 12:41:02 +000098lock_acquire_lock(self, args)
99 lockobject *self;
Barry Warsawd0c10421996-12-17 00:05:22 +0000100 PyObject *args;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000101{
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000102 int i;
103
104 if (args != NULL) {
Barry Warsawd0c10421996-12-17 00:05:22 +0000105 if (!PyArg_Parse(args, "i", &i))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000106 return NULL;
107 }
108 else
109 i = 1;
110
Barry Warsawd0c10421996-12-17 00:05:22 +0000111 Py_BEGIN_ALLOW_THREADS
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000112 i = acquire_lock(self->lock_lock, i);
Barry Warsawd0c10421996-12-17 00:05:22 +0000113 Py_END_ALLOW_THREADS
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000114
115 if (args == NULL) {
Barry Warsawd0c10421996-12-17 00:05:22 +0000116 Py_INCREF(Py_None);
117 return Py_None;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000118 }
119 else
Barry Warsawd0c10421996-12-17 00:05:22 +0000120 return PyInt_FromLong((long)i);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000121}
122
Barry Warsawd0c10421996-12-17 00:05:22 +0000123static PyObject *
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000124lock_release_lock(self, args)
125 lockobject *self;
Barry Warsawd0c10421996-12-17 00:05:22 +0000126 PyObject *args;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000127{
Barry Warsawd0c10421996-12-17 00:05:22 +0000128 if (!PyArg_NoArgs(args))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000129 return NULL;
130
131 /* Sanity check: the lock must be locked */
132 if (acquire_lock(self->lock_lock, 0)) {
133 release_lock(self->lock_lock);
Barry Warsawd0c10421996-12-17 00:05:22 +0000134 PyErr_SetString(ThreadError, "release unlocked lock");
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000135 return NULL;
136 }
137
138 release_lock(self->lock_lock);
Barry Warsawd0c10421996-12-17 00:05:22 +0000139 Py_INCREF(Py_None);
140 return Py_None;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000141}
142
Barry Warsawd0c10421996-12-17 00:05:22 +0000143static PyObject *
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000144lock_locked_lock(self, args)
145 lockobject *self;
Barry Warsawd0c10421996-12-17 00:05:22 +0000146 PyObject *args;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000147{
Barry Warsawd0c10421996-12-17 00:05:22 +0000148 if (!PyArg_NoArgs(args))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000149 return NULL;
150
151 if (acquire_lock(self->lock_lock, 0)) {
152 release_lock(self->lock_lock);
Barry Warsawd0c10421996-12-17 00:05:22 +0000153 return PyInt_FromLong(0L);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000154 }
Barry Warsawd0c10421996-12-17 00:05:22 +0000155 return PyInt_FromLong(1L);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000156}
157
Barry Warsawd0c10421996-12-17 00:05:22 +0000158static PyMethodDef lock_methods[] = {
159 {"acquire_lock", (PyCFunction)lock_acquire_lock},
160 {"acquire", (PyCFunction)lock_acquire_lock},
161 {"release_lock", (PyCFunction)lock_release_lock},
162 {"release", (PyCFunction)lock_release_lock},
163 {"locked_lock", (PyCFunction)lock_locked_lock},
164 {"locked", (PyCFunction)lock_locked_lock},
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000165 {NULL, NULL} /* sentinel */
166};
167
Barry Warsawd0c10421996-12-17 00:05:22 +0000168static PyObject *
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000169lock_getattr(self, name)
170 lockobject *self;
171 char *name;
172{
Barry Warsawd0c10421996-12-17 00:05:22 +0000173 return Py_FindMethod(lock_methods, (PyObject *)self, name);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000174}
175
Barry Warsawd0c10421996-12-17 00:05:22 +0000176static PyTypeObject Locktype = {
177 PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000178 0, /*ob_size*/
179 "lock", /*tp_name*/
180 sizeof(lockobject), /*tp_size*/
181 0, /*tp_itemsize*/
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000182 /* methods */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000183 (destructor)lock_dealloc, /*tp_dealloc*/
184 0, /*tp_print*/
185 (getattrfunc)lock_getattr, /*tp_getattr*/
186 0, /*tp_setattr*/
187 0, /*tp_compare*/
188 0, /*tp_repr*/
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000189};
190
191
192/* Module functions */
193
Guido van Rossuma027efa1997-05-05 20:56:21 +0000194struct bootstate {
195 PyInterpreterState *interp;
196 PyObject *func;
197 PyObject *args;
198 PyObject *keyw;
199};
200
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000201static void
Guido van Rossuma027efa1997-05-05 20:56:21 +0000202t_bootstrap(boot_raw)
203 void *boot_raw;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000204{
Guido van Rossuma027efa1997-05-05 20:56:21 +0000205 struct bootstate *boot = (struct bootstate *) boot_raw;
206 PyThreadState *alttstate, *tstate;
207 PyObject *res;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000208
Guido van Rossuma027efa1997-05-05 20:56:21 +0000209 tstate = PyThreadState_New(boot->interp);
Barry Warsawd0c10421996-12-17 00:05:22 +0000210 PyEval_RestoreThread((void *)NULL);
Guido van Rossuma027efa1997-05-05 20:56:21 +0000211 alttstate = PyThreadState_Swap(tstate);
212 res = PyEval_CallObjectWithKeywords(
213 boot->func, boot->args, boot->keyw);
214 Py_DECREF(boot->func);
215 Py_DECREF(boot->args);
216 Py_XDECREF(boot->keyw);
217 PyMem_DEL(boot_raw);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000218 if (res == NULL) {
Barry Warsawd0c10421996-12-17 00:05:22 +0000219 if (PyErr_Occurred() == PyExc_SystemExit)
220 PyErr_Clear();
Guido van Rossum385e7c61995-03-17 10:42:27 +0000221 else {
222 fprintf(stderr, "Unhandled exception in thread:\n");
Guido van Rossuma027efa1997-05-05 20:56:21 +0000223 PyErr_Print();
Guido van Rossum385e7c61995-03-17 10:42:27 +0000224 }
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000225 }
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000226 else
Barry Warsawd0c10421996-12-17 00:05:22 +0000227 Py_DECREF(res);
Guido van Rossuma027efa1997-05-05 20:56:21 +0000228 (void) PyThreadState_Swap(alttstate);
229 (void) PyEval_SaveThread();
230 PyThreadState_Delete(tstate);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000231 exit_thread();
232}
233
Barry Warsawd0c10421996-12-17 00:05:22 +0000234static PyObject *
Guido van Rossuma027efa1997-05-05 20:56:21 +0000235thread_start_new_thread(self, fargs)
Barry Warsawd0c10421996-12-17 00:05:22 +0000236 PyObject *self; /* Not used */
Guido van Rossuma027efa1997-05-05 20:56:21 +0000237 PyObject *fargs;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000238{
Guido van Rossuma027efa1997-05-05 20:56:21 +0000239 PyObject *func, *args = NULL, *keyw = NULL;
240 struct bootstate *boot;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000241
Guido van Rossuma027efa1997-05-05 20:56:21 +0000242 if (!PyArg_ParseTuple(fargs, "OO|O", &func, &args, &keyw))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000243 return NULL;
Guido van Rossuma027efa1997-05-05 20:56:21 +0000244 if (!PyCallable_Check(func)) {
245 PyErr_SetString(PyExc_TypeError,
246 "first arg must be callable");
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000247 return NULL;
248 }
Guido van Rossuma027efa1997-05-05 20:56:21 +0000249 if (!PyTuple_Check(args)) {
250 PyErr_SetString(PyExc_TypeError,
251 "optional 2nd arg must be a tuple");
252 return NULL;
253 }
254 if (keyw != NULL && !PyDict_Check(keyw)) {
255 PyErr_SetString(PyExc_TypeError,
256 "optional 3rd arg must be a dictionary");
257 return NULL;
258 }
259 boot = PyMem_NEW(struct bootstate, 1);
260 if (boot == NULL)
261 return PyErr_NoMemory();
262 boot->interp = PyThreadState_Get()->interpreter_state;
263 boot->func = func;
264 boot->args = args;
265 boot->keyw = keyw;
266 Py_INCREF(func);
267 Py_INCREF(args);
268 Py_XINCREF(keyw);
269 PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
270 if (!start_new_thread(t_bootstrap, (void*) boot)) {
271 PyErr_SetString(ThreadError, "can't start new thread\n");
272 Py_DECREF(func);
273 Py_DECREF(args);
274 Py_XDECREF(keyw);
275 PyMem_DEL(boot);
276 return NULL;
277 }
Barry Warsawd0c10421996-12-17 00:05:22 +0000278 Py_INCREF(Py_None);
279 return Py_None;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000280}
281
Barry Warsawd0c10421996-12-17 00:05:22 +0000282static PyObject *
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000283thread_exit_thread(self, args)
Barry Warsawd0c10421996-12-17 00:05:22 +0000284 PyObject *self; /* Not used */
285 PyObject *args;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000286{
Barry Warsawd0c10421996-12-17 00:05:22 +0000287 if (!PyArg_NoArgs(args))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000288 return NULL;
Barry Warsawd0c10421996-12-17 00:05:22 +0000289 PyErr_SetNone(PyExc_SystemExit);
Guido van Rossum385e7c61995-03-17 10:42:27 +0000290 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000291}
292
Guido van Rossumb6775db1994-08-01 11:34:53 +0000293#ifndef NO_EXIT_PROG
Barry Warsawd0c10421996-12-17 00:05:22 +0000294static PyObject *
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000295thread_exit_prog(self, args)
Barry Warsawd0c10421996-12-17 00:05:22 +0000296 PyObject *self; /* Not used */
297 PyObject *args;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000298{
299 int sts;
Barry Warsawd0c10421996-12-17 00:05:22 +0000300 if (!PyArg_Parse(args, "i", &sts))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000301 return NULL;
Barry Warsawd0c10421996-12-17 00:05:22 +0000302 Py_Exit(sts); /* Calls exit_prog(sts) or _exit_prog(sts) */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000303 for (;;) { } /* Should not be reached */
304}
Guido van Rossumb6775db1994-08-01 11:34:53 +0000305#endif
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000306
Barry Warsawd0c10421996-12-17 00:05:22 +0000307static PyObject *
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000308thread_allocate_lock(self, args)
Barry Warsawd0c10421996-12-17 00:05:22 +0000309 PyObject *self; /* Not used */
310 PyObject *args;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000311{
Barry Warsawd0c10421996-12-17 00:05:22 +0000312 if (!PyArg_NoArgs(args))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000313 return NULL;
Barry Warsawd0c10421996-12-17 00:05:22 +0000314 return (PyObject *) newlockobject();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000315}
316
Barry Warsawd0c10421996-12-17 00:05:22 +0000317static PyObject *
Guido van Rossumb6775db1994-08-01 11:34:53 +0000318thread_get_ident(self, args)
Barry Warsawd0c10421996-12-17 00:05:22 +0000319 PyObject *self; /* Not used */
320 PyObject *args;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000321{
322 long ident;
Barry Warsawd0c10421996-12-17 00:05:22 +0000323 if (!PyArg_NoArgs(args))
Guido van Rossumb6775db1994-08-01 11:34:53 +0000324 return NULL;
325 ident = get_thread_ident();
326 if (ident == -1) {
Barry Warsawd0c10421996-12-17 00:05:22 +0000327 PyErr_SetString(ThreadError, "no current thread ident");
Guido van Rossumb6775db1994-08-01 11:34:53 +0000328 return NULL;
329 }
Barry Warsawd0c10421996-12-17 00:05:22 +0000330 return PyInt_FromLong(ident);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000331}
332
Barry Warsawd0c10421996-12-17 00:05:22 +0000333static PyMethodDef thread_methods[] = {
Guido van Rossuma027efa1997-05-05 20:56:21 +0000334 {"start_new_thread", (PyCFunction)thread_start_new_thread, 1},
335 {"start_new", (PyCFunction)thread_start_new_thread, 1},
Barry Warsawd0c10421996-12-17 00:05:22 +0000336 {"allocate_lock", (PyCFunction)thread_allocate_lock},
337 {"allocate", (PyCFunction)thread_allocate_lock},
338 {"exit_thread", (PyCFunction)thread_exit_thread},
339 {"exit", (PyCFunction)thread_exit_thread},
340 {"get_ident", (PyCFunction)thread_get_ident},
Guido van Rossumb6775db1994-08-01 11:34:53 +0000341#ifndef NO_EXIT_PROG
Barry Warsawd0c10421996-12-17 00:05:22 +0000342 {"exit_prog", (PyCFunction)thread_exit_prog},
Guido van Rossumb6775db1994-08-01 11:34:53 +0000343#endif
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000344 {NULL, NULL} /* sentinel */
345};
346
347
348/* Initialization function */
349
350void
351initthread()
352{
Barry Warsawd0c10421996-12-17 00:05:22 +0000353 PyObject *m, *d;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000354
355 /* Create the module and add the functions */
Barry Warsawd0c10421996-12-17 00:05:22 +0000356 m = Py_InitModule("thread", thread_methods);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000357
358 /* Add a symbolic constant */
Barry Warsawd0c10421996-12-17 00:05:22 +0000359 d = PyModule_GetDict(m);
360 ThreadError = PyString_FromString("thread.error");
Barry Warsawd0c10421996-12-17 00:05:22 +0000361 PyDict_SetItemString(d, "error", ThreadError);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000362
363 /* Check for errors */
Barry Warsawd0c10421996-12-17 00:05:22 +0000364 if (PyErr_Occurred())
365 Py_FatalError("can't initialize module thread");
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000366
367 /* Initialize the C thread library */
368 init_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000369}