blob: 38394a4e74f0eefc68f80f5f0a399ca901996a6d [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
35#include "allobjects.h"
Guido van Rossum1984f1e1992-08-04 12:41:02 +000036
Guido van Rossumb6775db1994-08-01 11:34:53 +000037#ifndef WITH_THREAD
38Error! The rest of Python is not compiled with thread support.
39Rerun configure, adding a --with-thread option.
40#endif
41
Guido van Rossum1984f1e1992-08-04 12:41:02 +000042#include "thread.h"
43
Guido van Rossumb6775db1994-08-01 11:34:53 +000044extern int threads_started;
Guido van Rossumf9f2e821992-08-17 08:59:08 +000045
Guido van Rossum234f9421993-06-17 12:35:49 +000046static object *ThreadError;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000047
48
49/* Lock objects */
50
51typedef struct {
52 OB_HEAD
53 type_lock lock_lock;
54} lockobject;
55
Guido van Rossumb6775db1994-08-01 11:34:53 +000056staticforward typeobject Locktype;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000057
58#define is_lockobject(v) ((v)->ob_type == &Locktype)
59
Sjoerd Mullendered59d201993-01-06 13:36:38 +000060type_lock
61getlocklock(lock)
62 object *lock;
63{
64 if (lock == NULL || !is_lockobject(lock))
65 return NULL;
66 else
67 return ((lockobject *) lock)->lock_lock;
68}
69
Guido van Rossum1984f1e1992-08-04 12:41:02 +000070static lockobject *
71newlockobject()
72{
73 lockobject *self;
74 self = NEWOBJ(lockobject, &Locktype);
75 if (self == NULL)
76 return NULL;
77 self->lock_lock = allocate_lock();
78 if (self->lock_lock == NULL) {
79 DEL(self);
80 self = NULL;
81 err_setstr(ThreadError, "can't allocate lock");
82 }
83 return self;
84}
85
86static void
87lock_dealloc(self)
88 lockobject *self;
89{
90 /* Unlock the lock so it's safe to free it */
91 acquire_lock(self->lock_lock, 0);
92 release_lock(self->lock_lock);
93
94 free_lock(self->lock_lock);
95 DEL(self);
96}
97
98static object *
99lock_acquire_lock(self, args)
100 lockobject *self;
101 object *args;
102{
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000103 int i;
104
105 if (args != NULL) {
106 if (!getargs(args, "i", &i))
107 return NULL;
108 }
109 else
110 i = 1;
111
Guido van Rossumff4949e1992-08-05 19:58:53 +0000112 BGN_SAVE
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000113 i = acquire_lock(self->lock_lock, i);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000114 END_SAVE
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000115
116 if (args == NULL) {
117 INCREF(None);
118 return None;
119 }
120 else
121 return newintobject((long)i);
122}
123
124static object *
125lock_release_lock(self, args)
126 lockobject *self;
127 object *args;
128{
129 if (!getnoarg(args))
130 return NULL;
131
132 /* Sanity check: the lock must be locked */
133 if (acquire_lock(self->lock_lock, 0)) {
134 release_lock(self->lock_lock);
135 err_setstr(ThreadError, "release unlocked lock");
136 return NULL;
137 }
138
139 release_lock(self->lock_lock);
140 INCREF(None);
141 return None;
142}
143
144static object *
145lock_locked_lock(self, args)
146 lockobject *self;
147 object *args;
148{
149 if (!getnoarg(args))
150 return NULL;
151
152 if (acquire_lock(self->lock_lock, 0)) {
153 release_lock(self->lock_lock);
154 return newintobject(0L);
155 }
156 return newintobject(1L);
157}
158
159static struct methodlist lock_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000160 {"acquire_lock", (method)lock_acquire_lock},
161 {"acquire", (method)lock_acquire_lock},
162 {"release_lock", (method)lock_release_lock},
163 {"release", (method)lock_release_lock},
164 {"locked_lock", (method)lock_locked_lock},
165 {"locked", (method)lock_locked_lock},
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000166 {NULL, NULL} /* sentinel */
167};
168
169static object *
170lock_getattr(self, name)
171 lockobject *self;
172 char *name;
173{
174 return findmethod(lock_methods, (object *)self, name);
175}
176
177static typeobject Locktype = {
178 OB_HEAD_INIT(&Typetype)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000179 0, /*ob_size*/
180 "lock", /*tp_name*/
181 sizeof(lockobject), /*tp_size*/
182 0, /*tp_itemsize*/
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000183 /* methods */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000184 (destructor)lock_dealloc, /*tp_dealloc*/
185 0, /*tp_print*/
186 (getattrfunc)lock_getattr, /*tp_getattr*/
187 0, /*tp_setattr*/
188 0, /*tp_compare*/
189 0, /*tp_repr*/
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000190};
191
192
193/* Module functions */
194
195static void
196t_bootstrap(args_raw)
197 void *args_raw;
198{
199 object *args = (object *) args_raw;
200 object *func, *arg, *res;
201
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000202 threads_started++;
203
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000204 restore_thread((void *)NULL);
205 func = gettupleitem(args, 0);
206 arg = gettupleitem(args, 1);
207 res = call_object(func, arg);
Sjoerd Mullender66bca321993-12-03 16:54:45 +0000208 DECREF(args); /* Matches the INCREF(args) in thread_start_new_thread */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000209 if (res == NULL) {
Guido van Rossum385e7c61995-03-17 10:42:27 +0000210 if (err_occurred() == SystemExit)
211 err_clear();
212 else {
213 fprintf(stderr, "Unhandled exception in thread:\n");
214 print_error(); /* From pythonmain.c */
215 }
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000216 }
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000217 else
218 DECREF(res);
219 (void) save_thread(); /* Should always be NULL */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000220 exit_thread();
221}
222
223static object *
224thread_start_new_thread(self, args)
225 object *self; /* Not used */
226 object *args;
227{
228 object *func, *arg;
229
230 if (!getargs(args, "(OO)", &func, &arg))
231 return NULL;
232 INCREF(args);
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000233 /* Initialize the interpreter's stack save/restore mechanism */
234 init_save_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000235 if (!start_new_thread(t_bootstrap, (void*) args)) {
236 DECREF(args);
237 err_setstr(ThreadError, "can't start new thread\n");
238 return NULL;
239 }
240 /* Otherwise the DECREF(args) is done by t_bootstrap */
241 INCREF(None);
242 return None;
243}
244
245static object *
246thread_exit_thread(self, args)
247 object *self; /* Not used */
248 object *args;
249{
250 if (!getnoarg(args))
251 return NULL;
Guido van Rossum385e7c61995-03-17 10:42:27 +0000252 err_set(SystemExit);
253 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000254}
255
Guido van Rossumb6775db1994-08-01 11:34:53 +0000256#ifndef NO_EXIT_PROG
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000257static object *
258thread_exit_prog(self, args)
259 object *self; /* Not used */
260 object *args;
261{
262 int sts;
263 if (!getargs(args, "i", &sts))
264 return NULL;
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000265 goaway(sts); /* Calls exit_prog(sts) or _exit_prog(sts) */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000266 for (;;) { } /* Should not be reached */
267}
Guido van Rossumb6775db1994-08-01 11:34:53 +0000268#endif
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000269
270static object *
271thread_allocate_lock(self, args)
272 object *self; /* Not used */
273 object *args;
274{
275 if (!getnoarg(args))
276 return NULL;
Guido van Rossumff4949e1992-08-05 19:58:53 +0000277 return (object *) newlockobject();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000278}
279
Guido van Rossumb6775db1994-08-01 11:34:53 +0000280static object *
281thread_get_ident(self, args)
282 object *self; /* Not used */
283 object *args;
284{
285 long ident;
286 if (!getnoarg(args))
287 return NULL;
288 ident = get_thread_ident();
289 if (ident == -1) {
290 err_setstr(ThreadError, "no current thread ident");
291 return NULL;
292 }
293 return newintobject(ident);
294}
295
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000296static struct methodlist thread_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000297 {"start_new_thread", (method)thread_start_new_thread},
298 {"start_new", (method)thread_start_new_thread},
299 {"allocate_lock", (method)thread_allocate_lock},
300 {"allocate", (method)thread_allocate_lock},
301 {"exit_thread", (method)thread_exit_thread},
302 {"exit", (method)thread_exit_thread},
303 {"get_ident", (method)thread_get_ident},
304#ifndef NO_EXIT_PROG
305 {"exit_prog", (method)thread_exit_prog},
306#endif
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000307 {NULL, NULL} /* sentinel */
308};
309
310
311/* Initialization function */
312
313void
314initthread()
315{
Guido van Rossuma376cc51996-12-05 23:43:35 +0000316 object *m, *d;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000317
318 /* Create the module and add the functions */
319 m = initmodule("thread", thread_methods);
320
321 /* Add a symbolic constant */
322 d = getmoduledict(m);
323 ThreadError = newstringobject("thread.error");
324 INCREF(ThreadError);
325 dictinsert(d, "error", ThreadError);
326
327 /* Check for errors */
328 if (err_occurred())
329 fatal("can't initialize module thread");
330
331 /* Initialize the C thread library */
332 init_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000333}