New files.
[bpt/guile.git] / libguile / null-threads.c
CommitLineData
3d527b27
MV
1/* Copyright (C) 2002 Free Software Foundation, Inc.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice. */
41
42
43\f
44
45#include "libguile/validate.h"
46#include "libguile/root.h"
47#include "libguile/stackchk.h"
48#include "libguile/async.h"
49#include "sys/time.h"
50#include "sys/types.h"
51
52void *scm_null_threads_data;
53
54static SCM main_thread;
55
56void
57scm_threads_init (SCM_STACKITEM *i)
58{
59 main_thread = scm_permanent_object (scm_cell (scm_tc16_thread, 0));
60 scm_null_threads_data = NULL;
61}
62
63#ifdef __ia64__
64# define SCM_MARK_BACKING_STORE() do { \
65 ucontext_t ctx; \
66 SCM_STACKITEM * top, * bot; \
67 getcontext (&ctx); \
68 scm_mark_locations ((SCM_STACKITEM *) &ctx.uc_mcontext, \
69 ((size_t) (sizeof (SCM_STACKITEM) - 1 + sizeof ctx.uc_mcontext) \
70 / sizeof (SCM_STACKITEM))); \
71 bot = (SCM_STACKITEM *) __libc_ia64_register_backing_store_base; \
72 top = (SCM_STACKITEM *) ctx.uc_mcontext.sc_ar_bsp; \
73 scm_mark_locations (bot, top - bot); } while (0)
74#else
75# define SCM_MARK_BACKING_STORE()
76#endif
77
78void
79scm_threads_mark_stacks (void)
80{
81 /* Mark objects on the C stack. */
82 SCM_FLUSH_REGISTER_WINDOWS;
83 /* This assumes that all registers are saved into the jmp_buf */
84 setjmp (scm_save_regs_gc_mark);
85 scm_mark_locations ((SCM_STACKITEM *) scm_save_regs_gc_mark,
86 ( (size_t) (sizeof (SCM_STACKITEM) - 1 +
87 sizeof scm_save_regs_gc_mark)
88 / sizeof (SCM_STACKITEM)));
89
90 {
91 unsigned long stack_len = scm_stack_size (scm_stack_base);
92#ifdef SCM_STACK_GROWS_UP
93 scm_mark_locations (scm_stack_base, stack_len);
94#else
95 scm_mark_locations (scm_stack_base - stack_len, stack_len);
96#endif
97 }
98 SCM_MARK_BACKING_STORE();
99}
100
101SCM
102scm_call_with_new_thread (SCM argl)
103#define FUNC_NAME s_call_with_new_thread
104{
105 SCM_MISC_ERROR ("threads are not supported in this version of Guile",
106 SCM_EOL);
107 return SCM_BOOL_F;
108}
109#undef FUNC_NAME
110
111SCM
112scm_spawn_thread (scm_t_catch_body body, void *body_data,
113 scm_t_catch_handler handler, void *handler_data)
114{
115 scm_misc_error ("scm_spawn_thread",
116 "threads are not supported in this version of Guile",
117 SCM_EOL);
118 return SCM_BOOL_F;
119}
120
121SCM
122scm_current_thread (void)
123{
124 return main_thread;
125}
126
127SCM
128scm_all_threads (void)
129{
130 return scm_list_1 (main_thread);
131}
132
133scm_root_state *
134scm_i_thread_root (SCM thread)
135{
136 return (scm_root_state *)scm_null_threads_data;
137}
138
139SCM
140scm_join_thread (SCM thread)
141#define FUNC_NAME s_join_thread
142{
143 SCM_MISC_ERROR ("threads are not supported in this version of Guile",
144 SCM_EOL);
145 return SCM_BOOL_F;
146}
147#undef FUNC_NAME
148
149SCM
150scm_yield (void)
151{
152 return SCM_BOOL_T;
153}
154
155/* Block until a new async might have been queued.
156 */
157static void
158block ()
159{
160 select (0, NULL, NULL, NULL, NULL);
161}
162
163int
164scm_null_mutex_init (scm_null_mutex *m)
165{
166 m->locked = 0;
167 return 0;
168}
169
170int
171scm_null_mutex_lock (scm_null_mutex *m)
172{
173 while (m->locked)
174 {
175 block ();
176 SCM_ASYNC_TICK;
177 }
178 m->locked = 1;
179 return 1;
180}
181
182int
183scm_null_mutex_unlock (scm_null_mutex *m)
184{
185 if (m->locked == 0)
186 return 0;
187 m->locked = 0;
188 return 1;
189}
190
191int
192scm_null_mutex_destroy (scm_null_mutex *m)
193{
194 return 1;
195}
196
197SCM
198scm_make_mutex (void)
199{
200 SCM m = scm_make_smob (scm_tc16_mutex);
201 scm_null_mutex_init (SCM_MUTEX_DATA(m));
202 return m;
203}
204
205SCM
206scm_lock_mutex (SCM m)
207{
208 SCM_ASSERT (SCM_MUTEXP (m), m, SCM_ARG1, s_lock_mutex);
209 scm_null_mutex_lock (SCM_MUTEX_DATA(m));
210 return SCM_BOOL_T;
211}
212
213SCM
214scm_unlock_mutex (SCM m)
215{
216 SCM_ASSERT (SCM_MUTEXP (m), m, SCM_ARG1, s_unlock_mutex);
217 if (!scm_null_mutex_unlock (SCM_MUTEX_DATA(m)))
218 scm_misc_error (s_unlock_mutex, "mutex is not locked", SCM_EOL);
219 return SCM_BOOL_T;
220}
221
222int
223scm_null_condvar_init (scm_null_condvar *c)
224{
225 c->signalled = 0;
226 return 0;
227}
228
229int
230scm_null_condvar_wait (scm_null_condvar *c, scm_null_mutex *m)
231{
232 scm_null_mutex_unlock (m);
233 while (!c->signalled)
234 {
235 block ();
236 SCM_ASYNC_TICK;
237 }
238 scm_null_mutex_lock (m);
239 c->signalled = 0;
240 return 0;
241}
242
243int
244scm_null_condvar_signal (scm_null_condvar *c)
245{
246 c->signalled = 1;
247 return 0;
248}
249
250int
251scm_null_condvar_destroy (scm_null_condvar *c)
252{
253 return 1;
254}
255
256SCM
257scm_make_condition_variable (void)
258{
259 SCM c = scm_make_smob (scm_tc16_condvar);
260 scm_null_condvar_init (SCM_CONDVAR_DATA (c));
261 return c;
262}
263
264SCM
265scm_wait_condition_variable (SCM c, SCM m)
266{
267 SCM_ASSERT (SCM_CONDVARP (c),
268 c,
269 SCM_ARG1,
270 s_wait_condition_variable);
271 SCM_ASSERT (SCM_MUTEXP (m),
272 m,
273 SCM_ARG2,
274 s_wait_condition_variable);
275 scm_null_condvar_wait (SCM_CONDVAR_DATA (c), SCM_MUTEX_DATA (m));
276 return SCM_BOOL_T;
277}
278
279SCM
280scm_signal_condition_variable (SCM c)
281{
282 SCM_ASSERT (SCM_CONDVARP (c),
283 c,
284 SCM_ARG1,
285 s_signal_condition_variable);
286 scm_null_condvar_signal (SCM_CONDVAR_DATA (c));
287 return SCM_BOOL_T;
288}
289
290unsigned long
291scm_thread_usleep (unsigned long usec)
292{
293 struct timeval timeout;
294 timeout.tv_sec = 0;
295 timeout.tv_usec = usec;
296 select (0, NULL, NULL, NULL, &timeout);
297 return 0; /* Maybe we should calculate actual time slept,
298 but this is faster... :) */
299}
300
301unsigned long
302scm_thread_sleep (unsigned long sec)
303{
304 time_t now = time (NULL);
305 struct timeval timeout;
306 unsigned long slept;
307 timeout.tv_sec = sec;
308 timeout.tv_usec = 0;
309 select (0, NULL, NULL, NULL, &timeout);
310 slept = time (NULL) - now;
311 return slept > sec ? 0 : sec - slept;
312}
313
314/*
315 Local Variables:
316 c-file-style: "gnu"
317 End:
318*/