blob: befe6a225ceed49199b4bf47eb9941f3a9476b44 [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
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"
Guido van Rossum1984f1e1992-08-04 12:41:02 +000029
Guido van Rossumb6775db1994-08-01 11:34:53 +000030#ifndef WITH_THREAD
31Error! The rest of Python is not compiled with thread support.
32Rerun configure, adding a --with-thread option.
33#endif
34
Guido van Rossum1984f1e1992-08-04 12:41:02 +000035#include "thread.h"
36
Guido van Rossumb6775db1994-08-01 11:34:53 +000037extern int threads_started;
Guido van Rossumf9f2e821992-08-17 08:59:08 +000038
Guido van Rossum234f9421993-06-17 12:35:49 +000039static object *ThreadError;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000040
41
42/* Lock objects */
43
44typedef struct {
45 OB_HEAD
46 type_lock lock_lock;
47} lockobject;
48
Guido van Rossumb6775db1994-08-01 11:34:53 +000049staticforward typeobject Locktype;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000050
51#define is_lockobject(v) ((v)->ob_type == &Locktype)
52
Sjoerd Mullendered59d201993-01-06 13:36:38 +000053type_lock
54getlocklock(lock)
55 object *lock;
56{
57 if (lock == NULL || !is_lockobject(lock))
58 return NULL;
59 else
60 return ((lockobject *) lock)->lock_lock;
61}
62
Guido van Rossum1984f1e1992-08-04 12:41:02 +000063static lockobject *
64newlockobject()
65{
66 lockobject *self;
67 self = NEWOBJ(lockobject, &Locktype);
68 if (self == NULL)
69 return NULL;
70 self->lock_lock = allocate_lock();
71 if (self->lock_lock == NULL) {
72 DEL(self);
73 self = NULL;
74 err_setstr(ThreadError, "can't allocate lock");
75 }
76 return self;
77}
78
79static void
80lock_dealloc(self)
81 lockobject *self;
82{
83 /* Unlock the lock so it's safe to free it */
84 acquire_lock(self->lock_lock, 0);
85 release_lock(self->lock_lock);
86
87 free_lock(self->lock_lock);
88 DEL(self);
89}
90
91static object *
92lock_acquire_lock(self, args)
93 lockobject *self;
94 object *args;
95{
Guido van Rossum1984f1e1992-08-04 12:41:02 +000096 int i;
97
98 if (args != NULL) {
99 if (!getargs(args, "i", &i))
100 return NULL;
101 }
102 else
103 i = 1;
104
Guido van Rossumff4949e1992-08-05 19:58:53 +0000105 BGN_SAVE
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000106 i = acquire_lock(self->lock_lock, i);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000107 END_SAVE
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000108
109 if (args == NULL) {
110 INCREF(None);
111 return None;
112 }
113 else
114 return newintobject((long)i);
115}
116
117static object *
118lock_release_lock(self, args)
119 lockobject *self;
120 object *args;
121{
122 if (!getnoarg(args))
123 return NULL;
124
125 /* Sanity check: the lock must be locked */
126 if (acquire_lock(self->lock_lock, 0)) {
127 release_lock(self->lock_lock);
128 err_setstr(ThreadError, "release unlocked lock");
129 return NULL;
130 }
131
132 release_lock(self->lock_lock);
133 INCREF(None);
134 return None;
135}
136
137static object *
138lock_locked_lock(self, args)
139 lockobject *self;
140 object *args;
141{
142 if (!getnoarg(args))
143 return NULL;
144
145 if (acquire_lock(self->lock_lock, 0)) {
146 release_lock(self->lock_lock);
147 return newintobject(0L);
148 }
149 return newintobject(1L);
150}
151
152static struct methodlist lock_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000153 {"acquire_lock", (method)lock_acquire_lock},
154 {"acquire", (method)lock_acquire_lock},
155 {"release_lock", (method)lock_release_lock},
156 {"release", (method)lock_release_lock},
157 {"locked_lock", (method)lock_locked_lock},
158 {"locked", (method)lock_locked_lock},
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000159 {NULL, NULL} /* sentinel */
160};
161
162static object *
163lock_getattr(self, name)
164 lockobject *self;
165 char *name;
166{
167 return findmethod(lock_methods, (object *)self, name);
168}
169
170static typeobject Locktype = {
171 OB_HEAD_INIT(&Typetype)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000172 0, /*ob_size*/
173 "lock", /*tp_name*/
174 sizeof(lockobject), /*tp_size*/
175 0, /*tp_itemsize*/
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000176 /* methods */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000177 (destructor)lock_dealloc, /*tp_dealloc*/
178 0, /*tp_print*/
179 (getattrfunc)lock_getattr, /*tp_getattr*/
180 0, /*tp_setattr*/
181 0, /*tp_compare*/
182 0, /*tp_repr*/
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000183};
184
185
186/* Module functions */
187
188static void
189t_bootstrap(args_raw)
190 void *args_raw;
191{
192 object *args = (object *) args_raw;
193 object *func, *arg, *res;
194
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000195 threads_started++;
196
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000197 restore_thread((void *)NULL);
198 func = gettupleitem(args, 0);
199 arg = gettupleitem(args, 1);
200 res = call_object(func, arg);
Sjoerd Mullender66bca321993-12-03 16:54:45 +0000201 DECREF(args); /* Matches the INCREF(args) in thread_start_new_thread */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000202 if (res == NULL) {
Guido van Rossum385e7c61995-03-17 10:42:27 +0000203 if (err_occurred() == SystemExit)
204 err_clear();
205 else {
206 fprintf(stderr, "Unhandled exception in thread:\n");
207 print_error(); /* From pythonmain.c */
208 }
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000209 }
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000210 else
211 DECREF(res);
212 (void) save_thread(); /* Should always be NULL */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000213 exit_thread();
214}
215
216static object *
217thread_start_new_thread(self, args)
218 object *self; /* Not used */
219 object *args;
220{
221 object *func, *arg;
222
223 if (!getargs(args, "(OO)", &func, &arg))
224 return NULL;
225 INCREF(args);
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000226 /* Initialize the interpreter's stack save/restore mechanism */
227 init_save_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000228 if (!start_new_thread(t_bootstrap, (void*) args)) {
229 DECREF(args);
230 err_setstr(ThreadError, "can't start new thread\n");
231 return NULL;
232 }
233 /* Otherwise the DECREF(args) is done by t_bootstrap */
234 INCREF(None);
235 return None;
236}
237
238static object *
239thread_exit_thread(self, args)
240 object *self; /* Not used */
241 object *args;
242{
243 if (!getnoarg(args))
244 return NULL;
Guido van Rossum385e7c61995-03-17 10:42:27 +0000245 err_set(SystemExit);
246 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000247}
248
Guido van Rossumb6775db1994-08-01 11:34:53 +0000249#ifndef NO_EXIT_PROG
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000250static object *
251thread_exit_prog(self, args)
252 object *self; /* Not used */
253 object *args;
254{
255 int sts;
256 if (!getargs(args, "i", &sts))
257 return NULL;
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000258 goaway(sts); /* Calls exit_prog(sts) or _exit_prog(sts) */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000259 for (;;) { } /* Should not be reached */
260}
Guido van Rossumb6775db1994-08-01 11:34:53 +0000261#endif
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000262
263static object *
264thread_allocate_lock(self, args)
265 object *self; /* Not used */
266 object *args;
267{
268 if (!getnoarg(args))
269 return NULL;
Guido van Rossumff4949e1992-08-05 19:58:53 +0000270 return (object *) newlockobject();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000271}
272
Guido van Rossumb6775db1994-08-01 11:34:53 +0000273static object *
274thread_get_ident(self, args)
275 object *self; /* Not used */
276 object *args;
277{
278 long ident;
279 if (!getnoarg(args))
280 return NULL;
281 ident = get_thread_ident();
282 if (ident == -1) {
283 err_setstr(ThreadError, "no current thread ident");
284 return NULL;
285 }
286 return newintobject(ident);
287}
288
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000289static struct methodlist thread_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000290 {"start_new_thread", (method)thread_start_new_thread},
291 {"start_new", (method)thread_start_new_thread},
292 {"allocate_lock", (method)thread_allocate_lock},
293 {"allocate", (method)thread_allocate_lock},
294 {"exit_thread", (method)thread_exit_thread},
295 {"exit", (method)thread_exit_thread},
296 {"get_ident", (method)thread_get_ident},
297#ifndef NO_EXIT_PROG
298 {"exit_prog", (method)thread_exit_prog},
299#endif
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000300 {NULL, NULL} /* sentinel */
301};
302
303
304/* Initialization function */
305
306void
307initthread()
308{
309 object *m, *d, *x;
310
311 /* Create the module and add the functions */
312 m = initmodule("thread", thread_methods);
313
314 /* Add a symbolic constant */
315 d = getmoduledict(m);
316 ThreadError = newstringobject("thread.error");
317 INCREF(ThreadError);
318 dictinsert(d, "error", ThreadError);
319
320 /* Check for errors */
321 if (err_occurred())
322 fatal("can't initialize module thread");
323
324 /* Initialize the C thread library */
325 init_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000326}