blob: 51c24d13f5168e0ffada5eeeb700cd87ec984d08 [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 Rossum40769dd1998-02-06 22:32:08 +0000222 PyErr_PrintEx(0);
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 Rossumb02158e1997-08-02 03:13:11 +0000227 PyThreadState_Clear(tstate);
Guido van Rossum75aa0d61997-07-18 23:57:50 +0000228 PyEval_ReleaseThread(tstate);
Guido van Rossuma027efa1997-05-05 20:56:21 +0000229 PyThreadState_Delete(tstate);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000230 exit_thread();
231}
232
Barry Warsawd0c10421996-12-17 00:05:22 +0000233static PyObject *
Guido van Rossuma027efa1997-05-05 20:56:21 +0000234thread_start_new_thread(self, fargs)
Barry Warsawd0c10421996-12-17 00:05:22 +0000235 PyObject *self; /* Not used */
Guido van Rossuma027efa1997-05-05 20:56:21 +0000236 PyObject *fargs;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000237{
Guido van Rossuma027efa1997-05-05 20:56:21 +0000238 PyObject *func, *args = NULL, *keyw = NULL;
239 struct bootstate *boot;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000240
Guido van Rossuma027efa1997-05-05 20:56:21 +0000241 if (!PyArg_ParseTuple(fargs, "OO|O", &func, &args, &keyw))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000242 return NULL;
Guido van Rossuma027efa1997-05-05 20:56:21 +0000243 if (!PyCallable_Check(func)) {
244 PyErr_SetString(PyExc_TypeError,
245 "first arg must be callable");
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000246 return NULL;
247 }
Guido van Rossuma027efa1997-05-05 20:56:21 +0000248 if (!PyTuple_Check(args)) {
249 PyErr_SetString(PyExc_TypeError,
250 "optional 2nd arg must be a tuple");
251 return NULL;
252 }
253 if (keyw != NULL && !PyDict_Check(keyw)) {
254 PyErr_SetString(PyExc_TypeError,
255 "optional 3rd arg must be a dictionary");
256 return NULL;
257 }
258 boot = PyMem_NEW(struct bootstate, 1);
259 if (boot == NULL)
260 return PyErr_NoMemory();
Guido van Rossumb02158e1997-08-02 03:13:11 +0000261 boot->interp = PyThreadState_Get()->interp;
Guido van Rossuma027efa1997-05-05 20:56:21 +0000262 boot->func = func;
263 boot->args = args;
264 boot->keyw = keyw;
265 Py_INCREF(func);
266 Py_INCREF(args);
267 Py_XINCREF(keyw);
268 PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
269 if (!start_new_thread(t_bootstrap, (void*) boot)) {
270 PyErr_SetString(ThreadError, "can't start new thread\n");
271 Py_DECREF(func);
272 Py_DECREF(args);
273 Py_XDECREF(keyw);
274 PyMem_DEL(boot);
275 return NULL;
276 }
Barry Warsawd0c10421996-12-17 00:05:22 +0000277 Py_INCREF(Py_None);
278 return Py_None;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000279}
280
Barry Warsawd0c10421996-12-17 00:05:22 +0000281static PyObject *
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000282thread_exit_thread(self, args)
Barry Warsawd0c10421996-12-17 00:05:22 +0000283 PyObject *self; /* Not used */
284 PyObject *args;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000285{
Barry Warsawd0c10421996-12-17 00:05:22 +0000286 if (!PyArg_NoArgs(args))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000287 return NULL;
Barry Warsawd0c10421996-12-17 00:05:22 +0000288 PyErr_SetNone(PyExc_SystemExit);
Guido van Rossum385e7c61995-03-17 10:42:27 +0000289 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000290}
291
Guido van Rossumb6775db1994-08-01 11:34:53 +0000292#ifndef NO_EXIT_PROG
Barry Warsawd0c10421996-12-17 00:05:22 +0000293static PyObject *
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000294thread_exit_prog(self, args)
Barry Warsawd0c10421996-12-17 00:05:22 +0000295 PyObject *self; /* Not used */
296 PyObject *args;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000297{
298 int sts;
Barry Warsawd0c10421996-12-17 00:05:22 +0000299 if (!PyArg_Parse(args, "i", &sts))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000300 return NULL;
Barry Warsawd0c10421996-12-17 00:05:22 +0000301 Py_Exit(sts); /* Calls exit_prog(sts) or _exit_prog(sts) */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000302 for (;;) { } /* Should not be reached */
303}
Guido van Rossumb6775db1994-08-01 11:34:53 +0000304#endif
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000305
Barry Warsawd0c10421996-12-17 00:05:22 +0000306static PyObject *
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000307thread_allocate_lock(self, args)
Barry Warsawd0c10421996-12-17 00:05:22 +0000308 PyObject *self; /* Not used */
309 PyObject *args;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000310{
Barry Warsawd0c10421996-12-17 00:05:22 +0000311 if (!PyArg_NoArgs(args))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000312 return NULL;
Barry Warsawd0c10421996-12-17 00:05:22 +0000313 return (PyObject *) newlockobject();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000314}
315
Barry Warsawd0c10421996-12-17 00:05:22 +0000316static PyObject *
Guido van Rossumb6775db1994-08-01 11:34:53 +0000317thread_get_ident(self, args)
Barry Warsawd0c10421996-12-17 00:05:22 +0000318 PyObject *self; /* Not used */
319 PyObject *args;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000320{
321 long ident;
Barry Warsawd0c10421996-12-17 00:05:22 +0000322 if (!PyArg_NoArgs(args))
Guido van Rossumb6775db1994-08-01 11:34:53 +0000323 return NULL;
324 ident = get_thread_ident();
325 if (ident == -1) {
Barry Warsawd0c10421996-12-17 00:05:22 +0000326 PyErr_SetString(ThreadError, "no current thread ident");
Guido van Rossumb6775db1994-08-01 11:34:53 +0000327 return NULL;
328 }
Barry Warsawd0c10421996-12-17 00:05:22 +0000329 return PyInt_FromLong(ident);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000330}
331
Barry Warsawd0c10421996-12-17 00:05:22 +0000332static PyMethodDef thread_methods[] = {
Guido van Rossuma027efa1997-05-05 20:56:21 +0000333 {"start_new_thread", (PyCFunction)thread_start_new_thread, 1},
334 {"start_new", (PyCFunction)thread_start_new_thread, 1},
Barry Warsawd0c10421996-12-17 00:05:22 +0000335 {"allocate_lock", (PyCFunction)thread_allocate_lock},
336 {"allocate", (PyCFunction)thread_allocate_lock},
337 {"exit_thread", (PyCFunction)thread_exit_thread},
338 {"exit", (PyCFunction)thread_exit_thread},
339 {"get_ident", (PyCFunction)thread_get_ident},
Guido van Rossumb6775db1994-08-01 11:34:53 +0000340#ifndef NO_EXIT_PROG
Barry Warsawd0c10421996-12-17 00:05:22 +0000341 {"exit_prog", (PyCFunction)thread_exit_prog},
Guido van Rossumb6775db1994-08-01 11:34:53 +0000342#endif
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000343 {NULL, NULL} /* sentinel */
344};
345
346
347/* Initialization function */
348
349void
350initthread()
351{
Barry Warsawd0c10421996-12-17 00:05:22 +0000352 PyObject *m, *d;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000353
354 /* Create the module and add the functions */
Barry Warsawd0c10421996-12-17 00:05:22 +0000355 m = Py_InitModule("thread", thread_methods);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000356
357 /* Add a symbolic constant */
Barry Warsawd0c10421996-12-17 00:05:22 +0000358 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000359 ThreadError = PyErr_NewException("thread.error", NULL, NULL);
Barry Warsawd0c10421996-12-17 00:05:22 +0000360 PyDict_SetItemString(d, "error", ThreadError);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000361
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000362 /* Initialize the C thread library */
363 init_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000364}