blob: 40169a3a4fa1e5e7d67ac910da3c44b39378dc57 [file] [log] [blame]
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001/***********************************************************
Guido van Rossum34679b71993-01-26 13:33:44 +00002Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, 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
32#include "thread.h"
33
Guido van Rossumf9f2e821992-08-17 08:59:08 +000034int threads_started = 0;
35
Guido van Rossum234f9421993-06-17 12:35:49 +000036static object *ThreadError;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000037
38
39/* Lock objects */
40
41typedef struct {
42 OB_HEAD
43 type_lock lock_lock;
44} lockobject;
45
46extern typeobject Locktype; /* Really static, forward */
47
48#define is_lockobject(v) ((v)->ob_type == &Locktype)
49
Sjoerd Mullendered59d201993-01-06 13:36:38 +000050type_lock
51getlocklock(lock)
52 object *lock;
53{
54 if (lock == NULL || !is_lockobject(lock))
55 return NULL;
56 else
57 return ((lockobject *) lock)->lock_lock;
58}
59
Guido van Rossum1984f1e1992-08-04 12:41:02 +000060static lockobject *
61newlockobject()
62{
63 lockobject *self;
64 self = NEWOBJ(lockobject, &Locktype);
65 if (self == NULL)
66 return NULL;
67 self->lock_lock = allocate_lock();
68 if (self->lock_lock == NULL) {
69 DEL(self);
70 self = NULL;
71 err_setstr(ThreadError, "can't allocate lock");
72 }
73 return self;
74}
75
76static void
77lock_dealloc(self)
78 lockobject *self;
79{
80 /* Unlock the lock so it's safe to free it */
81 acquire_lock(self->lock_lock, 0);
82 release_lock(self->lock_lock);
83
84 free_lock(self->lock_lock);
85 DEL(self);
86}
87
88static object *
89lock_acquire_lock(self, args)
90 lockobject *self;
91 object *args;
92{
Guido van Rossum1984f1e1992-08-04 12:41:02 +000093 int i;
94
95 if (args != NULL) {
96 if (!getargs(args, "i", &i))
97 return NULL;
98 }
99 else
100 i = 1;
101
Guido van Rossumff4949e1992-08-05 19:58:53 +0000102 BGN_SAVE
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000103 i = acquire_lock(self->lock_lock, i);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000104 END_SAVE
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000105
106 if (args == NULL) {
107 INCREF(None);
108 return None;
109 }
110 else
111 return newintobject((long)i);
112}
113
114static object *
115lock_release_lock(self, args)
116 lockobject *self;
117 object *args;
118{
119 if (!getnoarg(args))
120 return NULL;
121
122 /* Sanity check: the lock must be locked */
123 if (acquire_lock(self->lock_lock, 0)) {
124 release_lock(self->lock_lock);
125 err_setstr(ThreadError, "release unlocked lock");
126 return NULL;
127 }
128
129 release_lock(self->lock_lock);
130 INCREF(None);
131 return None;
132}
133
134static object *
135lock_locked_lock(self, args)
136 lockobject *self;
137 object *args;
138{
139 if (!getnoarg(args))
140 return NULL;
141
142 if (acquire_lock(self->lock_lock, 0)) {
143 release_lock(self->lock_lock);
144 return newintobject(0L);
145 }
146 return newintobject(1L);
147}
148
149static struct methodlist lock_methods[] = {
150 {"acquire_lock", lock_acquire_lock},
151 {"acquire", lock_acquire_lock},
152 {"release_lock", lock_release_lock},
153 {"release", lock_release_lock},
154 {"locked_lock", lock_locked_lock},
155 {"locked", lock_locked_lock},
156 {NULL, NULL} /* sentinel */
157};
158
159static object *
160lock_getattr(self, name)
161 lockobject *self;
162 char *name;
163{
164 return findmethod(lock_methods, (object *)self, name);
165}
166
167static typeobject Locktype = {
168 OB_HEAD_INIT(&Typetype)
169 0, /*ob_size*/
170 "lock", /*tp_name*/
171 sizeof(lockobject), /*tp_size*/
172 0, /*tp_itemsize*/
173 /* methods */
174 lock_dealloc, /*tp_dealloc*/
175 0, /*tp_print*/
176 lock_getattr, /*tp_getattr*/
177 0, /*tp_setattr*/
178 0, /*tp_compare*/
179 0, /*tp_repr*/
180};
181
182
183/* Module functions */
184
185static void
186t_bootstrap(args_raw)
187 void *args_raw;
188{
189 object *args = (object *) args_raw;
190 object *func, *arg, *res;
191
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000192 threads_started++;
193
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000194 restore_thread((void *)NULL);
195 func = gettupleitem(args, 0);
196 arg = gettupleitem(args, 1);
197 res = call_object(func, arg);
Sjoerd Mullender66bca321993-12-03 16:54:45 +0000198 DECREF(args); /* Matches the INCREF(args) in thread_start_new_thread */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000199 if (res == NULL) {
200 fprintf(stderr, "Unhandled exception in thread:\n");
201 print_error(); /* From pythonmain.c */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000202 }
203 (void) save_thread();
204 exit_thread();
205}
206
207static object *
208thread_start_new_thread(self, args)
209 object *self; /* Not used */
210 object *args;
211{
212 object *func, *arg;
213
214 if (!getargs(args, "(OO)", &func, &arg))
215 return NULL;
216 INCREF(args);
Sjoerd Mullendered59d201993-01-06 13:36:38 +0000217 /* Initialize the interpreter's stack save/restore mechanism */
218 init_save_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000219 if (!start_new_thread(t_bootstrap, (void*) args)) {
220 DECREF(args);
221 err_setstr(ThreadError, "can't start new thread\n");
222 return NULL;
223 }
224 /* Otherwise the DECREF(args) is done by t_bootstrap */
225 INCREF(None);
226 return None;
227}
228
229static object *
230thread_exit_thread(self, args)
231 object *self; /* Not used */
232 object *args;
233{
234 if (!getnoarg(args))
235 return NULL;
236 (void) save_thread();
237 exit_thread();
238 for (;;) { } /* Should not be reached */
239}
240
241static object *
242thread_exit_prog(self, args)
243 object *self; /* Not used */
244 object *args;
245{
246 int sts;
247 if (!getargs(args, "i", &sts))
248 return NULL;
Guido van Rossumf9f2e821992-08-17 08:59:08 +0000249 goaway(sts); /* Calls exit_prog(sts) or _exit_prog(sts) */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000250 for (;;) { } /* Should not be reached */
251}
252
253static object *
254thread_allocate_lock(self, args)
255 object *self; /* Not used */
256 object *args;
257{
258 if (!getnoarg(args))
259 return NULL;
Guido van Rossumff4949e1992-08-05 19:58:53 +0000260 return (object *) newlockobject();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000261}
262
263static struct methodlist thread_methods[] = {
264 {"start_new_thread", thread_start_new_thread},
265 {"start_new", thread_start_new_thread},
266 {"allocate_lock", thread_allocate_lock},
267 {"allocate", thread_allocate_lock},
268 {"exit_thread", thread_exit_thread},
269 {"exit", thread_exit_thread},
270 {"exit_prog", thread_exit_prog},
271 {NULL, NULL} /* sentinel */
272};
273
274
275/* Initialization function */
276
277void
278initthread()
279{
280 object *m, *d, *x;
281
282 /* Create the module and add the functions */
283 m = initmodule("thread", thread_methods);
284
285 /* Add a symbolic constant */
286 d = getmoduledict(m);
287 ThreadError = newstringobject("thread.error");
288 INCREF(ThreadError);
289 dictinsert(d, "error", ThreadError);
290
291 /* Check for errors */
292 if (err_occurred())
293 fatal("can't initialize module thread");
294
295 /* Initialize the C thread library */
296 init_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000297}