blob: 301f060ec8b18c1fd37b0e1c1466235b39be4f84 [file] [log] [blame]
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001/***********************************************************
Guido van Rossumb6775db1994-08-01 11:34:53 +00002Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Guido van Rossum34679b71993-01-26 13:33:44 +00003Amsterdam, The Netherlands.
Guido van Rossum1984f1e1992-08-04 12:41:02 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* Thread module */
26/* Interface to Sjoerd's portable C thread library */
27
28#include "allobjects.h"
29#include "modsupport.h"
Guido van Rossum1984f1e1992-08-04 12:41:02 +000030#include "ceval.h"
31
Guido van Rossumb6775db1994-08-01 11:34:53 +000032#ifndef WITH_THREAD
33Error! The rest of Python is not compiled with thread support.
34Rerun configure, adding a --with-thread option.
35#endif
36
Guido van Rossum1984f1e1992-08-04 12:41:02 +000037#include "thread.h"
38
Guido van Rossumb6775db1994-08-01 11:34:53 +000039extern int threads_started;
Guido van Rossumf9f2e821992-08-17 08:59:08 +000040
Guido van Rossum234f9421993-06-17 12:35:49 +000041static object *ThreadError;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000042
43
44/* Lock objects */
45
46typedef struct {
47 OB_HEAD
48 type_lock lock_lock;
49} lockobject;
50
Guido van Rossumb6775db1994-08-01 11:34:53 +000051staticforward typeobject Locktype;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000052
53#define is_lockobject(v) ((v)->ob_type == &Locktype)
54
Sjoerd Mullendered59d201993-01-06 13:36:38 +000055type_lock
56getlocklock(lock)
57 object *lock;
58{
59 if (lock == NULL || !is_lockobject(lock))
60 return NULL;
61 else
62 return ((lockobject *) lock)->lock_lock;
63}
64
Guido van Rossum1984f1e1992-08-04 12:41:02 +000065static lockobject *
66newlockobject()
67{
68 lockobject *self;
69 self = NEWOBJ(lockobject, &Locktype);
70 if (self == NULL)
71 return NULL;
72 self->lock_lock = allocate_lock();
73 if (self->lock_lock == NULL) {
74 DEL(self);
75 self = NULL;
76 err_setstr(ThreadError, "can't allocate lock");
77 }
78 return self;
79}
80
81static void
82lock_dealloc(self)
83 lockobject *self;
84{
85 /* Unlock the lock so it's safe to free it */
86 acquire_lock(self->lock_lock, 0);
87 release_lock(self->lock_lock);
88
89 free_lock(self->lock_lock);
90 DEL(self);
91}
92
93static object *
94lock_acquire_lock(self, args)
95 lockobject *self;
96 object *args;
97{
Guido van Rossum1984f1e1992-08-04 12:41:02 +000098 int i;
99
100 if (args != NULL) {
101 if (!getargs(args, "i", &i))
102 return NULL;
103 }
104 else
105 i = 1;
106
Guido van Rossumff4949e1992-08-05 19:58:53 +0000107 BGN_SAVE
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000108 i = acquire_lock(self->lock_lock, i);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000109 END_SAVE
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000110
111 if (args == NULL) {
112 INCREF(None);
113 return None;
114 }
115 else
116 return newintobject((long)i);
117}
118
119static object *
120lock_release_lock(self, args)
121 lockobject *self;
122 object *args;
123{
124 if (!getnoarg(args))
125 return NULL;
126
127 /* Sanity check: the lock must be locked */
128 if (acquire_lock(self->lock_lock, 0)) {
129 release_lock(self->lock_lock);
130 err_setstr(ThreadError, "release unlocked lock");
131 return NULL;
132 }
133
134 release_lock(self->lock_lock);
135 INCREF(None);
136 return None;
137}
138
139static object *
140lock_locked_lock(self, args)
141 lockobject *self;
142 object *args;
143{
144 if (!getnoarg(args))
145 return NULL;
146
147 if (acquire_lock(self->lock_lock, 0)) {
148 release_lock(self->lock_lock);
149 return newintobject(0L);
150 }
151 return newintobject(1L);
152}
153
154static struct methodlist lock_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000155 {"acquire_lock", (method)lock_acquire_lock},
156 {"acquire", (method)lock_acquire_lock},
157 {"release_lock", (method)lock_release_lock},
158 {"release", (method)lock_release_lock},
159 {"locked_lock", (method)lock_locked_lock},
160 {"locked", (method)lock_locked_lock},
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000161 {NULL, NULL} /* sentinel */
162};
163
164static object *
165lock_getattr(self, name)
166 lockobject *self;
167 char *name;
168{
169 return findmethod(lock_methods, (object *)self, name);
170}
171
172static typeobject Locktype = {
173 OB_HEAD_INIT(&Typetype)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000174 0, /*ob_size*/
175 "lock", /*tp_name*/
176 sizeof(lockobject), /*tp_size*/
177 0, /*tp_itemsize*/
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000178 /* methods */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000179 (destructor)lock_dealloc, /*tp_dealloc*/
180 0, /*tp_print*/
181 (getattrfunc)lock_getattr, /*tp_getattr*/
182 0, /*tp_setattr*/
183 0, /*tp_compare*/
184 0, /*tp_repr*/
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000185};
186
187
188/* Module functions */
189
190static void
191t_bootstrap(args_raw)
192 void *args_raw;
193{
194 object *args = (object *) args_raw;
195 object *func, *arg, *res;
196
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000197 threads_started++;
198
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000199 restore_thread((void *)NULL);
200 func = gettupleitem(args, 0);
201 arg = gettupleitem(args, 1);
202 res = call_object(func, arg);
Sjoerd Mullender66bca321993-12-03 16:54:45 +0000203 DECREF(args); /* Matches the INCREF(args) in thread_start_new_thread */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000204 if (res == NULL) {
205 fprintf(stderr, "Unhandled exception in thread:\n");
206 print_error(); /* From pythonmain.c */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000207 }
208 (void) save_thread();
209 exit_thread();
210}
211
212static object *
213thread_start_new_thread(self, args)
214 object *self; /* Not used */
215 object *args;
216{
217 object *func, *arg;
218
219 if (!getargs(args, "(OO)", &func, &arg))
220 return NULL;
221 INCREF(args);
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000222 /* Initialize the interpreter's stack save/restore mechanism */
223 init_save_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000224 if (!start_new_thread(t_bootstrap, (void*) args)) {
225 DECREF(args);
226 err_setstr(ThreadError, "can't start new thread\n");
227 return NULL;
228 }
229 /* Otherwise the DECREF(args) is done by t_bootstrap */
230 INCREF(None);
231 return None;
232}
233
234static object *
235thread_exit_thread(self, args)
236 object *self; /* Not used */
237 object *args;
238{
239 if (!getnoarg(args))
240 return NULL;
241 (void) save_thread();
242 exit_thread();
243 for (;;) { } /* Should not be reached */
244}
245
Guido van Rossumb6775db1994-08-01 11:34:53 +0000246#ifndef NO_EXIT_PROG
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000247static object *
248thread_exit_prog(self, args)
249 object *self; /* Not used */
250 object *args;
251{
252 int sts;
253 if (!getargs(args, "i", &sts))
254 return NULL;
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000255 goaway(sts); /* Calls exit_prog(sts) or _exit_prog(sts) */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000256 for (;;) { } /* Should not be reached */
257}
Guido van Rossumb6775db1994-08-01 11:34:53 +0000258#endif
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000259
260static object *
261thread_allocate_lock(self, args)
262 object *self; /* Not used */
263 object *args;
264{
265 if (!getnoarg(args))
266 return NULL;
Guido van Rossumff4949e1992-08-05 19:58:53 +0000267 return (object *) newlockobject();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000268}
269
Guido van Rossumb6775db1994-08-01 11:34:53 +0000270static object *
271thread_get_ident(self, args)
272 object *self; /* Not used */
273 object *args;
274{
275 long ident;
276 if (!getnoarg(args))
277 return NULL;
278 ident = get_thread_ident();
279 if (ident == -1) {
280 err_setstr(ThreadError, "no current thread ident");
281 return NULL;
282 }
283 return newintobject(ident);
284}
285
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000286static struct methodlist thread_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000287 {"start_new_thread", (method)thread_start_new_thread},
288 {"start_new", (method)thread_start_new_thread},
289 {"allocate_lock", (method)thread_allocate_lock},
290 {"allocate", (method)thread_allocate_lock},
291 {"exit_thread", (method)thread_exit_thread},
292 {"exit", (method)thread_exit_thread},
293 {"get_ident", (method)thread_get_ident},
294#ifndef NO_EXIT_PROG
295 {"exit_prog", (method)thread_exit_prog},
296#endif
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000297 {NULL, NULL} /* sentinel */
298};
299
300
301/* Initialization function */
302
303void
304initthread()
305{
306 object *m, *d, *x;
307
308 /* Create the module and add the functions */
309 m = initmodule("thread", thread_methods);
310
311 /* Add a symbolic constant */
312 d = getmoduledict(m);
313 ThreadError = newstringobject("thread.error");
314 INCREF(ThreadError);
315 dictinsert(d, "error", ThreadError);
316
317 /* Check for errors */
318 if (err_occurred())
319 fatal("can't initialize module thread");
320
321 /* Initialize the C thread library */
322 init_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000323}