1 /* Copyright (C) 1995,1996,1997,1998,2000,2001, 2002, 2006 Free Software Foundation, Inc.
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.
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.
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
21 #include "libguile/_scm.h" /* config.h, _scm.h, __scm.h should be first */
28 #include "libguile/validate.h"
29 #include "libguile/coop-pthreads.h"
30 #include "libguile/root.h"
31 #include "libguile/eval.h"
32 #include "libguile/async.h"
33 #include "libguile/ports.h"
42 return scm_cons (SCM_EOL
, SCM_EOL
);
46 enqueue (SCM q
, SCM t
)
48 SCM c
= scm_cons (t
, SCM_EOL
);
49 if (scm_is_null (SCM_CAR (q
)))
52 SCM_SETCDR (SCM_CDR (q
), c
);
64 SCM_SETCAR (q
, SCM_CDR (c
));
65 if (scm_is_null (SCM_CAR (q
)))
66 SCM_SETCDR (q
, SCM_EOL
);
74 typedef struct scm_copt_thread
{
76 /* A condition variable for sleeping on.
78 pthread_cond_t sleep_cond
;
80 /* A link for waiting queues.
82 struct scm_copt_thread
*next_waiting
;
91 /* For keeping track of the stack and registers. */
99 make_thread (SCM creation_protects
)
102 scm_copt_thread
*t
= scm_gc_malloc (sizeof(*t
), "thread");
103 z
= scm_cell (scm_tc16_thread
, (scm_t_bits
)t
);
105 t
->result
= creation_protects
;
107 t
->joining_threads
= make_queue ();
108 pthread_cond_init (&t
->sleep_cond
, NULL
);
113 init_thread_creator (SCM thread
, pthread_t th
, scm_root_state
*r
)
115 scm_copt_thread
*t
= SCM_THREAD_DATA(thread
);
119 // fprintf (stderr, "%ld created %ld\n", pthread_self (), th);
124 init_thread_creatant (SCM thread
, SCM_STACKITEM
*base
)
126 scm_copt_thread
*t
= SCM_THREAD_DATA(thread
);
132 thread_mark (SCM obj
)
134 scm_copt_thread
*t
= SCM_THREAD_DATA (obj
);
135 scm_gc_mark (t
->result
);
136 scm_gc_mark (t
->joining_threads
);
137 return t
->root
->handle
;
141 thread_print (SCM exp
, SCM port
, scm_print_state
*pstate SCM_UNUSED
)
143 scm_copt_thread
*t
= SCM_THREAD_DATA (exp
);
144 scm_puts ("#<thread ", port
);
145 scm_uintprint ((scm_t_bits
)t
, 16, port
);
146 if (t
->pthread
!= -1)
148 scm_putc (' ', port
);
149 scm_intprint (t
->pthread
, 10, port
);
152 scm_puts (" (exited)", port
);
153 scm_putc ('>', port
);
158 thread_free (SCM obj
)
160 scm_copt_thread
*t
= SCM_THREAD_DATA (obj
);
161 if (t
->pthread
!= -1)
163 scm_gc_free (t
, sizeof (*t
), "thread");
169 /* POSIX mutexes are not necessarily fair but since we'd like to use a
170 mutex for scheduling, we build a fair one on top of POSIX.
173 typedef struct fair_mutex
{
174 pthread_mutex_t lock
;
175 scm_copt_thread
*owner
;
176 scm_copt_thread
*next_waiting
, *last_waiting
;
180 fair_mutex_init (fair_mutex
*m
)
182 pthread_mutex_init (&m
->lock
, NULL
);
184 m
->next_waiting
= NULL
;
185 m
->last_waiting
= NULL
;
189 fair_mutex_lock_1 (fair_mutex
*m
, scm_copt_thread
*t
)
191 if (m
->owner
== NULL
)
195 t
->next_waiting
= NULL
;
197 m
->last_waiting
->next_waiting
= t
;
203 pthread_cond_wait (&t
->sleep_cond
, &m
->lock
);
205 while (m
->owner
!= t
);
206 assert (m
->next_waiting
== t
);
207 m
->next_waiting
= t
->next_waiting
;
208 if (m
->next_waiting
== NULL
)
209 m
->last_waiting
= NULL
;
211 pthread_mutex_unlock (&m
->lock
);
215 fair_mutex_lock (fair_mutex
*m
, scm_copt_thread
*t
)
217 pthread_mutex_lock (&m
->lock
);
218 fair_mutex_lock_1 (m
, t
);
222 fair_mutex_unlock_1 (fair_mutex
*m
)
225 pthread_mutex_lock (&m
->lock
);
226 // fprintf (stderr, "%ld unlocking\n", m->owner->pthread);
227 if ((t
= m
->next_waiting
) != NULL
)
230 pthread_cond_signal (&t
->sleep_cond
);
234 // fprintf (stderr, "%ld unlocked\n", pthread_self ());
238 fair_mutex_unlock (fair_mutex
*m
)
240 fair_mutex_unlock_1 (m
);
241 pthread_mutex_unlock (&m
->lock
);
244 /* Temporarily give up the mutex. This function makes sure that we
245 are on the wait queue before starting the next thread. Otherwise
246 the next thread might preempt us and we will have a hard time
247 getting on the wait queue.
251 fair_mutex_yield (fair_mutex
*m
)
253 scm_copt_thread
*self
, *next
;
255 pthread_mutex_lock (&m
->lock
);
259 if ((next
= m
->next_waiting
) == NULL
)
261 /* No use giving it up. */
262 pthread_mutex_unlock (&m
->lock
);
269 self
->next_waiting
= NULL
;
271 m
->last_waiting
->next_waiting
= self
;
273 m
->next_waiting
= self
;
274 m
->last_waiting
= self
;
276 /* wake up next thread
280 pthread_cond_signal (&next
->sleep_cond
);
286 pthread_cond_wait (&self
->sleep_cond
, &m
->lock
);
288 while (m
->owner
!= self
);
289 assert (m
->next_waiting
== self
);
290 m
->next_waiting
= self
->next_waiting
;
291 if (m
->next_waiting
== NULL
)
292 m
->last_waiting
= NULL
;
294 pthread_mutex_unlock (&m
->lock
);
298 fair_mutex_yield (fair_mutex
*m
)
300 scm_copt_thread
*self
= m
->owner
;
301 fair_mutex_unlock_1 (m
);
302 fair_mutex_lock_1 (m
, self
);
307 fair_cond_wait (pthread_cond_t
*c
, fair_mutex
*m
)
309 scm_copt_thread
*t
= m
->owner
;
310 fair_mutex_unlock_1 (m
);
311 pthread_cond_wait (c
, &m
->lock
);
312 fair_mutex_lock_1 (m
, t
);
315 /* Return 1 when the mutex was signalled and 0 when not. */
317 fair_cond_timedwait (pthread_cond_t
*c
, fair_mutex
*m
, scm_t_timespec
*at
)
320 scm_copt_thread
*t
= m
->owner
;
321 fair_mutex_unlock_1 (m
);
322 res
= pthread_cond_timedwait (c
, &m
->lock
, at
); /* XXX - signals? */
323 fair_mutex_lock_1 (m
, t
);
329 /* When a thread wants to execute Guile functions, it locks the
333 static fair_mutex guile_mutex
;
335 static SCM cur_thread
;
336 void *scm_i_copt_thread_data
;
339 scm_i_copt_set_thread_data (void *data
)
341 scm_copt_thread
*t
= SCM_THREAD_DATA (cur_thread
);
342 scm_i_copt_thread_data
= data
;
343 t
->root
= (scm_root_state
*)data
;
347 resume (scm_copt_thread
*t
)
349 cur_thread
= t
->handle
;
350 scm_i_copt_thread_data
= t
->root
;
355 enter_guile (scm_copt_thread
*t
)
357 fair_mutex_lock (&guile_mutex
, t
);
361 static scm_copt_thread
*
364 SCM cur
= cur_thread
;
365 scm_copt_thread
*c
= SCM_THREAD_DATA (cur
);
367 /* record top of stack for the GC */
368 c
->top
= (SCM_STACKITEM
*)&c
;
369 /* save registers. */
370 SCM_FLUSH_REGISTER_WINDOWS
;
376 static scm_copt_thread
*
379 scm_copt_thread
*c
= suspend ();
380 fair_mutex_unlock (&guile_mutex
);
384 int scm_i_switch_counter
;
389 /* Testing guile_mutex.next_waiting without locking guile_mutex.lock
390 is OK since the outcome is not critical. Even when it changes
391 after the test, we do the right thing.
393 if (guile_mutex
.next_waiting
)
395 scm_copt_thread
*t
= suspend ();
396 fair_mutex_yield (&guile_mutex
);
402 /* Put the current thread to sleep until it is explicitely unblocked.
407 scm_copt_thread
*t
= suspend ();
408 fair_cond_wait (&t
->sleep_cond
, &guile_mutex
);
412 /* Put the current thread to sleep until it is explicitely unblocked
413 or until a signal arrives or until time AT (absolute time) is
414 reached. Return 1 when it has been unblocked; 0 otherwise.
417 timed_block (scm_t_timespec
*at
)
420 scm_copt_thread
*t
= suspend ();
421 res
= fair_cond_timedwait (&t
->sleep_cond
, &guile_mutex
, at
);
426 /* Unblock a sleeping thread.
429 unblock (scm_copt_thread
*t
)
431 pthread_cond_signal (&t
->sleep_cond
);
434 /*** Thread creation */
436 static SCM all_threads
;
437 static int thread_count
;
439 typedef struct launch_data
{
442 scm_t_catch_body body
;
444 scm_t_catch_handler handler
;
449 body_bootstrip (launch_data
* data
)
451 /* First save the new root continuation */
452 data
->rootcont
= scm_root
->rootcont
;
453 return (data
->body
) (data
->body_data
);
454 // return scm_call_0 (data->body);
458 handler_bootstrip (launch_data
* data
, SCM tag
, SCM throw_args
)
460 scm_root
->rootcont
= data
->rootcont
;
461 return (data
->handler
) (data
->handler_data
, tag
, throw_args
);
462 // return scm_apply_1 (data->handler, tag, throw_args);
466 really_launch (SCM_STACKITEM
*base
, launch_data
*data
)
468 SCM thread
= data
->thread
;
469 scm_copt_thread
*t
= SCM_THREAD_DATA (thread
);
470 init_thread_creatant (thread
, base
);
473 data
->rootcont
= SCM_BOOL_F
;
475 scm_internal_cwdr ((scm_t_catch_body
) body_bootstrip
,
477 (scm_t_catch_handler
) handler_bootstrip
,
481 pthread_detach (t
->pthread
);
482 all_threads
= scm_delq (thread
, all_threads
);
489 launch_thread (void *p
)
491 really_launch ((SCM_STACKITEM
*)&p
, (launch_data
*)p
);
496 create_thread (scm_t_catch_body body
, void *body_data
,
497 scm_t_catch_handler handler
, void *handler_data
,
502 /* Make new thread. The first thing the new thread will do is to
503 lock guile_mutex. Thus, we can safely complete its
504 initialization after creating it. While the new thread starts,
505 all its data is protected via all_threads.
513 /* Unwind wind chain. */
514 old_winds
= scm_dynwinds
;
515 scm_dowinds (SCM_EOL
, scm_ilength (scm_root
->dynwinds
));
517 /* Allocate thread locals. */
518 root
= scm_make_root (scm_root
->handle
);
519 data
= scm_malloc (sizeof (launch_data
));
522 thread
= make_thread (protects
);
523 data
->thread
= thread
;
525 data
->body_data
= body_data
;
526 data
->handler
= handler
;
527 data
->handler_data
= handler_data
;
528 pthread_create (&th
, NULL
, launch_thread
, (void *) data
);
529 init_thread_creator (thread
, th
, SCM_ROOT_STATE (root
));
530 all_threads
= scm_cons (thread
, all_threads
);
533 /* Return to old dynamic context. */
534 scm_dowinds (old_winds
, - scm_ilength (old_winds
));
541 scm_call_with_new_thread (SCM argl
)
542 #define FUNC_NAME s_call_with_new_thread
546 /* Check arguments. */
548 register SCM args
= argl
;
549 if (!scm_is_pair (args
))
550 SCM_WRONG_NUM_ARGS ();
551 thunk
= SCM_CAR (args
);
552 SCM_ASSERT (scm_is_true (scm_thunk_p (thunk
)),
555 s_call_with_new_thread
);
556 args
= SCM_CDR (args
);
557 if (!scm_is_pair (args
))
558 SCM_WRONG_NUM_ARGS ();
559 handler
= SCM_CAR (args
);
560 SCM_ASSERT (scm_is_true (scm_procedure_p (handler
)),
563 s_call_with_new_thread
);
564 if (!scm_is_null (SCM_CDR (args
)))
565 SCM_WRONG_NUM_ARGS ();
568 return create_thread ((scm_t_catch_body
) scm_call_0
, thunk
,
569 (scm_t_catch_handler
) scm_apply_1
, handler
,
575 scm_spawn_thread (scm_t_catch_body body
, void *body_data
,
576 scm_t_catch_handler handler
, void *handler_data
)
578 return create_thread (body
, body_data
, handler
, handler_data
, SCM_BOOL_F
);
583 /* We implement our own mutex type since we want them to be 'fair', we
584 want to do fancy things while waiting for them (like running
585 asyncs) and we want to support waiting on many things at once.
586 Also, we might add things that are nice for debugging.
589 typedef struct scm_copt_mutex
{
590 /* the thread currently owning the mutex, or SCM_BOOL_F. */
592 /* how much the owner owns us. */
594 /* the threads waiting for this mutex. */
601 scm_copt_mutex
*m
= SCM_MUTEX_DATA (mx
);
602 scm_gc_mark (m
->owner
);
609 SCM mx
= scm_make_smob (scm_tc16_mutex
);
610 scm_copt_mutex
*m
= SCM_MUTEX_DATA (mx
);
611 m
->owner
= SCM_BOOL_F
;
613 m
->waiting
= make_queue ();
618 scm_lock_mutex (SCM mx
)
619 #define FUNC_NAME s_lock_mutex
622 SCM_ASSERT (SCM_MUTEXP (mx
), mx
, SCM_ARG1
, FUNC_NAME
);
623 m
= SCM_MUTEX_DATA (mx
);
625 if (m
->owner
== SCM_BOOL_F
)
626 m
->owner
= cur_thread
;
627 else if (m
->owner
== cur_thread
)
631 while (m
->owner
!= cur_thread
)
633 enqueue (m
->waiting
, cur_thread
);
643 scm_try_mutex (SCM mx
)
644 #define FUNC_NAME s_try_mutex
647 SCM_ASSERT (SCM_MUTEXP (mx
), mx
, SCM_ARG1
, FUNC_NAME
);
648 m
= SCM_MUTEX_DATA (mx
);
650 if (m
->owner
== SCM_BOOL_F
)
651 m
->owner
= cur_thread
;
652 else if (m
->owner
== cur_thread
)
661 scm_unlock_mutex (SCM mx
)
662 #define FUNC_NAME s_unlock_mutex
665 SCM_ASSERT (SCM_MUTEXP (mx
), mx
, SCM_ARG1
, FUNC_NAME
);
666 m
= SCM_MUTEX_DATA (mx
);
668 if (m
->owner
!= cur_thread
)
670 if (m
->owner
== SCM_BOOL_F
)
671 SCM_MISC_ERROR ("mutex not locked", SCM_EOL
);
673 SCM_MISC_ERROR ("mutex not locked by this thread", SCM_EOL
);
675 else if (m
->level
> 0)
679 SCM next
= dequeue (m
->waiting
);
680 if (scm_is_true (next
))
683 unblock (SCM_THREAD_DATA (next
));
687 m
->owner
= SCM_BOOL_F
;
693 /*** Condition variables */
695 /* Like mutexes, we implement our own condition variables using the
699 /* yeah, we don't need a structure for this, but more things (like a
700 name) will likely follow... */
702 typedef struct scm_copt_cond
{
703 /* the threads waiting for this condition. */
710 scm_copt_cond
*c
= SCM_CONDVAR_DATA (cv
);
715 scm_make_condition_variable (void)
717 SCM cv
= scm_make_smob (scm_tc16_condvar
);
718 scm_copt_cond
*c
= SCM_CONDVAR_DATA (cv
);
719 c
->waiting
= make_queue ();
724 scm_timed_wait_condition_variable (SCM cv
, SCM mx
, SCM t
)
725 #define FUNC_NAME s_wait_condition_variable
728 scm_t_timespec waittime
;
731 SCM_ASSERT (SCM_CONDVARP (cv
),
734 s_wait_condition_variable
);
735 SCM_ASSERT (SCM_MUTEXP (mx
),
738 s_wait_condition_variable
);
743 SCM_VALIDATE_UINT_COPY (3, SCM_CAR(t
), waittime
.tv_sec
);
744 SCM_VALIDATE_UINT_COPY (3, SCM_CDR(t
), waittime
.tv_nsec
);
745 waittime
.tv_nsec
*= 1000;
749 SCM_VALIDATE_UINT_COPY (3, t
, waittime
.tv_sec
);
750 waittime
.tv_nsec
= 0;
754 c
= SCM_CONDVAR_DATA (cv
);
756 enqueue (c
->waiting
, cur_thread
);
757 scm_unlock_mutex (mx
);
764 res
= timed_block (&waittime
);
766 return scm_from_bool (res
);
771 scm_signal_condition_variable (SCM cv
)
772 #define FUNC_NAME s_signal_condition_variable
776 SCM_ASSERT (SCM_CONDVARP (cv
),
779 s_signal_condition_variable
);
780 c
= SCM_CONDVAR_DATA (cv
);
781 if (scm_is_true (th
= dequeue (c
->waiting
)))
782 unblock (SCM_THREAD_DATA (th
));
788 scm_broadcast_condition_variable (SCM cv
)
789 #define FUNC_NAME s_broadcast_condition_variable
793 SCM_ASSERT (SCM_CONDVARP (cv
),
796 s_signal_condition_variable
);
797 c
= SCM_CONDVAR_DATA (cv
);
798 while (scm_is_true (th
= dequeue (c
->waiting
)))
799 unblock (SCM_THREAD_DATA (th
));
804 /*** Initialization */
807 scm_threads_init (SCM_STACKITEM
*base
)
809 scm_tc16_thread
= scm_make_smob_type ("thread", 0);
810 scm_tc16_mutex
= scm_make_smob_type ("mutex", sizeof (scm_copt_mutex
));
811 scm_tc16_condvar
= scm_make_smob_type ("condition-variable",
812 sizeof (scm_copt_cond
));
814 scm_i_switch_counter
= SCM_I_THREAD_SWITCH_COUNT
;
816 fair_mutex_init (&guile_mutex
);
818 cur_thread
= make_thread (SCM_BOOL_F
);
819 enter_guile (SCM_THREAD_DATA (cur_thread
));
820 /* root is set later from init.c */
821 init_thread_creator (cur_thread
, pthread_self(), NULL
);
822 init_thread_creatant (cur_thread
, base
);
825 scm_gc_register_root (&all_threads
);
826 all_threads
= scm_cons (cur_thread
, SCM_EOL
);
828 scm_set_smob_mark (scm_tc16_thread
, thread_mark
);
829 scm_set_smob_print (scm_tc16_thread
, thread_print
);
830 scm_set_smob_free (scm_tc16_thread
, thread_free
);
832 scm_set_smob_mark (scm_tc16_mutex
, mutex_mark
);
834 scm_set_smob_mark (scm_tc16_condvar
, cond_mark
);
837 /*** Marking stacks */
839 /* XXX - what to do with this? Do we need to handle this for blocked
843 # define SCM_MARK_BACKING_STORE() do { \
845 SCM_STACKITEM * top, * bot; \
847 scm_mark_locations ((SCM_STACKITEM *) &ctx.uc_mcontext, \
848 ((size_t) (sizeof (SCM_STACKITEM) - 1 + sizeof ctx.uc_mcontext) \
849 / sizeof (SCM_STACKITEM))); \
850 bot = (SCM_STACKITEM *) __libc_ia64_register_backing_store_base; \
851 top = (SCM_STACKITEM *) ctx.uc_mcontext.sc_ar_bsp; \
852 scm_mark_locations (bot, top - bot); } while (0)
854 # define SCM_MARK_BACKING_STORE()
858 scm_threads_mark_stacks (void)
861 for (c
= all_threads
; !scm_is_null (c
); c
= SCM_CDR (c
))
863 scm_copt_thread
*t
= SCM_THREAD_DATA (SCM_CAR (c
));
866 /* Not fully initialized yet. */
872 /* stack_len is long rather than sizet in order to guarantee
873 that &stack_len is long aligned */
874 #if SCM_STACK_GROWS_UP
875 long stack_len
= ((SCM_STACKITEM
*) (&t
) -
876 (SCM_STACKITEM
*) thread
->base
);
878 /* Protect from the C stack. This must be the first marking
879 * done because it provides information about what objects
880 * are "in-use" by the C code. "in-use" objects are those
881 * for which the information about length and base address must
882 * remain usable. This requirement is stricter than a liveness
883 * requirement -- in particular, it constrains the implementation
886 SCM_FLUSH_REGISTER_WINDOWS
;
887 /* This assumes that all registers are saved into the jmp_buf */
888 setjmp (scm_save_regs_gc_mark
);
889 scm_mark_locations ((SCM_STACKITEM
*) scm_save_regs_gc_mark
,
890 ((size_t) sizeof scm_save_regs_gc_mark
891 / sizeof (SCM_STACKITEM
)));
893 scm_mark_locations (((size_t) t
->base
,
896 long stack_len
= ((SCM_STACKITEM
*) t
->base
-
897 (SCM_STACKITEM
*) (&t
));
899 /* Protect from the C stack. This must be the first marking
900 * done because it provides information about what objects
901 * are "in-use" by the C code. "in-use" objects are those
902 * for which the information about length and base address must
903 * remain usable. This requirement is stricter than a liveness
904 * requirement -- in particular, it constrains the implementation
907 SCM_FLUSH_REGISTER_WINDOWS
;
908 /* This assumes that all registers are saved into the jmp_buf */
909 setjmp (scm_save_regs_gc_mark
);
910 scm_mark_locations ((SCM_STACKITEM
*) scm_save_regs_gc_mark
,
911 ((size_t) sizeof scm_save_regs_gc_mark
912 / sizeof (SCM_STACKITEM
)));
914 scm_mark_locations ((SCM_STACKITEM
*) &t
,
920 /* Suspended thread */
921 #if SCM_STACK_GROWS_UP
922 long stack_len
= t
->top
- t
->base
;
923 scm_mark_locations (t
->base
, stack_len
);
925 long stack_len
= t
->base
- t
->top
;
926 scm_mark_locations (t
->top
, stack_len
);
928 scm_mark_locations ((SCM_STACKITEM
*) t
->regs
,
929 ((size_t) sizeof(t
->regs
)
930 / sizeof (SCM_STACKITEM
)));
938 scm_internal_select (int nfds
,
939 SELECT_TYPE
*readfds
,
940 SELECT_TYPE
*writefds
,
941 SELECT_TYPE
*exceptfds
,
942 struct timeval
*timeout
)
945 scm_copt_thread
*c
= leave_guile ();
946 res
= select (nfds
, readfds
, writefds
, exceptfds
, timeout
);
960 scm_thread_usleep (unsigned long usec
)
962 scm_copt_thread
*c
= leave_guile ();
969 scm_thread_sleep (unsigned long sec
)
972 scm_copt_thread
*c
= leave_guile ();
981 scm_current_thread (void)
987 scm_all_threads (void)
993 scm_i_thread_root (SCM thread
)
995 if (thread
== cur_thread
)
996 return scm_i_copt_thread_data
;
998 return ((scm_copt_thread
*)SCM_THREAD_DATA (thread
))->root
;
1002 scm_join_thread (SCM thread
)
1003 #define FUNC_NAME s_join_thread
1008 SCM_VALIDATE_THREAD (1, thread
);
1010 t
= SCM_THREAD_DATA (thread
);
1011 if (t
->pthread
!= -1)
1013 scm_copt_thread
*c
= leave_guile ();
1014 pthread_join (t
->pthread
, NULL
);
1018 t
->result
= SCM_BOOL_F
;
1024 scm_c_thread_exited_p (SCM thread
)
1025 #define FUNC_NAME s_scm_thread_exited_p
1028 SCM_VALIDATE_THREAD (1, thread
);
1029 t
= SCM_THREAD_DATA (thread
);
1030 return t
->pthread
== -1;