]> git.donarmstrong.com Git - lilypond.git/blob - guile18/libguile/threads.c
Import guile-1.8 as multiple upstream tarball component
[lilypond.git] / guile18 / libguile / threads.c
1 /* Copyright (C) 1995,1996,1997,1998,2000,2001, 2002, 2003, 2004, 2005, 2006, 2008 Free Software Foundation, Inc.
2  * 
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 2.1 of the License, or (at your option) any later version.
7  *
8  * This library 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 GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16  */
17
18
19 \f
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include "libguile/_scm.h"
25
26 #if HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 #include <stdio.h>
30 #include <assert.h>
31
32 #ifdef HAVE_STRING_H
33 #include <string.h>   /* for memset used by FD_ZERO on Solaris 10 */
34 #endif
35
36 #if HAVE_SYS_TIME_H
37 #include <sys/time.h>
38 #endif
39
40 #include "libguile/validate.h"
41 #include "libguile/root.h"
42 #include "libguile/eval.h"
43 #include "libguile/async.h"
44 #include "libguile/ports.h"
45 #include "libguile/threads.h"
46 #include "libguile/dynwind.h"
47 #include "libguile/iselect.h"
48 #include "libguile/fluids.h"
49 #include "libguile/continuations.h"
50 #include "libguile/gc.h"
51 #include "libguile/init.h"
52
53 #ifdef __MINGW32__
54 #ifndef ETIMEDOUT
55 # define ETIMEDOUT       WSAETIMEDOUT
56 #endif
57 # include <fcntl.h>
58 # include <process.h>
59 # define pipe(fd) _pipe (fd, 256, O_BINARY)
60 #endif /* __MINGW32__ */
61
62 /*** Queues */
63
64 /* Make an empty queue data structure.
65  */
66 static SCM
67 make_queue ()
68 {
69   return scm_cons (SCM_EOL, SCM_EOL);
70 }
71
72 /* Put T at the back of Q and return a handle that can be used with
73    remqueue to remove T from Q again.
74  */
75 static SCM
76 enqueue (SCM q, SCM t)
77 {
78   SCM c = scm_cons (t, SCM_EOL);
79   if (scm_is_null (SCM_CDR (q)))
80     SCM_SETCDR (q, c);
81   else
82     SCM_SETCDR (SCM_CAR (q), c);
83   SCM_SETCAR (q, c);
84   return c;
85 }
86
87 /* Remove the element that the handle C refers to from the queue Q.  C
88    must have been returned from a call to enqueue.  The return value
89    is zero when the element referred to by C has already been removed.
90    Otherwise, 1 is returned.
91 */
92 static int
93 remqueue (SCM q, SCM c)
94 {
95   SCM p, prev = q;
96   for (p = SCM_CDR (q); !scm_is_null (p); p = SCM_CDR (p))
97     {
98       if (scm_is_eq (p, c))
99         {
100           if (scm_is_eq (c, SCM_CAR (q)))
101             SCM_SETCAR (q, SCM_CDR (c));
102           SCM_SETCDR (prev, SCM_CDR (c));
103           return 1;
104         }
105       prev = p;
106     }
107   return 0;
108 }
109
110 /* Remove the front-most element from the queue Q and return it.
111    Return SCM_BOOL_F when Q is empty.
112 */
113 static SCM
114 dequeue (SCM q)
115 {
116   SCM c = SCM_CDR (q);
117   if (scm_is_null (c))
118     return SCM_BOOL_F;
119   else
120     {
121       SCM_SETCDR (q, SCM_CDR (c));
122       if (scm_is_null (SCM_CDR (q)))
123         SCM_SETCAR (q, SCM_EOL);
124       return SCM_CAR (c);
125     }
126 }
127
128 /*** Thread smob routines */
129
130 static SCM
131 thread_mark (SCM obj)
132 {
133   scm_i_thread *t = SCM_I_THREAD_DATA (obj);
134   scm_gc_mark (t->result);
135   scm_gc_mark (t->join_queue);
136   scm_gc_mark (t->dynwinds);
137   scm_gc_mark (t->active_asyncs);
138   scm_gc_mark (t->continuation_root);
139   return t->dynamic_state;
140 }
141
142 static int
143 thread_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
144 {
145   /* On a Gnu system pthread_t is an unsigned long, but on mingw it's a
146      struct.  A cast like "(unsigned long) t->pthread" is a syntax error in
147      the struct case, hence we go via a union, and extract according to the
148      size of pthread_t.  */
149   union {
150     scm_i_pthread_t p;
151     unsigned short us;
152     unsigned int   ui;
153     unsigned long  ul;
154     scm_t_uintmax  um;
155   } u;
156   scm_i_thread *t = SCM_I_THREAD_DATA (exp);
157   scm_i_pthread_t p = t->pthread;
158   scm_t_uintmax id;
159   u.p = p;
160   if (sizeof (p) == sizeof (unsigned short))
161     id = u.us;
162   else if (sizeof (p) == sizeof (unsigned int))
163     id = u.ui;
164   else if (sizeof (p) == sizeof (unsigned long))
165     id = u.ul;
166   else
167     id = u.um;
168
169   scm_puts ("#<thread ", port);
170   scm_uintprint (id, 10, port);
171   scm_puts (" (", port);
172   scm_uintprint ((scm_t_bits)t, 16, port);
173   scm_puts (")>", port);
174   return 1;
175 }
176
177 static size_t
178 thread_free (SCM obj)
179 {
180   scm_i_thread *t = SCM_I_THREAD_DATA (obj);
181   assert (t->exited);
182   scm_gc_free (t, sizeof (*t), "thread");
183   return 0;
184 }
185
186 /*** Blocking on queues. */
187
188 /* See also scm_i_queue_async_cell for how such a block is
189    interrputed.
190 */
191
192 /* Put the current thread on QUEUE and go to sleep, waiting for it to
193    be woken up by a call to 'unblock_from_queue', or to be
194    interrupted.  Upon return of this function, the current thread is
195    no longer on QUEUE, even when the sleep has been interrupted.
196
197    The QUEUE data structure is assumed to be protected by MUTEX and
198    the caller of block_self must hold MUTEX.  It will be atomically
199    unlocked while sleeping, just as with scm_i_pthread_cond_wait.
200
201    SLEEP_OBJECT is an arbitrary SCM value that is kept alive as long
202    as MUTEX is needed.
203
204    When WAITTIME is not NULL, the sleep will be aborted at that time.
205
206    The return value of block_self is an errno value.  It will be zero
207    when the sleep has been successfully completed by a call to
208    unblock_from_queue, EINTR when it has been interrupted by the
209    delivery of a system async, and ETIMEDOUT when the timeout has
210    expired.
211
212    The system asyncs themselves are not executed by block_self.
213 */
214 static int
215 block_self (SCM queue, SCM sleep_object, scm_i_pthread_mutex_t *mutex,
216             const scm_t_timespec *waittime)
217 {
218   scm_i_thread *t = SCM_I_CURRENT_THREAD;
219   SCM q_handle;
220   int err;
221
222   if (scm_i_setup_sleep (t, sleep_object, mutex, -1))
223     err = EINTR;
224   else
225     {
226       t->block_asyncs++;
227       q_handle = enqueue (queue, t->handle);
228       if (waittime == NULL)
229         err = scm_i_scm_pthread_cond_wait (&t->sleep_cond, mutex);
230       else
231         err = scm_i_scm_pthread_cond_timedwait (&t->sleep_cond, mutex, waittime);
232
233       /* When we are still on QUEUE, we have been interrupted.  We
234          report this only when no other error (such as a timeout) has
235          happened above.
236       */
237       if (remqueue (queue, q_handle) && err == 0)
238         err = EINTR;
239       t->block_asyncs--;
240       scm_i_reset_sleep (t);
241     }
242
243   return err;
244 }
245
246 /* Wake up the first thread on QUEUE, if any.  The caller must hold
247    the mutex that protects QUEUE.  The awoken thread is returned, or
248    #f when the queue was empty.
249  */
250 static SCM
251 unblock_from_queue (SCM queue)
252 {
253   SCM thread = dequeue (queue);
254   if (scm_is_true (thread))
255     scm_i_pthread_cond_signal (&SCM_I_THREAD_DATA(thread)->sleep_cond);
256   return thread;
257 }
258
259 /* Getting into and out of guile mode.
260  */
261
262 /* Ken Raeburn observes that the implementation of suspend and resume
263    (and the things that build on top of them) are very likely not
264    correct (see below).  We will need fix this eventually, and that's
265    why scm_leave_guile/scm_enter_guile are not exported in the API.
266
267    Ken writes:
268
269    Consider this sequence:
270
271    Function foo, called in Guile mode, calls suspend (maybe indirectly
272    through scm_leave_guile), which does this:
273
274       // record top of stack for the GC
275       t->top = SCM_STACK_PTR (&t);     // just takes address of automatic
276       var 't'
277       // save registers.
278       SCM_FLUSH_REGISTER_WINDOWS;      // sparc only
279       SCM_I_SETJMP (t->regs);          // here's most of the magic
280
281    ... and returns.
282
283    Function foo has a SCM value X, a handle on a non-immediate object, in
284    a caller-saved register R, and it's the only reference to the object
285    currently.
286
287    The compiler wants to use R in suspend, so it pushes the current
288    value, X, into a stack slot which will be reloaded on exit from
289    suspend; then it loads stuff into R and goes about its business.  The
290    setjmp call saves (some of) the current registers, including R, which
291    no longer contains X.  (This isn't a problem for a normal
292    setjmp/longjmp situation, where longjmp would be called before
293    setjmp's caller returns; the old value for X would be loaded back from
294    the stack after the longjmp, before the function returned.)
295
296    So, suspend returns, loading X back into R (and invalidating the jump
297    buffer) in the process.  The caller foo then goes off and calls a
298    bunch of other functions out of Guile mode, occasionally storing X on
299    the stack again, but, say, much deeper on the stack than suspend's
300    stack frame went, and the stack slot where suspend had written X has
301    long since been overwritten with other values.
302
303    Okay, nothing actively broken so far.  Now, let garbage collection
304    run, triggered by another thread.
305
306    The thread calling foo is out of Guile mode at the time, so the
307    garbage collector just scans a range of stack addresses.  Too bad that
308    X isn't stored there.  So the pointed-to storage goes onto the free
309    list, and I think you can see where things go from there.
310
311    Is there anything I'm missing that'll prevent this scenario from
312    happening?  I mean, aside from, "well, suspend and scm_leave_guile
313    don't have many local variables, so they probably won't need to save
314    any registers on most systems, so we hope everything will wind up in
315    the jump buffer and we'll just get away with it"?
316
317    (And, going the other direction, if scm_leave_guile and suspend push
318    the stack pointer over onto a new page, and foo doesn't make further
319    function calls and thus the stack pointer no longer includes that
320    page, are we guaranteed that the kernel cannot release the now-unused
321    stack page that contains the top-of-stack pointer we just saved?  I
322    don't know if any OS actually does that.  If it does, we could get
323    faults in garbage collection.)
324
325    I don't think scm_without_guile has to have this problem, as it gets
326    more control over the stack handling -- but it should call setjmp
327    itself.  I'd probably try something like:
328
329       // record top of stack for the GC
330       t->top = SCM_STACK_PTR (&t);
331       // save registers.
332       SCM_FLUSH_REGISTER_WINDOWS;
333       SCM_I_SETJMP (t->regs);
334       res = func(data);
335       scm_enter_guile (t);
336
337    ... though even that's making some assumptions about the stack
338    ordering of local variables versus caller-saved registers.
339
340    For something like scm_leave_guile to work, I don't think it can just
341    rely on invalidated jump buffers.  A valid jump buffer, and a handle
342    on the stack state at the point when the jump buffer was initialized,
343    together, would work fine, but I think then we're talking about macros
344    invoking setjmp in the caller's stack frame, and requiring that the
345    caller of scm_leave_guile also call scm_enter_guile before returning,
346    kind of like pthread_cleanup_push/pop calls that have to be paired up
347    in a function.  (In fact, the pthread ones have to be paired up
348    syntactically, as if they might expand to a compound statement
349    incorporating the user's code, and invoking a compiler's
350    exception-handling primitives.  Which might be something to think
351    about for cases where Guile is used with C++ exceptions or
352    pthread_cancel.)
353 */
354
355 scm_i_pthread_key_t scm_i_thread_key;
356
357 static void
358 resume (scm_i_thread *t)
359 {
360   t->top = NULL;
361   if (t->clear_freelists_p)
362     {
363       *SCM_FREELIST_LOC (scm_i_freelist) = SCM_EOL;
364       *SCM_FREELIST_LOC (scm_i_freelist2) = SCM_EOL;
365       t->clear_freelists_p = 0;
366     }
367 }
368
369 typedef void* scm_t_guile_ticket;
370
371 static void
372 scm_enter_guile (scm_t_guile_ticket ticket)
373 {
374   scm_i_thread *t = (scm_i_thread *)ticket;
375   if (t)
376     {
377       scm_i_pthread_mutex_lock (&t->heap_mutex);
378       resume (t);
379     }
380 }
381
382 static scm_i_thread *
383 suspend (void)
384 {
385   scm_i_thread *t = SCM_I_CURRENT_THREAD;
386
387   /* record top of stack for the GC */
388   t->top = SCM_STACK_PTR (&t);
389   /* save registers. */
390   SCM_FLUSH_REGISTER_WINDOWS;
391   SCM_I_SETJMP (t->regs);
392   return t;
393 }
394
395 static scm_t_guile_ticket
396 scm_leave_guile ()
397 {
398   scm_i_thread *t = suspend ();
399   scm_i_pthread_mutex_unlock (&t->heap_mutex);
400   return (scm_t_guile_ticket) t;
401 }
402
403 static scm_i_pthread_mutex_t thread_admin_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
404 static scm_i_thread *all_threads = NULL;
405 static int thread_count;
406
407 static SCM scm_i_default_dynamic_state;
408
409 /* Perform first stage of thread initialisation, in non-guile mode.
410  */
411 static void
412 guilify_self_1 (SCM_STACKITEM *base)
413 {
414   scm_i_thread *t = malloc (sizeof (scm_i_thread));
415
416   t->pthread = scm_i_pthread_self ();
417   t->handle = SCM_BOOL_F;
418   t->result = SCM_BOOL_F;
419   t->join_queue = SCM_EOL;
420   t->dynamic_state = SCM_BOOL_F;
421   t->dynwinds = SCM_EOL;
422   t->active_asyncs = SCM_EOL;
423   t->block_asyncs = 1;
424   t->pending_asyncs = 1;
425   t->critical_section_level = 0;
426   t->last_debug_frame = NULL;
427   t->base = base;
428 #ifdef __ia64__
429   /* Calculate and store off the base of this thread's register
430      backing store (RBS).  Unfortunately our implementation(s) of
431      scm_ia64_register_backing_store_base are only reliable for the
432      main thread.  For other threads, therefore, find out the current
433      top of the RBS, and use that as a maximum. */
434   t->register_backing_store_base = scm_ia64_register_backing_store_base ();
435   {
436     ucontext_t ctx;
437     void *bsp;
438     getcontext (&ctx);
439     bsp = scm_ia64_ar_bsp (&ctx);
440     if (t->register_backing_store_base > bsp)
441       t->register_backing_store_base = bsp;
442   }
443 #endif
444   t->continuation_root = SCM_EOL;
445   t->continuation_base = base;
446   scm_i_pthread_cond_init (&t->sleep_cond, NULL);
447   t->sleep_mutex = NULL;
448   t->sleep_object = SCM_BOOL_F;
449   t->sleep_fd = -1;
450
451   if (pipe (t->sleep_pipe) != 0)
452     /* FIXME: Error conditions during the initialization phase are handled
453        gracelessly since public functions such as `scm_init_guile ()'
454        currently have type `void'.  */
455     abort ();
456
457   scm_i_pthread_mutex_init (&t->heap_mutex, NULL);
458   t->clear_freelists_p = 0;
459   t->gc_running_p = 0;
460   t->exited = 0;
461
462   t->freelist = SCM_EOL;
463   t->freelist2 = SCM_EOL;
464   SCM_SET_FREELIST_LOC (scm_i_freelist, &t->freelist);
465   SCM_SET_FREELIST_LOC (scm_i_freelist2, &t->freelist2);
466
467   scm_i_pthread_setspecific (scm_i_thread_key, t);
468
469   /* As soon as this thread adds itself to the global thread list, the
470      GC may think that it has a stack that needs marking.  Therefore
471      initialize t->top to be the same as t->base, just in case GC runs
472      before the thread can lock its heap_mutex for the first time. */
473   t->top = t->base;
474   scm_i_pthread_mutex_lock (&thread_admin_mutex);
475   t->next_thread = all_threads;
476   all_threads = t;
477   thread_count++;
478   scm_i_pthread_mutex_unlock (&thread_admin_mutex);
479
480   /* Enter Guile mode. */
481   scm_enter_guile (t);
482 }
483
484 /* Perform second stage of thread initialisation, in guile mode.
485  */
486 static void
487 guilify_self_2 (SCM parent)
488 {
489   scm_i_thread *t = SCM_I_CURRENT_THREAD;
490
491   SCM_NEWSMOB (t->handle, scm_tc16_thread, t);
492   scm_gc_register_collectable_memory (t, sizeof (scm_i_thread), "thread");
493   t->continuation_root = scm_cons (t->handle, SCM_EOL);
494   t->continuation_base = t->base;
495
496   if (scm_is_true (parent))
497     t->dynamic_state = scm_make_dynamic_state (parent);
498   else
499     t->dynamic_state = scm_i_make_initial_dynamic_state ();
500
501   t->join_queue = make_queue ();
502   t->block_asyncs = 0;
503 }
504
505 /* Perform thread tear-down, in guile mode.
506  */
507 static void *
508 do_thread_exit (void *v)
509 {
510   scm_i_thread *t = (scm_i_thread *)v;
511
512   scm_i_scm_pthread_mutex_lock (&thread_admin_mutex);
513
514   t->exited = 1;
515   close (t->sleep_pipe[0]);
516   close (t->sleep_pipe[1]);
517   while (scm_is_true (unblock_from_queue (t->join_queue)))
518     ;
519
520   scm_i_pthread_mutex_unlock (&thread_admin_mutex);
521   return NULL;
522 }
523
524 static void
525 on_thread_exit (void *v)
526 {
527   /* This handler is executed in non-guile mode.  */
528   scm_i_thread *t = (scm_i_thread *)v, **tp;
529
530   scm_i_pthread_setspecific (scm_i_thread_key, v);
531
532   /* Unblocking the joining threads needs to happen in guile mode
533      since the queue is a SCM data structure.  */
534   scm_with_guile (do_thread_exit, v);
535
536   /* Removing ourself from the list of all threads needs to happen in
537      non-guile mode since all SCM values on our stack become
538      unprotected once we are no longer in the list.  */
539   scm_i_pthread_mutex_lock (&thread_admin_mutex);
540   for (tp = &all_threads; *tp; tp = &(*tp)->next_thread)
541     if (*tp == t)
542       {
543         *tp = t->next_thread;
544         break;
545       }
546   thread_count--;
547   scm_i_pthread_mutex_unlock (&thread_admin_mutex);
548
549   scm_i_pthread_setspecific (scm_i_thread_key, NULL);
550 }
551
552 static scm_i_pthread_once_t init_thread_key_once = SCM_I_PTHREAD_ONCE_INIT;
553
554 static void
555 init_thread_key (void)
556 {
557   scm_i_pthread_key_create (&scm_i_thread_key, on_thread_exit);
558 }
559
560 /* Perform any initializations necessary to bring the current thread
561    into guile mode, initializing Guile itself, if necessary.
562
563    BASE is the stack base to use with GC.
564
565    PARENT is the dynamic state to use as the parent, ot SCM_BOOL_F in
566    which case the default dynamic state is used.
567
568    Return zero when the thread was in guile mode already; otherwise
569    return 1.
570 */
571
572 static int
573 scm_i_init_thread_for_guile (SCM_STACKITEM *base, SCM parent)
574 {
575   scm_i_thread *t;
576
577   scm_i_pthread_once (&init_thread_key_once, init_thread_key);
578
579   if ((t = SCM_I_CURRENT_THREAD) == NULL)
580     {
581       /* This thread has not been guilified yet.
582        */
583
584       scm_i_pthread_mutex_lock (&scm_i_init_mutex);
585       if (scm_initialized_p == 0)
586         {
587           /* First thread ever to enter Guile.  Run the full
588              initialization.
589           */
590           scm_i_init_guile (base);
591           scm_i_pthread_mutex_unlock (&scm_i_init_mutex);
592         }
593       else
594         {
595           /* Guile is already initialized, but this thread enters it for
596              the first time.  Only initialize this thread.
597           */
598           scm_i_pthread_mutex_unlock (&scm_i_init_mutex);
599           guilify_self_1 (base);
600           guilify_self_2 (parent);
601         }
602       return 1;
603     }
604   else if (t->top)
605     {
606       /* This thread is already guilified but not in guile mode, just
607          resume it.
608
609          A user call to scm_with_guile() will lead us to here.  This could
610          happen from anywhere on the stack, and in particular lower on the
611          stack than when it was when this thread was first guilified.  Thus,
612          `base' must be updated.  */
613 #if SCM_STACK_GROWS_UP
614       if (base < t->base)
615          t->base = base;
616 #else
617       if (base > t->base)
618          t->base = base;
619 #endif
620
621       scm_enter_guile ((scm_t_guile_ticket) t);
622       return 1;
623     }
624   else
625     {
626       /* Thread is already in guile mode.  Nothing to do.
627       */
628       return 0;
629     }
630 }
631
632 #if SCM_USE_PTHREAD_THREADS
633
634 #if HAVE_PTHREAD_ATTR_GETSTACK && HAVE_PTHREAD_GETATTR_NP
635 /* This method for GNU/Linux and perhaps some other systems.
636    It's not for MacOS X or Solaris 10, since pthread_getattr_np is not
637    available on them.  */
638 #define HAVE_GET_THREAD_STACK_BASE
639
640 static SCM_STACKITEM *
641 get_thread_stack_base ()
642 {
643   pthread_attr_t attr;
644   void *start, *end;
645   size_t size;
646
647   pthread_getattr_np (pthread_self (), &attr);
648   pthread_attr_getstack (&attr, &start, &size);
649   end = (char *)start + size;
650
651   /* XXX - pthread_getattr_np from LinuxThreads does not seem to work
652      for the main thread, but we can use scm_get_stack_base in that
653      case.
654   */
655
656 #ifndef PTHREAD_ATTR_GETSTACK_WORKS
657   if ((void *)&attr < start || (void *)&attr >= end)
658     return scm_get_stack_base ();
659   else
660 #endif
661     {
662 #if SCM_STACK_GROWS_UP
663       return start;
664 #else
665       return end;
666 #endif
667     }
668 }
669
670 #elif HAVE_PTHREAD_GET_STACKADDR_NP
671 /* This method for MacOS X.
672    It'd be nice if there was some documentation on pthread_get_stackaddr_np,
673    but as of 2006 there's nothing obvious at apple.com.  */
674 #define HAVE_GET_THREAD_STACK_BASE
675 static SCM_STACKITEM *
676 get_thread_stack_base ()
677 {
678   return pthread_get_stackaddr_np (pthread_self ());
679 }
680
681 #elif defined (__MINGW32__)
682 /* This method for mingw.  In mingw the basic scm_get_stack_base can be used
683    in any thread.  We don't like hard-coding the name of a system, but there
684    doesn't seem to be a cleaner way of knowing scm_get_stack_base can
685    work.  */
686 #define HAVE_GET_THREAD_STACK_BASE
687 static SCM_STACKITEM *
688 get_thread_stack_base ()
689 {
690   return scm_get_stack_base ();
691 }
692
693 #endif /* pthread methods of get_thread_stack_base */
694
695 #else /* !SCM_USE_PTHREAD_THREADS */
696
697 #define HAVE_GET_THREAD_STACK_BASE
698
699 static SCM_STACKITEM *
700 get_thread_stack_base ()
701 {
702   return scm_get_stack_base ();
703 }
704
705 #endif /* !SCM_USE_PTHREAD_THREADS */
706
707 #ifdef HAVE_GET_THREAD_STACK_BASE
708
709 void
710 scm_init_guile ()
711 {
712   scm_i_init_thread_for_guile (get_thread_stack_base (),
713                                scm_i_default_dynamic_state);
714 }
715
716 #endif
717
718 void *
719 scm_with_guile (void *(*func)(void *), void *data)
720 {
721   return scm_i_with_guile_and_parent (func, data,
722                                       scm_i_default_dynamic_state);
723 }
724
725 void *
726 scm_i_with_guile_and_parent (void *(*func)(void *), void *data,
727                              SCM parent)
728 {
729   void *res;
730   int really_entered;
731   SCM_STACKITEM base_item;
732   really_entered = scm_i_init_thread_for_guile (&base_item, parent);
733   res = scm_c_with_continuation_barrier (func, data);
734   if (really_entered)
735     scm_leave_guile ();
736   return res;
737 }
738
739 void *
740 scm_without_guile (void *(*func)(void *), void *data)
741 {
742   void *res;
743   scm_t_guile_ticket t;
744   t = scm_leave_guile ();
745   res = func (data);
746   scm_enter_guile (t);
747   return res;
748 }
749
750 /*** Thread creation */
751
752 typedef struct {
753   SCM parent;
754   SCM thunk;
755   SCM handler;
756   SCM thread;
757   scm_i_pthread_mutex_t mutex;
758   scm_i_pthread_cond_t cond;
759 } launch_data;
760
761 static void *
762 really_launch (void *d)
763 {
764   launch_data *data = (launch_data *)d;
765   SCM thunk = data->thunk, handler = data->handler;
766   scm_i_thread *t;
767
768   t = SCM_I_CURRENT_THREAD;
769
770   scm_i_scm_pthread_mutex_lock (&data->mutex);
771   data->thread = scm_current_thread ();
772   scm_i_pthread_cond_signal (&data->cond);
773   scm_i_pthread_mutex_unlock (&data->mutex);
774
775   if (SCM_UNBNDP (handler))
776     t->result = scm_call_0 (thunk);
777   else
778     t->result = scm_catch (SCM_BOOL_T, thunk, handler);
779
780   return 0;
781 }
782
783 static void *
784 launch_thread (void *d)
785 {
786   launch_data *data = (launch_data *)d;
787   scm_i_pthread_detach (scm_i_pthread_self ());
788   scm_i_with_guile_and_parent (really_launch, d, data->parent);
789   return NULL;
790 }
791
792 SCM_DEFINE (scm_call_with_new_thread, "call-with-new-thread", 1, 1, 0,
793             (SCM thunk, SCM handler),
794             "Call @code{thunk} in a new thread and with a new dynamic state,\n"
795             "returning a new thread object representing the thread.  The procedure\n"
796             "@var{thunk} is called via @code{with-continuation-barrier}.\n"
797             "\n"
798             "When @var{handler} is specified, then @var{thunk} is called from\n"
799             "within a @code{catch} with tag @code{#t} that has @var{handler} as its\n"
800             "handler.  This catch is established inside the continuation barrier.\n"
801             "\n"
802             "Once @var{thunk} or @var{handler} returns, the return value is made\n"
803             "the @emph{exit value} of the thread and the thread is terminated.")
804 #define FUNC_NAME s_scm_call_with_new_thread
805 {
806   launch_data data;
807   scm_i_pthread_t id;
808   int err;
809
810   SCM_ASSERT (scm_is_true (scm_thunk_p (thunk)), thunk, SCM_ARG1, FUNC_NAME);
811   SCM_ASSERT (SCM_UNBNDP (handler) || scm_is_true (scm_procedure_p (handler)),
812               handler, SCM_ARG2, FUNC_NAME);
813
814   data.parent = scm_current_dynamic_state ();
815   data.thunk = thunk;
816   data.handler = handler;
817   data.thread = SCM_BOOL_F;
818   scm_i_pthread_mutex_init (&data.mutex, NULL);
819   scm_i_pthread_cond_init (&data.cond, NULL);
820
821   scm_i_scm_pthread_mutex_lock (&data.mutex);
822   err = scm_i_pthread_create (&id, NULL, launch_thread, &data);
823   if (err)
824     {
825       scm_i_pthread_mutex_unlock (&data.mutex);
826       errno = err;
827       scm_syserror (NULL);
828     }
829   scm_i_scm_pthread_cond_wait (&data.cond, &data.mutex);
830   scm_i_pthread_mutex_unlock (&data.mutex);
831   
832   return data.thread;
833 }
834 #undef FUNC_NAME
835
836 typedef struct {
837   SCM parent;
838   scm_t_catch_body body;
839   void *body_data;
840   scm_t_catch_handler handler;
841   void *handler_data;
842   SCM thread;
843   scm_i_pthread_mutex_t mutex;
844   scm_i_pthread_cond_t cond;
845 } spawn_data;
846
847 static void *
848 really_spawn (void *d)
849 {
850   spawn_data *data = (spawn_data *)d;
851   scm_t_catch_body body = data->body;
852   void *body_data = data->body_data;
853   scm_t_catch_handler handler = data->handler;
854   void *handler_data = data->handler_data;
855   scm_i_thread *t = SCM_I_CURRENT_THREAD;
856
857   scm_i_scm_pthread_mutex_lock (&data->mutex);
858   data->thread = scm_current_thread ();
859   scm_i_pthread_cond_signal (&data->cond);
860   scm_i_pthread_mutex_unlock (&data->mutex);
861
862   if (handler == NULL)
863     t->result = body (body_data);
864   else
865     t->result = scm_internal_catch (SCM_BOOL_T,
866                                     body, body_data,
867                                     handler, handler_data);
868
869   return 0;
870 }
871
872 static void *
873 spawn_thread (void *d)
874 {
875   spawn_data *data = (spawn_data *)d;
876   scm_i_pthread_detach (scm_i_pthread_self ());
877   scm_i_with_guile_and_parent (really_spawn, d, data->parent);
878   return NULL;
879 }
880
881 SCM
882 scm_spawn_thread (scm_t_catch_body body, void *body_data,
883                   scm_t_catch_handler handler, void *handler_data)
884 {
885   spawn_data data;
886   scm_i_pthread_t id;
887   int err;
888
889   data.parent = scm_current_dynamic_state ();
890   data.body = body;
891   data.body_data = body_data;
892   data.handler = handler;
893   data.handler_data = handler_data;
894   data.thread = SCM_BOOL_F;
895   scm_i_pthread_mutex_init (&data.mutex, NULL);
896   scm_i_pthread_cond_init (&data.cond, NULL);
897
898   scm_i_scm_pthread_mutex_lock (&data.mutex);
899   err = scm_i_pthread_create (&id, NULL, spawn_thread, &data);
900   if (err)
901     {
902       scm_i_pthread_mutex_unlock (&data.mutex);
903       errno = err;
904       scm_syserror (NULL);
905     }
906   scm_i_scm_pthread_cond_wait (&data.cond, &data.mutex);
907   scm_i_pthread_mutex_unlock (&data.mutex);
908   
909   return data.thread;
910 }
911
912 SCM_DEFINE (scm_yield, "yield", 0, 0, 0,
913             (),
914 "Move the calling thread to the end of the scheduling queue.")
915 #define FUNC_NAME s_scm_yield
916 {
917   return scm_from_bool (scm_i_sched_yield ());
918 }
919 #undef FUNC_NAME
920
921 SCM_DEFINE (scm_join_thread, "join-thread", 1, 0, 0,
922             (SCM thread),
923 "Suspend execution of the calling thread until the target @var{thread} "
924 "terminates, unless the target @var{thread} has already terminated. ")
925 #define FUNC_NAME s_scm_join_thread
926 {
927   scm_i_thread *t;
928   SCM res;
929
930   SCM_VALIDATE_THREAD (1, thread);
931   if (scm_is_eq (scm_current_thread (), thread))
932     SCM_MISC_ERROR ("can not join the current thread", SCM_EOL);
933
934   scm_i_scm_pthread_mutex_lock (&thread_admin_mutex);
935
936   t = SCM_I_THREAD_DATA (thread);
937   while (!t->exited)
938     {
939       block_self (t->join_queue, thread, &thread_admin_mutex, NULL);
940       if (t->exited)
941         break;
942       scm_i_pthread_mutex_unlock (&thread_admin_mutex);
943       SCM_TICK;
944       scm_i_scm_pthread_mutex_lock (&thread_admin_mutex);
945     }
946   res = t->result;
947
948   scm_i_pthread_mutex_unlock (&thread_admin_mutex);
949   return res;
950 }
951 #undef FUNC_NAME
952
953 /*** Fat mutexes */
954
955 /* We implement our own mutex type since we want them to be 'fair', we
956    want to do fancy things while waiting for them (like running
957    asyncs) and we might want to add things that are nice for
958    debugging.
959 */
960
961 typedef struct {
962   scm_i_pthread_mutex_t lock;
963   SCM owner;
964   int level;      /* how much the owner owns us.  
965                      < 0 for non-recursive mutexes */
966   SCM waiting;    /* the threads waiting for this mutex. */
967 } fat_mutex;
968
969 #define SCM_MUTEXP(x)         SCM_SMOB_PREDICATE (scm_tc16_mutex, x)
970 #define SCM_MUTEX_DATA(x)     ((fat_mutex *) SCM_SMOB_DATA (x))
971
972 static SCM
973 fat_mutex_mark (SCM mx)
974 {
975   fat_mutex *m = SCM_MUTEX_DATA (mx);
976   scm_gc_mark (m->owner);
977   return m->waiting;
978 }
979
980 static size_t
981 fat_mutex_free (SCM mx)
982 {
983   fat_mutex *m = SCM_MUTEX_DATA (mx);
984   scm_i_pthread_mutex_destroy (&m->lock);
985   scm_gc_free (m, sizeof (fat_mutex), "mutex");
986   return 0;
987 }
988
989 static int
990 fat_mutex_print (SCM mx, SCM port, scm_print_state *pstate SCM_UNUSED)
991 {
992   fat_mutex *m = SCM_MUTEX_DATA (mx);
993   scm_puts ("#<mutex ", port);
994   scm_uintprint ((scm_t_bits)m, 16, port);
995   scm_puts (">", port);
996   return 1;
997 }
998
999 static SCM
1000 make_fat_mutex (int recursive)
1001 {
1002   fat_mutex *m;
1003   SCM mx;
1004
1005   m = scm_gc_malloc (sizeof (fat_mutex), "mutex");
1006   scm_i_pthread_mutex_init (&m->lock, NULL);
1007   m->owner = SCM_BOOL_F;
1008   m->level = recursive? 0 : -1;
1009   m->waiting = SCM_EOL;
1010   SCM_NEWSMOB (mx, scm_tc16_mutex, (scm_t_bits) m);
1011   m->waiting = make_queue ();
1012   return mx;
1013 }
1014
1015 SCM_DEFINE (scm_make_mutex, "make-mutex", 0, 0, 0,
1016             (void),
1017             "Create a new mutex. ")
1018 #define FUNC_NAME s_scm_make_mutex
1019 {
1020   return make_fat_mutex (0);
1021 }
1022 #undef FUNC_NAME
1023
1024 SCM_DEFINE (scm_make_recursive_mutex, "make-recursive-mutex", 0, 0, 0,
1025             (void),
1026             "Create a new recursive mutex. ")
1027 #define FUNC_NAME s_scm_make_recursive_mutex
1028 {
1029   return make_fat_mutex (1);
1030 }
1031 #undef FUNC_NAME
1032
1033 static char *
1034 fat_mutex_lock (SCM mutex)
1035 {
1036   fat_mutex *m = SCM_MUTEX_DATA (mutex);
1037   SCM thread = scm_current_thread ();
1038   char *msg = NULL;
1039
1040   scm_i_scm_pthread_mutex_lock (&m->lock);
1041   if (scm_is_false (m->owner))
1042     m->owner = thread;
1043   else if (scm_is_eq (m->owner, thread))
1044     {
1045       if (m->level >= 0)
1046         m->level++;
1047       else
1048         msg = "mutex already locked by current thread";
1049     }
1050   else
1051     {
1052       while (1)
1053         {
1054           if (scm_is_eq (m->owner, thread))
1055             break;
1056           block_self (m->waiting, mutex, &m->lock, NULL);
1057           scm_i_pthread_mutex_unlock (&m->lock);
1058           SCM_TICK;
1059           scm_i_scm_pthread_mutex_lock (&m->lock);
1060         }
1061     }
1062   scm_i_pthread_mutex_unlock (&m->lock);
1063   return msg;
1064 }
1065
1066 SCM_DEFINE (scm_lock_mutex, "lock-mutex", 1, 0, 0,
1067             (SCM mx),
1068 "Lock @var{mutex}. If the mutex is already locked, the calling thread "
1069 "blocks until the mutex becomes available. The function returns when "
1070 "the calling thread owns the lock on @var{mutex}.  Locking a mutex that "
1071 "a thread already owns will succeed right away and will not block the "
1072 "thread.  That is, Guile's mutexes are @emph{recursive}. ")
1073 #define FUNC_NAME s_scm_lock_mutex
1074 {
1075   char *msg;
1076
1077   SCM_VALIDATE_MUTEX (1, mx);
1078   msg = fat_mutex_lock (mx);
1079   if (msg)
1080     scm_misc_error (NULL, msg, SCM_EOL);
1081   return SCM_BOOL_T;
1082 }
1083 #undef FUNC_NAME
1084
1085 void
1086 scm_dynwind_lock_mutex (SCM mutex)
1087 {
1088   scm_dynwind_unwind_handler_with_scm ((void(*)(SCM))scm_unlock_mutex, mutex,
1089                                        SCM_F_WIND_EXPLICITLY);
1090   scm_dynwind_rewind_handler_with_scm ((void(*)(SCM))scm_lock_mutex, mutex,
1091                                        SCM_F_WIND_EXPLICITLY);
1092 }
1093
1094 static char *
1095 fat_mutex_trylock (fat_mutex *m, int *resp)
1096 {
1097   char *msg = NULL;
1098   SCM thread = scm_current_thread ();
1099
1100   *resp = 1;
1101   scm_i_pthread_mutex_lock (&m->lock);
1102   if (scm_is_false (m->owner))
1103     m->owner = thread;
1104   else if (scm_is_eq (m->owner, thread))
1105     {
1106       if (m->level >= 0)
1107         m->level++;
1108       else
1109         msg = "mutex already locked by current thread";
1110     }
1111   else
1112     *resp = 0;
1113   scm_i_pthread_mutex_unlock (&m->lock);
1114   return msg;
1115 }
1116
1117 SCM_DEFINE (scm_try_mutex, "try-mutex", 1, 0, 0,
1118             (SCM mutex),
1119 "Try to lock @var{mutex}. If the mutex is already locked by someone "
1120 "else, return @code{#f}.  Else lock the mutex and return @code{#t}. ")
1121 #define FUNC_NAME s_scm_try_mutex
1122 {
1123   char *msg;
1124   int res;
1125
1126   SCM_VALIDATE_MUTEX (1, mutex);
1127   
1128   msg = fat_mutex_trylock (SCM_MUTEX_DATA (mutex), &res);
1129   if (msg)
1130     scm_misc_error (NULL, msg, SCM_EOL);
1131   return scm_from_bool (res);
1132 }
1133 #undef FUNC_NAME
1134
1135 static char *
1136 fat_mutex_unlock (fat_mutex *m)
1137 {
1138   char *msg = NULL;
1139
1140   scm_i_scm_pthread_mutex_lock (&m->lock);
1141   if (!scm_is_eq (m->owner, scm_current_thread ()))
1142     {
1143       if (scm_is_false (m->owner))
1144         msg = "mutex not locked";
1145       else
1146         msg = "mutex not locked by current thread";
1147     }
1148   else if (m->level > 0)
1149     m->level--;
1150   else
1151     m->owner = unblock_from_queue (m->waiting);
1152   scm_i_pthread_mutex_unlock (&m->lock);
1153
1154   return msg;
1155 }
1156
1157 SCM_DEFINE (scm_unlock_mutex, "unlock-mutex", 1, 0, 0,
1158             (SCM mx),
1159 "Unlocks @var{mutex} if the calling thread owns the lock on "
1160 "@var{mutex}.  Calling unlock-mutex on a mutex not owned by the current "
1161 "thread results in undefined behaviour. Once a mutex has been unlocked, "
1162 "one thread blocked on @var{mutex} is awakened and grabs the mutex "
1163 "lock.  Every call to @code{lock-mutex} by this thread must be matched "
1164 "with a call to @code{unlock-mutex}.  Only the last call to "
1165 "@code{unlock-mutex} will actually unlock the mutex. ")
1166 #define FUNC_NAME s_scm_unlock_mutex
1167 {
1168   char *msg;
1169   SCM_VALIDATE_MUTEX (1, mx);
1170   
1171   msg = fat_mutex_unlock (SCM_MUTEX_DATA (mx));
1172   if (msg)
1173     scm_misc_error (NULL, msg, SCM_EOL);
1174   return SCM_BOOL_T;
1175 }
1176 #undef FUNC_NAME
1177
1178 #if 0
1179
1180 SCM_DEFINE (scm_mutex_owner, "mutex-owner", 1, 0, 0,
1181             (SCM mx),
1182             "Return the thread owning @var{mx}, or @code{#f}.")
1183 #define FUNC_NAME s_scm_mutex_owner
1184 {
1185   SCM_VALIDATE_MUTEX (1, mx);
1186   return (SCM_MUTEX_DATA(mx))->owner;
1187 }
1188 #undef FUNC_NAME
1189
1190 SCM_DEFINE (scm_mutex_level, "mutex-level", 1, 0, 0,
1191             (SCM mx),
1192             "Return the lock level of a recursive mutex, or -1\n"
1193             "for a standard mutex.")
1194 #define FUNC_NAME s_scm_mutex_level
1195 {
1196   SCM_VALIDATE_MUTEX (1, mx);
1197   return scm_from_int (SCM_MUTEX_DATA(mx)->level);
1198 }
1199 #undef FUNC_NAME
1200
1201 #endif
1202
1203 /*** Fat condition variables */
1204
1205 typedef struct {
1206   scm_i_pthread_mutex_t lock;
1207   SCM waiting;               /* the threads waiting for this condition. */
1208 } fat_cond;
1209
1210 #define SCM_CONDVARP(x)       SCM_SMOB_PREDICATE (scm_tc16_condvar, x)
1211 #define SCM_CONDVAR_DATA(x)   ((fat_cond *) SCM_SMOB_DATA (x))
1212
1213 static SCM
1214 fat_cond_mark (SCM cv)
1215 {
1216   fat_cond *c = SCM_CONDVAR_DATA (cv);
1217   return c->waiting;
1218 }
1219
1220 static size_t
1221 fat_cond_free (SCM mx)
1222 {
1223   fat_cond *c = SCM_CONDVAR_DATA (mx);
1224   scm_i_pthread_mutex_destroy (&c->lock);
1225   scm_gc_free (c, sizeof (fat_cond), "condition-variable");
1226   return 0;
1227 }
1228
1229 static int
1230 fat_cond_print (SCM cv, SCM port, scm_print_state *pstate SCM_UNUSED)
1231 {
1232   fat_cond *c = SCM_CONDVAR_DATA (cv);
1233   scm_puts ("#<condition-variable ", port);
1234   scm_uintprint ((scm_t_bits)c, 16, port);
1235   scm_puts (">", port);
1236   return 1;
1237 }
1238
1239 SCM_DEFINE (scm_make_condition_variable, "make-condition-variable", 0, 0, 0,
1240             (void),
1241             "Make a new condition variable.")
1242 #define FUNC_NAME s_scm_make_condition_variable
1243 {
1244   fat_cond *c;
1245   SCM cv;
1246
1247   c = scm_gc_malloc (sizeof (fat_cond), "condition variable");
1248   scm_i_pthread_mutex_init (&c->lock, 0);
1249   c->waiting = SCM_EOL;
1250   SCM_NEWSMOB (cv, scm_tc16_condvar, (scm_t_bits) c);
1251   c->waiting = make_queue ();
1252   return cv;
1253 }
1254 #undef FUNC_NAME
1255
1256 static int
1257 fat_cond_timedwait (SCM cond, SCM mutex,
1258                     const scm_t_timespec *waittime)
1259 {
1260   scm_i_thread *t = SCM_I_CURRENT_THREAD;
1261   fat_cond *c = SCM_CONDVAR_DATA (cond);
1262   fat_mutex *m = SCM_MUTEX_DATA (mutex);
1263   const char *msg;
1264   int err = 0;
1265
1266   while (1)
1267     {
1268       scm_i_scm_pthread_mutex_lock (&c->lock);
1269       msg = fat_mutex_unlock (m);
1270       t->block_asyncs++;
1271       if (msg == NULL)
1272         {
1273           err = block_self (c->waiting, cond, &c->lock, waittime);
1274           scm_i_pthread_mutex_unlock (&c->lock);
1275           fat_mutex_lock (mutex);
1276         }
1277       else
1278         scm_i_pthread_mutex_unlock (&c->lock);
1279       t->block_asyncs--;
1280       scm_async_click ();
1281
1282       if (msg)
1283         scm_misc_error (NULL, msg, SCM_EOL);
1284
1285       scm_remember_upto_here_2 (cond, mutex);
1286
1287       if (err == 0)
1288         return 1;
1289       if (err == ETIMEDOUT)
1290         return 0;
1291       if (err != EINTR)
1292         {
1293           errno = err;
1294           scm_syserror (NULL);
1295         }
1296     }
1297 }
1298
1299 SCM_DEFINE (scm_timed_wait_condition_variable, "wait-condition-variable", 2, 1, 0,
1300             (SCM cv, SCM mx, SCM t),
1301 "Wait until @var{cond-var} has been signalled.  While waiting, "
1302 "@var{mutex} is atomically unlocked (as with @code{unlock-mutex}) and "
1303 "is locked again when this function returns.  When @var{time} is given, "
1304 "it specifies a point in time where the waiting should be aborted.  It "
1305 "can be either a integer as returned by @code{current-time} or a pair "
1306 "as returned by @code{gettimeofday}.  When the waiting is aborted the "
1307 "mutex is locked and @code{#f} is returned.  When the condition "
1308 "variable is in fact signalled, the mutex is also locked and @code{#t} "
1309 "is returned. ")
1310 #define FUNC_NAME s_scm_timed_wait_condition_variable
1311 {
1312   scm_t_timespec waittime, *waitptr = NULL;
1313
1314   SCM_VALIDATE_CONDVAR (1, cv);
1315   SCM_VALIDATE_MUTEX (2, mx);
1316   
1317   if (!SCM_UNBNDP (t))
1318     {
1319       if (scm_is_pair (t))
1320         {
1321           waittime.tv_sec = scm_to_ulong (SCM_CAR (t));
1322           waittime.tv_nsec = scm_to_ulong (SCM_CAR (t)) * 1000;
1323         }
1324       else
1325         {
1326           waittime.tv_sec = scm_to_ulong (t);
1327           waittime.tv_nsec = 0;
1328         }
1329       waitptr = &waittime;
1330     }
1331
1332   return scm_from_bool (fat_cond_timedwait (cv, mx, waitptr));
1333 }
1334 #undef FUNC_NAME
1335
1336 static void
1337 fat_cond_signal (fat_cond *c)
1338 {
1339   scm_i_scm_pthread_mutex_lock (&c->lock);
1340   unblock_from_queue (c->waiting);
1341   scm_i_pthread_mutex_unlock (&c->lock);
1342 }
1343
1344 SCM_DEFINE (scm_signal_condition_variable, "signal-condition-variable", 1, 0, 0,
1345             (SCM cv),
1346             "Wake up one thread that is waiting for @var{cv}")
1347 #define FUNC_NAME s_scm_signal_condition_variable
1348 {
1349   SCM_VALIDATE_CONDVAR (1, cv);
1350   fat_cond_signal (SCM_CONDVAR_DATA (cv));
1351   return SCM_BOOL_T;
1352 }
1353 #undef FUNC_NAME
1354
1355 static void
1356 fat_cond_broadcast (fat_cond *c)
1357 {
1358   scm_i_scm_pthread_mutex_lock (&c->lock);
1359   while (scm_is_true (unblock_from_queue (c->waiting)))
1360     ;
1361   scm_i_pthread_mutex_unlock (&c->lock);
1362 }
1363
1364 SCM_DEFINE (scm_broadcast_condition_variable, "broadcast-condition-variable", 1, 0, 0,
1365             (SCM cv),
1366             "Wake up all threads that are waiting for @var{cv}. ")
1367 #define FUNC_NAME s_scm_broadcast_condition_variable
1368 {
1369   SCM_VALIDATE_CONDVAR (1, cv);
1370   fat_cond_broadcast (SCM_CONDVAR_DATA (cv));
1371   return SCM_BOOL_T;
1372 }
1373 #undef FUNC_NAME
1374
1375 /*** Marking stacks */
1376
1377 /* XXX - what to do with this?  Do we need to handle this for blocked
1378    threads as well?
1379 */
1380 #ifdef __ia64__
1381 # define SCM_MARK_BACKING_STORE() do {                                \
1382     ucontext_t ctx;                                                   \
1383     SCM_STACKITEM * top, * bot;                                       \
1384     getcontext (&ctx);                                                \
1385     scm_mark_locations ((SCM_STACKITEM *) &ctx.uc_mcontext,           \
1386       ((size_t) (sizeof (SCM_STACKITEM) - 1 + sizeof ctx.uc_mcontext) \
1387        / sizeof (SCM_STACKITEM)));                                    \
1388     bot = (SCM_STACKITEM *) SCM_I_CURRENT_THREAD->register_backing_store_base;  \
1389     top = (SCM_STACKITEM *) scm_ia64_ar_bsp (&ctx);                   \
1390     scm_mark_locations (bot, top - bot); } while (0)
1391 #else
1392 # define SCM_MARK_BACKING_STORE()
1393 #endif
1394
1395 void
1396 scm_threads_mark_stacks (void)
1397 {
1398   scm_i_thread *t;
1399   for (t = all_threads; t; t = t->next_thread)
1400     {
1401       /* Check that thread has indeed been suspended.
1402        */
1403       assert (t->top);
1404
1405       scm_gc_mark (t->handle);
1406
1407 #if SCM_STACK_GROWS_UP
1408       scm_mark_locations (t->base, t->top - t->base);
1409 #else
1410       scm_mark_locations (t->top, t->base - t->top);
1411 #endif
1412       scm_mark_locations ((void *) &t->regs,
1413                           ((size_t) sizeof(t->regs)
1414                            / sizeof (SCM_STACKITEM)));
1415     }
1416
1417   SCM_MARK_BACKING_STORE ();
1418 }
1419
1420 /*** Select */
1421
1422 int
1423 scm_std_select (int nfds,
1424                 SELECT_TYPE *readfds,
1425                 SELECT_TYPE *writefds,
1426                 SELECT_TYPE *exceptfds,
1427                 struct timeval *timeout)
1428 {
1429   fd_set my_readfds;
1430   int res, eno, wakeup_fd;
1431   scm_i_thread *t = SCM_I_CURRENT_THREAD;
1432   scm_t_guile_ticket ticket;
1433
1434   if (readfds == NULL)
1435     {
1436       FD_ZERO (&my_readfds);
1437       readfds = &my_readfds;
1438     }
1439
1440   while (scm_i_setup_sleep (t, SCM_BOOL_F, NULL, t->sleep_pipe[1]))
1441     SCM_TICK;
1442
1443   wakeup_fd = t->sleep_pipe[0];
1444   ticket = scm_leave_guile ();
1445   FD_SET (wakeup_fd, readfds);
1446   if (wakeup_fd >= nfds)
1447     nfds = wakeup_fd+1;
1448   res = select (nfds, readfds, writefds, exceptfds, timeout);
1449   t->sleep_fd = -1;
1450   eno = errno;
1451   scm_enter_guile (ticket);
1452
1453   scm_i_reset_sleep (t);
1454
1455   if (res > 0 && FD_ISSET (wakeup_fd, readfds))
1456     {
1457       char dummy;
1458       size_t count;
1459
1460       count = read (wakeup_fd, &dummy, 1);
1461
1462       FD_CLR (wakeup_fd, readfds);
1463       res -= 1;
1464       if (res == 0)
1465         {
1466           eno = EINTR;
1467           res = -1;
1468         }
1469     }
1470   errno = eno;
1471   return res;
1472 }
1473
1474 /* Convenience API for blocking while in guile mode. */
1475
1476 #if SCM_USE_PTHREAD_THREADS
1477
1478 int
1479 scm_pthread_mutex_lock (scm_i_pthread_mutex_t *mutex)
1480 {
1481   scm_t_guile_ticket t = scm_leave_guile ();
1482   int res = scm_i_pthread_mutex_lock (mutex);
1483   scm_enter_guile (t);
1484   return res;
1485 }
1486
1487 static void
1488 do_unlock (void *data)
1489 {
1490   scm_i_pthread_mutex_unlock ((scm_i_pthread_mutex_t *)data);
1491 }
1492
1493 void
1494 scm_dynwind_pthread_mutex_lock (scm_i_pthread_mutex_t *mutex)
1495 {
1496   scm_i_scm_pthread_mutex_lock (mutex);
1497   scm_dynwind_unwind_handler (do_unlock, mutex, SCM_F_WIND_EXPLICITLY);
1498 }
1499
1500 int
1501 scm_pthread_cond_wait (scm_i_pthread_cond_t *cond, scm_i_pthread_mutex_t *mutex)
1502 {
1503   scm_t_guile_ticket t = scm_leave_guile ();
1504   int res = scm_i_pthread_cond_wait (cond, mutex);
1505   scm_enter_guile (t);
1506   return res;
1507 }
1508
1509 int
1510 scm_pthread_cond_timedwait (scm_i_pthread_cond_t *cond,
1511                             scm_i_pthread_mutex_t *mutex,
1512                             const scm_t_timespec *wt)
1513 {
1514   scm_t_guile_ticket t = scm_leave_guile ();
1515   int res = scm_i_pthread_cond_timedwait (cond, mutex, wt);
1516   scm_enter_guile (t);
1517   return res;
1518 }
1519
1520 #endif
1521
1522 unsigned long
1523 scm_std_usleep (unsigned long usecs)
1524 {
1525   struct timeval tv;
1526   tv.tv_usec = usecs % 1000000;
1527   tv.tv_sec = usecs / 1000000;
1528   scm_std_select (0, NULL, NULL, NULL, &tv);
1529   return tv.tv_sec * 1000000 + tv.tv_usec;
1530 }
1531
1532 unsigned int
1533 scm_std_sleep (unsigned int secs)
1534 {
1535   struct timeval tv;
1536   tv.tv_usec = 0;
1537   tv.tv_sec = secs;
1538   scm_std_select (0, NULL, NULL, NULL, &tv);
1539   return tv.tv_sec;
1540 }
1541
1542 /*** Misc */
1543
1544 SCM_DEFINE (scm_current_thread, "current-thread", 0, 0, 0,
1545             (void),
1546             "Return the thread that called this function.")
1547 #define FUNC_NAME s_scm_current_thread
1548 {
1549   return SCM_I_CURRENT_THREAD->handle;
1550 }
1551 #undef FUNC_NAME
1552
1553 static SCM
1554 scm_c_make_list (size_t n, SCM fill)
1555 {
1556   SCM res = SCM_EOL;
1557   while (n-- > 0)
1558     res = scm_cons (fill, res);
1559   return res;
1560 }
1561
1562 SCM_DEFINE (scm_all_threads, "all-threads", 0, 0, 0,
1563             (void),
1564             "Return a list of all threads.")
1565 #define FUNC_NAME s_scm_all_threads
1566 {
1567   /* We can not allocate while holding the thread_admin_mutex because
1568      of the way GC is done.
1569   */
1570   int n = thread_count;
1571   scm_i_thread *t;
1572   SCM list = scm_c_make_list (n, SCM_UNSPECIFIED), *l;
1573
1574   scm_i_pthread_mutex_lock (&thread_admin_mutex);
1575   l = &list;
1576   for (t = all_threads; t && n > 0; t = t->next_thread)
1577     {
1578       SCM_SETCAR (*l, t->handle);
1579       l = SCM_CDRLOC (*l);
1580       n--;
1581     }
1582   *l = SCM_EOL;
1583   scm_i_pthread_mutex_unlock (&thread_admin_mutex);
1584   return list;
1585 }
1586 #undef FUNC_NAME
1587
1588 SCM_DEFINE (scm_thread_exited_p, "thread-exited?", 1, 0, 0,
1589             (SCM thread),
1590             "Return @code{#t} iff @var{thread} has exited.\n")
1591 #define FUNC_NAME s_scm_thread_exited_p
1592 {
1593   return scm_from_bool (scm_c_thread_exited_p (thread));
1594 }
1595 #undef FUNC_NAME
1596
1597 int
1598 scm_c_thread_exited_p (SCM thread)
1599 #define FUNC_NAME  s_scm_thread_exited_p
1600 {
1601   scm_i_thread *t;
1602   SCM_VALIDATE_THREAD (1, thread);
1603   t = SCM_I_THREAD_DATA (thread);
1604   return t->exited;
1605 }
1606 #undef FUNC_NAME
1607
1608 static scm_i_pthread_cond_t wake_up_cond;
1609 int scm_i_thread_go_to_sleep;
1610 static int threads_initialized_p = 0;
1611
1612 void
1613 scm_i_thread_put_to_sleep ()
1614 {
1615   if (threads_initialized_p)
1616     {
1617       scm_i_thread *t;
1618
1619       scm_leave_guile ();
1620       scm_i_pthread_mutex_lock (&thread_admin_mutex);
1621
1622       /* Signal all threads to go to sleep 
1623        */
1624       scm_i_thread_go_to_sleep = 1;
1625       for (t = all_threads; t; t = t->next_thread)
1626         scm_i_pthread_mutex_lock (&t->heap_mutex);
1627       scm_i_thread_go_to_sleep = 0;
1628     }
1629 }
1630
1631 void
1632 scm_i_thread_invalidate_freelists ()
1633 {
1634   /* thread_admin_mutex is already locked. */
1635
1636   scm_i_thread *t;
1637   for (t = all_threads; t; t = t->next_thread)
1638     if (t != SCM_I_CURRENT_THREAD)
1639       t->clear_freelists_p = 1;
1640 }
1641
1642 void
1643 scm_i_thread_wake_up ()
1644 {
1645   if (threads_initialized_p)
1646     {
1647       scm_i_thread *t;
1648
1649       scm_i_pthread_cond_broadcast (&wake_up_cond);
1650       for (t = all_threads; t; t = t->next_thread)
1651         scm_i_pthread_mutex_unlock (&t->heap_mutex);
1652       scm_i_pthread_mutex_unlock (&thread_admin_mutex);
1653       scm_enter_guile ((scm_t_guile_ticket) SCM_I_CURRENT_THREAD);
1654     }
1655 }
1656
1657 void
1658 scm_i_thread_sleep_for_gc ()
1659 {
1660   scm_i_thread *t = suspend ();
1661   scm_i_pthread_cond_wait (&wake_up_cond, &t->heap_mutex);
1662   resume (t);
1663 }
1664
1665 /* This mutex is used by SCM_CRITICAL_SECTION_START/END.
1666  */
1667 scm_i_pthread_mutex_t scm_i_critical_section_mutex;
1668
1669 static SCM dynwind_critical_section_mutex;
1670
1671 void
1672 scm_dynwind_critical_section (SCM mutex)
1673 {
1674   if (scm_is_false (mutex))
1675     mutex = dynwind_critical_section_mutex;
1676   scm_dynwind_lock_mutex (mutex);
1677   scm_dynwind_block_asyncs ();
1678 }
1679
1680 /*** Initialization */
1681
1682 scm_i_pthread_key_t scm_i_freelist, scm_i_freelist2;
1683 #ifdef __MINGW32__
1684 scm_i_pthread_key_t *scm_i_freelist_ptr = &scm_i_freelist;
1685 scm_i_pthread_key_t *scm_i_freelist2_ptr = &scm_i_freelist2;
1686 #endif
1687 scm_i_pthread_mutex_t scm_i_misc_mutex;
1688
1689 #if SCM_USE_PTHREAD_THREADS
1690 pthread_mutexattr_t scm_i_pthread_mutexattr_recursive[1];
1691 #endif
1692
1693 void
1694 scm_threads_prehistory (SCM_STACKITEM *base)
1695 {
1696 #if SCM_USE_PTHREAD_THREADS
1697   pthread_mutexattr_init (scm_i_pthread_mutexattr_recursive);
1698   pthread_mutexattr_settype (scm_i_pthread_mutexattr_recursive,
1699                              PTHREAD_MUTEX_RECURSIVE);
1700 #endif
1701
1702   scm_i_pthread_mutex_init (&scm_i_critical_section_mutex,
1703                             scm_i_pthread_mutexattr_recursive);
1704   scm_i_pthread_mutex_init (&scm_i_misc_mutex, NULL);
1705   scm_i_pthread_cond_init (&wake_up_cond, NULL);
1706   scm_i_pthread_key_create (&scm_i_freelist, NULL);
1707   scm_i_pthread_key_create (&scm_i_freelist2, NULL);
1708   
1709   guilify_self_1 (base);
1710 }
1711
1712 scm_t_bits scm_tc16_thread;
1713 scm_t_bits scm_tc16_mutex;
1714 scm_t_bits scm_tc16_condvar;
1715
1716 void
1717 scm_init_threads ()
1718 {
1719   scm_tc16_thread = scm_make_smob_type ("thread", sizeof (scm_i_thread));
1720   scm_set_smob_mark (scm_tc16_thread, thread_mark);
1721   scm_set_smob_print (scm_tc16_thread, thread_print);
1722   scm_set_smob_free (scm_tc16_thread, thread_free);
1723
1724   scm_tc16_mutex = scm_make_smob_type ("mutex", sizeof (fat_mutex));
1725   scm_set_smob_mark (scm_tc16_mutex, fat_mutex_mark);
1726   scm_set_smob_print (scm_tc16_mutex, fat_mutex_print);
1727   scm_set_smob_free (scm_tc16_mutex, fat_mutex_free);
1728
1729   scm_tc16_condvar = scm_make_smob_type ("condition-variable",
1730                                          sizeof (fat_cond));
1731   scm_set_smob_mark (scm_tc16_condvar, fat_cond_mark);
1732   scm_set_smob_print (scm_tc16_condvar, fat_cond_print);
1733   scm_set_smob_free (scm_tc16_condvar, fat_cond_free);
1734
1735   scm_i_default_dynamic_state = SCM_BOOL_F;
1736   guilify_self_2 (SCM_BOOL_F);
1737   threads_initialized_p = 1;
1738
1739   dynwind_critical_section_mutex =
1740     scm_permanent_object (scm_make_recursive_mutex ());
1741 }
1742
1743 void
1744 scm_init_threads_default_dynamic_state ()
1745 {
1746   SCM state = scm_make_dynamic_state (scm_current_dynamic_state ());
1747   scm_i_default_dynamic_state = scm_permanent_object (state);
1748 }
1749
1750 void
1751 scm_init_thread_procs ()
1752 {
1753 #include "libguile/threads.x"
1754 }
1755
1756 /*
1757   Local Variables:
1758   c-file-style: "gnu"
1759   End:
1760 */