1 /***********************************************************
2 Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3 Amsterdam, The Netherlands.
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
26 /* Interface to Sjoerd's portable C thread library */
28 #include "allobjects.h"
29 #include "modsupport.h"
34 int threads_started
= 0;
36 static object
*ThreadError
;
46 extern typeobject Locktype
; /* Really static, forward */
48 #define is_lockobject(v) ((v)->ob_type == &Locktype)
54 if (lock
== NULL
|| !is_lockobject(lock
))
57 return ((lockobject
*) lock
)->lock_lock
;
64 self
= NEWOBJ(lockobject
, &Locktype
);
67 self
->lock_lock
= allocate_lock();
68 if (self
->lock_lock
== NULL
) {
71 err_setstr(ThreadError
, "can't allocate lock");
80 /* Unlock the lock so it's safe to free it */
81 acquire_lock(self
->lock_lock
, 0);
82 release_lock(self
->lock_lock
);
84 free_lock(self
->lock_lock
);
89 lock_acquire_lock(self
, args
)
96 if (!getargs(args
, "i", &i
))
103 i
= acquire_lock(self
->lock_lock
, i
);
111 return newintobject((long)i
);
115 lock_release_lock(self
, args
)
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");
129 release_lock(self
->lock_lock
);
135 lock_locked_lock(self
, args
)
142 if (acquire_lock(self
->lock_lock
, 0)) {
143 release_lock(self
->lock_lock
);
144 return newintobject(0L);
146 return newintobject(1L);
149 static 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 */
160 lock_getattr(self
, name
)
164 return findmethod(lock_methods
, (object
*)self
, name
);
167 static typeobject Locktype
= {
168 OB_HEAD_INIT(&Typetype
)
171 sizeof(lockobject
), /*tp_size*/
174 lock_dealloc
, /*tp_dealloc*/
176 lock_getattr
, /*tp_getattr*/
183 /* Module functions */
186 t_bootstrap(args_raw
)
189 object
*args
= (object
*) args_raw
;
190 object
*func
, *arg
, *res
;
194 restore_thread((void *)NULL
);
195 func
= gettupleitem(args
, 0);
196 arg
= gettupleitem(args
, 1);
197 res
= call_object(func
, arg
);
198 DECREF(args
); /* Matches the INCREF(args) in thread_start_new_thread */
200 fprintf(stderr
, "Unhandled exception in thread:\n");
201 print_error(); /* From pythonmain.c */
203 (void) save_thread();
208 thread_start_new_thread(self
, args
)
209 object
*self
; /* Not used */
214 if (!getargs(args
, "(OO)", &func
, &arg
))
217 /* Initialize the interpreter's stack save/restore mechanism */
219 if (!start_new_thread(t_bootstrap
, (void*) args
)) {
221 err_setstr(ThreadError
, "can't start new thread\n");
224 /* Otherwise the DECREF(args) is done by t_bootstrap */
230 thread_exit_thread(self
, args
)
231 object
*self
; /* Not used */
236 (void) save_thread();
238 for (;;) { } /* Should not be reached */
242 thread_exit_prog(self
, args
)
243 object
*self
; /* Not used */
247 if (!getargs(args
, "i", &sts
))
249 goaway(sts
); /* Calls exit_prog(sts) or _exit_prog(sts) */
250 for (;;) { } /* Should not be reached */
254 thread_allocate_lock(self
, args
)
255 object
*self
; /* Not used */
260 return (object
*) newlockobject();
263 static 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 */
275 /* Initialization function */
282 /* Create the module and add the functions */
283 m
= initmodule("thread", thread_methods
);
285 /* Add a symbolic constant */
286 d
= getmoduledict(m
);
287 ThreadError
= newstringobject("thread.error");
289 dictinsert(d
, "error", ThreadError
);
291 /* Check for errors */
293 fatal("can't initialize module thread");
295 /* Initialize the C thread library */