blob: 9cb4cbaa8a279e5a9d254816b80b1bac19d491cb [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) {
203 fprintf(stderr, "Unhandled exception in thread:\n");
204 print_error(); /* From pythonmain.c */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000205 }
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000206 else
207 DECREF(res);
208 (void) save_thread(); /* Should always be NULL */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000209 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{
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000239 object *frame;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000240 if (!getnoarg(args))
241 return NULL;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000242 frame = save_thread(); /* Should never be NULL */
243 DECREF(frame);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000244 exit_thread();
245 for (;;) { } /* Should not be reached */
246}
247
Guido van Rossumb6775db1994-08-01 11:34:53 +0000248#ifndef NO_EXIT_PROG
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000249static object *
250thread_exit_prog(self, args)
251 object *self; /* Not used */
252 object *args;
253{
254 int sts;
255 if (!getargs(args, "i", &sts))
256 return NULL;
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000257 goaway(sts); /* Calls exit_prog(sts) or _exit_prog(sts) */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000258 for (;;) { } /* Should not be reached */
259}
Guido van Rossumb6775db1994-08-01 11:34:53 +0000260#endif
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000261
262static object *
263thread_allocate_lock(self, args)
264 object *self; /* Not used */
265 object *args;
266{
267 if (!getnoarg(args))
268 return NULL;
Guido van Rossumff4949e1992-08-05 19:58:53 +0000269 return (object *) newlockobject();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000270}
271
Guido van Rossumb6775db1994-08-01 11:34:53 +0000272static object *
273thread_get_ident(self, args)
274 object *self; /* Not used */
275 object *args;
276{
277 long ident;
278 if (!getnoarg(args))
279 return NULL;
280 ident = get_thread_ident();
281 if (ident == -1) {
282 err_setstr(ThreadError, "no current thread ident");
283 return NULL;
284 }
285 return newintobject(ident);
286}
287
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000288static struct methodlist thread_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000289 {"start_new_thread", (method)thread_start_new_thread},
290 {"start_new", (method)thread_start_new_thread},
291 {"allocate_lock", (method)thread_allocate_lock},
292 {"allocate", (method)thread_allocate_lock},
293 {"exit_thread", (method)thread_exit_thread},
294 {"exit", (method)thread_exit_thread},
295 {"get_ident", (method)thread_get_ident},
296#ifndef NO_EXIT_PROG
297 {"exit_prog", (method)thread_exit_prog},
298#endif
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000299 {NULL, NULL} /* sentinel */
300};
301
302
303/* Initialization function */
304
305void
306initthread()
307{
308 object *m, *d, *x;
309
310 /* Create the module and add the functions */
311 m = initmodule("thread", thread_methods);
312
313 /* Add a symbolic constant */
314 d = getmoduledict(m);
315 ThreadError = newstringobject("thread.error");
316 INCREF(ThreadError);
317 dictinsert(d, "error", ThreadError);
318
319 /* Check for errors */
320 if (err_occurred())
321 fatal("can't initialize module thread");
322
323 /* Initialize the C thread library */
324 init_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000325}