blob: 22017992a546be802a4bde347456dd17dc7abf65 [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;
Guido van Rossum75aa0d61997-07-18 23:57:50 +0000206 PyThreadState *tstate;
Guido van Rossuma027efa1997-05-05 20:56:21 +0000207 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);
Guido van Rossum75aa0d61997-07-18 23:57:50 +0000210 PyEval_AcquireThread(tstate);
Guido van Rossuma027efa1997-05-05 20:56:21 +0000211 res = PyEval_CallObjectWithKeywords(
212 boot->func, boot->args, boot->keyw);
213 Py_DECREF(boot->func);
214 Py_DECREF(boot->args);
215 Py_XDECREF(boot->keyw);
216 PyMem_DEL(boot_raw);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000217 if (res == NULL) {
Barry Warsawd0c10421996-12-17 00:05:22 +0000218 if (PyErr_Occurred() == PyExc_SystemExit)
219 PyErr_Clear();
Guido van Rossum385e7c61995-03-17 10:42:27 +0000220 else {
221 fprintf(stderr, "Unhandled exception in thread:\n");
Guido van Rossuma027efa1997-05-05 20:56:21 +0000222 PyErr_Print();
Guido van Rossum385e7c61995-03-17 10:42:27 +0000223 }
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000224 }
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000225 else
Barry Warsawd0c10421996-12-17 00:05:22 +0000226 Py_DECREF(res);
Guido van Rossum75aa0d61997-07-18 23:57:50 +0000227 PyEval_ReleaseThread(tstate);
Guido van Rossuma027efa1997-05-05 20:56:21 +0000228 PyThreadState_Delete(tstate);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000229 exit_thread();
230}
231
Barry Warsawd0c10421996-12-17 00:05:22 +0000232static PyObject *
Guido van Rossuma027efa1997-05-05 20:56:21 +0000233thread_start_new_thread(self, fargs)
Barry Warsawd0c10421996-12-17 00:05:22 +0000234 PyObject *self; /* Not used */
Guido van Rossuma027efa1997-05-05 20:56:21 +0000235 PyObject *fargs;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000236{
Guido van Rossuma027efa1997-05-05 20:56:21 +0000237 PyObject *func, *args = NULL, *keyw = NULL;
238 struct bootstate *boot;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000239
Guido van Rossuma027efa1997-05-05 20:56:21 +0000240 if (!PyArg_ParseTuple(fargs, "OO|O", &func, &args, &keyw))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000241 return NULL;
Guido van Rossuma027efa1997-05-05 20:56:21 +0000242 if (!PyCallable_Check(func)) {
243 PyErr_SetString(PyExc_TypeError,
244 "first arg must be callable");
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000245 return NULL;
246 }
Guido van Rossuma027efa1997-05-05 20:56:21 +0000247 if (!PyTuple_Check(args)) {
248 PyErr_SetString(PyExc_TypeError,
249 "optional 2nd arg must be a tuple");
250 return NULL;
251 }
252 if (keyw != NULL && !PyDict_Check(keyw)) {
253 PyErr_SetString(PyExc_TypeError,
254 "optional 3rd arg must be a dictionary");
255 return NULL;
256 }
257 boot = PyMem_NEW(struct bootstate, 1);
258 if (boot == NULL)
259 return PyErr_NoMemory();
260 boot->interp = PyThreadState_Get()->interpreter_state;
261 boot->func = func;
262 boot->args = args;
263 boot->keyw = keyw;
264 Py_INCREF(func);
265 Py_INCREF(args);
266 Py_XINCREF(keyw);
267 PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
268 if (!start_new_thread(t_bootstrap, (void*) boot)) {
269 PyErr_SetString(ThreadError, "can't start new thread\n");
270 Py_DECREF(func);
271 Py_DECREF(args);
272 Py_XDECREF(keyw);
273 PyMem_DEL(boot);
274 return NULL;
275 }
Barry Warsawd0c10421996-12-17 00:05:22 +0000276 Py_INCREF(Py_None);
277 return Py_None;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000278}
279
Barry Warsawd0c10421996-12-17 00:05:22 +0000280static PyObject *
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000281thread_exit_thread(self, args)
Barry Warsawd0c10421996-12-17 00:05:22 +0000282 PyObject *self; /* Not used */
283 PyObject *args;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000284{
Barry Warsawd0c10421996-12-17 00:05:22 +0000285 if (!PyArg_NoArgs(args))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000286 return NULL;
Barry Warsawd0c10421996-12-17 00:05:22 +0000287 PyErr_SetNone(PyExc_SystemExit);
Guido van Rossum385e7c61995-03-17 10:42:27 +0000288 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000289}
290
Guido van Rossumb6775db1994-08-01 11:34:53 +0000291#ifndef NO_EXIT_PROG
Barry Warsawd0c10421996-12-17 00:05:22 +0000292static PyObject *
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000293thread_exit_prog(self, args)
Barry Warsawd0c10421996-12-17 00:05:22 +0000294 PyObject *self; /* Not used */
295 PyObject *args;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000296{
297 int sts;
Barry Warsawd0c10421996-12-17 00:05:22 +0000298 if (!PyArg_Parse(args, "i", &sts))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000299 return NULL;
Barry Warsawd0c10421996-12-17 00:05:22 +0000300 Py_Exit(sts); /* Calls exit_prog(sts) or _exit_prog(sts) */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000301 for (;;) { } /* Should not be reached */
302}
Guido van Rossumb6775db1994-08-01 11:34:53 +0000303#endif
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000304
Barry Warsawd0c10421996-12-17 00:05:22 +0000305static PyObject *
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000306thread_allocate_lock(self, args)
Barry Warsawd0c10421996-12-17 00:05:22 +0000307 PyObject *self; /* Not used */
308 PyObject *args;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000309{
Barry Warsawd0c10421996-12-17 00:05:22 +0000310 if (!PyArg_NoArgs(args))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000311 return NULL;
Barry Warsawd0c10421996-12-17 00:05:22 +0000312 return (PyObject *) newlockobject();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000313}
314
Barry Warsawd0c10421996-12-17 00:05:22 +0000315static PyObject *
Guido van Rossumb6775db1994-08-01 11:34:53 +0000316thread_get_ident(self, args)
Barry Warsawd0c10421996-12-17 00:05:22 +0000317 PyObject *self; /* Not used */
318 PyObject *args;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000319{
320 long ident;
Barry Warsawd0c10421996-12-17 00:05:22 +0000321 if (!PyArg_NoArgs(args))
Guido van Rossumb6775db1994-08-01 11:34:53 +0000322 return NULL;
323 ident = get_thread_ident();
324 if (ident == -1) {
Barry Warsawd0c10421996-12-17 00:05:22 +0000325 PyErr_SetString(ThreadError, "no current thread ident");
Guido van Rossumb6775db1994-08-01 11:34:53 +0000326 return NULL;
327 }
Barry Warsawd0c10421996-12-17 00:05:22 +0000328 return PyInt_FromLong(ident);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000329}
330
Barry Warsawd0c10421996-12-17 00:05:22 +0000331static PyMethodDef thread_methods[] = {
Guido van Rossuma027efa1997-05-05 20:56:21 +0000332 {"start_new_thread", (PyCFunction)thread_start_new_thread, 1},
333 {"start_new", (PyCFunction)thread_start_new_thread, 1},
Barry Warsawd0c10421996-12-17 00:05:22 +0000334 {"allocate_lock", (PyCFunction)thread_allocate_lock},
335 {"allocate", (PyCFunction)thread_allocate_lock},
336 {"exit_thread", (PyCFunction)thread_exit_thread},
337 {"exit", (PyCFunction)thread_exit_thread},
338 {"get_ident", (PyCFunction)thread_get_ident},
Guido van Rossumb6775db1994-08-01 11:34:53 +0000339#ifndef NO_EXIT_PROG
Barry Warsawd0c10421996-12-17 00:05:22 +0000340 {"exit_prog", (PyCFunction)thread_exit_prog},
Guido van Rossumb6775db1994-08-01 11:34:53 +0000341#endif
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000342 {NULL, NULL} /* sentinel */
343};
344
345
346/* Initialization function */
347
348void
349initthread()
350{
Barry Warsawd0c10421996-12-17 00:05:22 +0000351 PyObject *m, *d;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000352
353 /* Create the module and add the functions */
Barry Warsawd0c10421996-12-17 00:05:22 +0000354 m = Py_InitModule("thread", thread_methods);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000355
356 /* Add a symbolic constant */
Barry Warsawd0c10421996-12-17 00:05:22 +0000357 d = PyModule_GetDict(m);
358 ThreadError = PyString_FromString("thread.error");
Barry Warsawd0c10421996-12-17 00:05:22 +0000359 PyDict_SetItemString(d, "error", ThreadError);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000360
361 /* Check for errors */
Barry Warsawd0c10421996-12-17 00:05:22 +0000362 if (PyErr_Occurred())
363 Py_FatalError("can't initialize module thread");
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000364
365 /* Initialize the C thread library */
366 init_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000367}