summaryrefslogtreecommitdiff
path: root/libguile
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2008-09-10 22:51:46 +0200
committerLudovic Courtès <ludo@gnu.org>2008-09-10 22:51:46 +0200
commite0513d4d77a7dbf42252a5dddfee62c46a700b9c (patch)
tree09066826f011a3f4fb6aec31e577773af1f85334 /libguile
parent6774820f1e83a388b3232cd61a66340886b395d8 (diff)
parent2e77f7202b11ad0003831fcff94ec7db80cca015 (diff)
downloadguile-e0513d4d77a7dbf42252a5dddfee62c46a700b9c.tar.gz
Merge commit '2e77f7202b11ad0003831fcff94ec7db80cca015' into boehm-demers-weiser-gc
Conflicts: libguile/threads.c
Diffstat (limited to 'libguile')
-rw-r--r--libguile/ChangeLog64
-rw-r--r--libguile/gen-scmconfig.c5
-rw-r--r--libguile/gen-scmconfig.h.in1
-rw-r--r--libguile/i18n.c8
-rw-r--r--libguile/null-threads.h3
-rw-r--r--libguile/pthread-threads.h9
-rw-r--r--libguile/read.c7
-rw-r--r--libguile/scmsigs.c50
-rw-r--r--libguile/scmsigs.h8
-rw-r--r--libguile/threads.c133
-rw-r--r--libguile/threads.h9
11 files changed, 268 insertions, 29 deletions
diff --git a/libguile/ChangeLog b/libguile/ChangeLog
index f3dd1c5f7..691159b52 100644
--- a/libguile/ChangeLog
+++ b/libguile/ChangeLog
@@ -1,3 +1,67 @@
+2007-10-20 Julian Graham <joolean@gmail.com>
+
+ Add support for thread cancellation and user-defined thread
+ cleanup handlers. Small rework by Ludovic Courtès.
+
+ * null-threads.h (scm_i_pthread_cancel,
+ scm_i_pthread_cleanup_push, scm_i_pthread_cleanup_pop): New.
+ * pthread-threads.h (scm_i_pthread_cancel,
+ scm_i_pthread_cleanup_push, scm_i_pthread_cleanup_pop): New.
+ * scmsigs.c (scm_i_signal_delivery_thread,
+ signal_delivery_thread_mutex): New.
+ (signal_delivery_thread): Leave when `read_without_guile ()'
+ returns zero.
+ (start_signal_delivery_thread): Acquire SIGNAL_DELIVERY_THREAD
+ before spawning the thread. Initialize
+ SCM_I_SIGNAL_DELIVERY_THREAD.
+ (ensure_signal_delivery_thread): Renamed to...
+ (scm_i_ensure_signal_delivery_thread): this.
+ (scm_i_close_signal_pipe): New.
+ * scmsigs.h: Updated.
+ * threads.c (thread_mark): Mark `t->cleanup_handler'.
+ (guilify_self_1): Initialize `t->cleanup_handler' and
+ `t->canceled'.
+ (do_thread_exit): Invoke `t->cleanup_handler'.
+ (on_thread_exit): Call `scm_i_ensure_signal_delivery_thread ()'.
+ Call `scm_i_close_signal_pipe ()' when the next-to-last thread
+ vanishes.
+ (scm_leave_guile_cleanup): New.
+ (scm_i_with_guile_and_parent): Use `scm_i_pthread_cleanup_push ()'
+ and `scm_leave_guile_cleanup ()' to leave guile mode, rather
+ than call `scm_leave_guile ()' after FUNC.
+ (scm_cancel_thread, scm_set_thread_cleanup_x,
+ scm_threads_cleanup): New.
+ (scm_all_threads): Remove SCM_I_SIGNAL_DELIVERY_THREAD from the
+ returned list.
+ * threads.h (scm_i_thread)[cleanup_handler, canceled]: New
+ fields.
+ Add declarations of new functions.
+
+2007-10-17 Ludovic Courtès <ludo@gnu.org>
+
+ * read.c (CHAR_IS_BLANK_): Add `\r' (ASCII 0x0d). This fixes a
+ regression compared to 1.8.2. Reported by Puneet
+ <schemer@gmail.com>.
+
+2007-10-10 Ludovic Courtès <ludo@gnu.org>
+
+ * pthread-threads.h (SCM_I_PTHREAD_MUTEX_INITIALIZER): Check
+ `SCM_NEED_BRACES_ON_PTHREAD_MUTEX_INITIALIZER'.
+ * gen-scmconfig.h.in
+ (SCM_I_GSC_NEED_BRACES_ON_PTHREAD_MUTEX_INITIALIZER): New.
+ * gen-scmconfig.c (main): Define
+ `SCM_NEED_BRACES_ON_PTHREAD_MUTEX_INITIALIZER'.
+
+2007-10-04 Ludovic Courtès <ludo@gnu.org>
+
+ * i18n.c (scm_make_locale)[!USE_GNU_LOCALE_API]: Don't call
+ `leave_locale_section ()' on failure of
+ `enter_locale_section ()' since the mutex is not held and locale
+ settings are unchanged.
+ (scm_nl_langinfo)[!USE_GNU_LOCALE_API]: Use
+ `restore_locale_settings ()' instead of `leave_locale_section ()'
+ since the mutex is not held.
+
2007-10-02 Ludovic Courtès <ludo@gnu.org>
* threads.c (on_thread_exit): Don't call `scm_leave_guile ()'
diff --git a/libguile/gen-scmconfig.c b/libguile/gen-scmconfig.c
index 43a2a989d..6afa72fcc 100644
--- a/libguile/gen-scmconfig.c
+++ b/libguile/gen-scmconfig.c
@@ -382,6 +382,11 @@ main (int argc, char *argv[])
pf ("#define SCM_NEED_BRACES_ON_PTHREAD_ONCE_INIT %d /* 0 or 1 */\n",
SCM_I_GSC_NEED_BRACES_ON_PTHREAD_ONCE_INIT);
+ pf ("/* Define to 1 if need braces around PTHREAD_MUTEX_INITIALIZER\n"
+ " (for IRIX with GCC) */\n");
+ pf ("#define SCM_NEED_BRACES_ON_PTHREAD_MUTEX_INITIALIZER %d /* 0 or 1 */\n",
+ SCM_I_GSC_NEED_BRACES_ON_PTHREAD_MUTEX_INITIALIZER);
+
#if USE_DLL_IMPORT
pf ("\n");
pf ("/* Define some additional CPP macros on Win32 platforms. */\n");
diff --git a/libguile/gen-scmconfig.h.in b/libguile/gen-scmconfig.h.in
index b4e0561f1..cdc59b047 100644
--- a/libguile/gen-scmconfig.h.in
+++ b/libguile/gen-scmconfig.h.in
@@ -29,6 +29,7 @@
#define SCM_I_GSC_USE_PTHREAD_THREADS @SCM_I_GSC_USE_PTHREAD_THREADS@
#define SCM_I_GSC_USE_NULL_THREADS @SCM_I_GSC_USE_NULL_THREADS@
#define SCM_I_GSC_NEED_BRACES_ON_PTHREAD_ONCE_INIT @SCM_I_GSC_NEED_BRACES_ON_PTHREAD_ONCE_INIT@
+#define SCM_I_GSC_NEED_BRACES_ON_PTHREAD_MUTEX_INITIALIZER @SCM_I_GSC_NEED_BRACES_ON_PTHREAD_MUTEX_INITIALIZER@
/*
Local Variables:
diff --git a/libguile/i18n.c b/libguile/i18n.c
index 88652efd2..43381f4ed 100644
--- a/libguile/i18n.c
+++ b/libguile/i18n.c
@@ -685,12 +685,14 @@ SCM_DEFINE (scm_make_locale, "make-locale", 2, 1, 0,
scm_t_locale_settings prev_locale;
err = enter_locale_section (c_locale, &prev_locale);
- leave_locale_section (&prev_locale);
if (err)
goto fail;
else
- SCM_NEWSMOB (locale, scm_tc16_locale_smob_type, c_locale);
+ {
+ leave_locale_section (&prev_locale);
+ SCM_NEWSMOB (locale, scm_tc16_locale_smob_type, c_locale);
+ }
}
#endif
@@ -1410,7 +1412,7 @@ SCM_DEFINE (scm_nl_langinfo, "nl-langinfo", 1, 1, 0,
{
c_result = nl_langinfo (c_item);
- leave_locale_section (&lsec_prev_locale);
+ restore_locale_settings (&lsec_prev_locale);
free_locale_settings (&lsec_prev_locale);
}
#endif
diff --git a/libguile/null-threads.h b/libguile/null-threads.h
index 233b8139d..5a61dbf50 100644
--- a/libguile/null-threads.h
+++ b/libguile/null-threads.h
@@ -41,6 +41,9 @@
#define scm_i_pthread_create(t,a,f,d) (*(t)=0, (void)(f), ENOSYS)
#define scm_i_pthread_detach(t) do { } while (0)
#define scm_i_pthread_exit(v) exit(0)
+#define scm_i_pthread_cancel(t) 0
+#define scm_i_pthread_cleanup_push(t,v) 0
+#define scm_i_pthread_cleanup_pop(e) 0
#define scm_i_sched_yield() 0
/* Signals
diff --git a/libguile/pthread-threads.h b/libguile/pthread-threads.h
index 5f652252a..bd6d4854d 100644
--- a/libguile/pthread-threads.h
+++ b/libguile/pthread-threads.h
@@ -38,6 +38,9 @@
#define scm_i_pthread_create pthread_create
#define scm_i_pthread_detach pthread_detach
#define scm_i_pthread_exit pthread_exit
+#define scm_i_pthread_cancel pthread_cancel
+#define scm_i_pthread_cleanup_push pthread_cleanup_push
+#define scm_i_pthread_cleanup_pop pthread_cleanup_pop
#define scm_i_sched_yield sched_yield
/* Signals
@@ -46,7 +49,11 @@
/* Mutexes
*/
-#define SCM_I_PTHREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#if SCM_NEED_BRACES_ON_PTHREAD_MUTEX_INITIALIZER
+# define SCM_I_PTHREAD_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
+#else
+# define SCM_I_PTHREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#endif
#define scm_i_pthread_mutex_t pthread_mutex_t
#define scm_i_pthread_mutex_init pthread_mutex_init
#define scm_i_pthread_mutex_destroy pthread_mutex_destroy
diff --git a/libguile/read.c b/libguile/read.c
index d1013c586..53715f2b5 100644
--- a/libguile/read.c
+++ b/libguile/read.c
@@ -150,7 +150,7 @@ static SCM *scm_read_hash_procedures;
/* `isblank' is only in C99. */
#define CHAR_IS_BLANK_(_chr) \
(((_chr) == ' ') || ((_chr) == '\t') || ((_chr) == '\n') \
- || ((_chr) == '\f'))
+ || ((_chr) == '\f') || ((_chr) == '\r'))
#ifdef MSDOS
# define CHAR_IS_BLANK(_chr) \
@@ -182,9 +182,8 @@ static SCM *scm_read_hash_procedures;
/* Read an SCSH block comment. */
static inline SCM scm_read_scsh_block_comment (int chr, SCM port);
-/* Helper function similar to `scm_read_token ()'. Read from PORT until a
- whitespace is read. Return zero if the whole token could fit in BUF,
- non-zero otherwise. */
+/* Read from PORT until a delimiter (e.g., a whitespace) is read. Return
+ zero if the whole token fits in BUF, non-zero otherwise. */
static inline int
read_token (SCM port, char *buf, size_t buf_size, size_t *read)
{
diff --git a/libguile/scmsigs.c b/libguile/scmsigs.c
index 989ddcab1..d05bdac67 100644
--- a/libguile/scmsigs.c
+++ b/libguile/scmsigs.c
@@ -33,6 +33,7 @@
#include "libguile/eval.h"
#include "libguile/root.h"
#include "libguile/vectors.h"
+#include "libguile/threads.h"
#include "libguile/validate.h"
#include "libguile/scmsigs.h"
@@ -99,6 +100,14 @@ static SCM *signal_handlers;
static SCM signal_handler_asyncs;
static SCM signal_handler_threads;
+/* The signal delivery thread. */
+scm_i_thread *scm_i_signal_delivery_thread = NULL;
+
+/* The mutex held when launching the signal delivery thread. */
+static scm_i_pthread_mutex_t signal_delivery_thread_mutex =
+ SCM_I_PTHREAD_MUTEX_INITIALIZER;
+
+
/* saves the original C handlers, when a new handler is installed.
set to SIG_ERR if the original handler is installed. */
#ifdef HAVE_SIGACTION
@@ -185,24 +194,34 @@ signal_delivery_thread (void *data)
if (scm_is_true (h))
scm_system_async_mark_for_thread (h, t);
}
+ else if (n == 0)
+ break; /* the signal pipe was closed. */
else if (n < 0 && errno != EINTR)
perror ("error in signal delivery thread");
}
- return SCM_UNSPECIFIED; /* not reached */
+ return SCM_UNSPECIFIED; /* not reached unless all other threads exited */
}
static void
start_signal_delivery_thread (void)
{
+ SCM signal_thread;
+
+ scm_i_pthread_mutex_lock (&signal_delivery_thread_mutex);
+
if (pipe (signal_pipe) != 0)
scm_syserror (NULL);
- scm_spawn_thread (signal_delivery_thread, NULL,
- scm_handle_by_message, "signal delivery thread");
+ signal_thread = scm_spawn_thread (signal_delivery_thread, NULL,
+ scm_handle_by_message,
+ "signal delivery thread");
+ scm_i_signal_delivery_thread = SCM_I_THREAD_DATA (signal_thread);
+
+ scm_i_pthread_mutex_unlock (&signal_delivery_thread_mutex);
}
-static void
-ensure_signal_delivery_thread ()
+void
+scm_i_ensure_signal_delivery_thread ()
{
static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT;
scm_i_pthread_once (&once, start_signal_delivery_thread);
@@ -228,8 +247,8 @@ take_signal (int signum)
#endif
}
-static void
-ensure_signal_delivery_thread ()
+void
+scm_i_ensure_signal_delivery_thread ()
{
return;
}
@@ -332,7 +351,7 @@ SCM_DEFINE (scm_sigaction_for_thread, "sigaction", 1, 3, 0,
SCM_MISC_ERROR ("thread has already exited", SCM_EOL);
}
- ensure_signal_delivery_thread ();
+ scm_i_ensure_signal_delivery_thread ();
SCM_CRITICAL_SECTION_START;
old_handler = SCM_SIMPLE_VECTOR_REF (*signal_handlers, csig);
@@ -653,6 +672,21 @@ SCM_DEFINE (scm_raise, "raise", 1, 0, 0,
void
+scm_i_close_signal_pipe()
+{
+ /* SIGNAL_DELIVERY_THREAD_MUTEX is only locked while the signal delivery
+ thread is being launched. The thread that calls this function is
+ already holding the thread admin mutex, so if the delivery thread hasn't
+ been launched at this point, it never will be before shutdown. */
+ scm_i_pthread_mutex_lock (&signal_delivery_thread_mutex);
+
+ if (scm_i_signal_delivery_thread != NULL)
+ close (signal_pipe[1]);
+
+ scm_i_pthread_mutex_unlock (&signal_delivery_thread_mutex);
+}
+
+void
scm_init_scmsigs ()
{
int i;
diff --git a/libguile/scmsigs.h b/libguile/scmsigs.h
index 54742de14..2aced3a3c 100644
--- a/libguile/scmsigs.h
+++ b/libguile/scmsigs.h
@@ -3,7 +3,7 @@
#ifndef SCM_SCMSIGS_H
#define SCM_SCMSIGS_H
-/* Copyright (C) 1995,1996,1997,1998,2000, 2002, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,2000, 2002, 2006, 2007 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,6 +23,7 @@
#include "libguile/__scm.h"
+#include "libguile/threads.h"
@@ -41,6 +42,11 @@ SCM_API SCM scm_usleep (SCM i);
SCM_API SCM scm_raise (SCM sig);
SCM_API void scm_init_scmsigs (void);
+SCM_API void scm_i_close_signal_pipe (void);
+SCM_API void scm_i_ensure_signal_delivery_thread (void);
+
+SCM_API scm_i_thread *scm_i_signal_delivery_thread;
+
#endif /* SCM_SCMSIGS_H */
/*
diff --git a/libguile/threads.c b/libguile/threads.c
index 77dcbb37a..c1b681a9e 100644
--- a/libguile/threads.c
+++ b/libguile/threads.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995,1996,1997,1998,2000,2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,2000,2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -49,6 +49,7 @@
#include "libguile/continuations.h"
#include "libguile/gc.h"
#include "libguile/init.h"
+#include "libguile/scmsigs.h"
#ifdef __MINGW32__
#ifndef ETIMEDOUT
@@ -405,6 +406,7 @@ guilify_self_1 (SCM_STACKITEM *base)
t->pthread = scm_i_pthread_self ();
t->handle = SCM_BOOL_F;
t->result = SCM_BOOL_F;
+ t->cleanup_handler = SCM_BOOL_F;
t->join_queue = SCM_EOL;
t->dynamic_state = SCM_BOOL_F;
t->dynwinds = SCM_EOL;
@@ -426,6 +428,7 @@ guilify_self_1 (SCM_STACKITEM *base)
t->gc_running_p = 0;
t->current_mark_stack_ptr = NULL;
t->current_mark_stack_limit = NULL;
+ t->canceled = 0;
t->exited = 0;
t->freelist = SCM_EOL;
@@ -470,7 +473,17 @@ guilify_self_2 (SCM parent)
static void *
do_thread_exit (void *v)
{
- scm_i_thread *t = (scm_i_thread *)v;
+ scm_i_thread *t = (scm_i_thread *) v;
+
+ if (!scm_is_false (t->cleanup_handler))
+ {
+ SCM ptr = t->cleanup_handler;
+
+ t->cleanup_handler = SCM_BOOL_F;
+ t->result = scm_internal_catch (SCM_BOOL_T,
+ (scm_t_catch_body) scm_call_0, ptr,
+ scm_handle_by_message_noexit, NULL);
+ }
scm_i_scm_pthread_mutex_lock (&thread_admin_mutex);
@@ -481,6 +494,7 @@ do_thread_exit (void *v)
;
scm_i_pthread_mutex_unlock (&thread_admin_mutex);
+
return NULL;
}
@@ -488,10 +502,14 @@ static void
on_thread_exit (void *v)
{
/* This handler is executed in non-guile mode. */
- scm_i_thread *t = (scm_i_thread *)v, **tp;
+ scm_i_thread *t = (scm_i_thread *) v, **tp;
scm_i_pthread_setspecific (scm_i_thread_key, v);
+ /* Ensure the signal handling thread has been launched, because we might be
+ shutting it down. */
+ scm_i_ensure_signal_delivery_thread ();
+
/* Unblocking the joining threads needs to happen in guile mode
since the queue is a SCM data structure. */
scm_with_guile (do_thread_exit, v);
@@ -507,6 +525,14 @@ on_thread_exit (void *v)
break;
}
thread_count--;
+
+ /* If there's only one other thread, it could be the signal delivery
+ thread, so we need to notify it to shut down by closing its read pipe.
+ If it's not the signal delivery thread, then closing the read pipe isn't
+ going to hurt. */
+ if (thread_count <= 1)
+ scm_i_close_signal_pipe ();
+
scm_i_pthread_mutex_unlock (&thread_admin_mutex);
scm_i_pthread_setspecific (scm_i_thread_key, NULL);
@@ -676,17 +702,30 @@ scm_with_guile (void *(*func)(void *), void *data)
scm_i_default_dynamic_state);
}
+static void
+scm_leave_guile_cleanup (void *x)
+{
+ scm_leave_guile ();
+}
+
void *
-scm_i_with_guile_and_parent (void *(*func)(void *), void *data,
- SCM parent)
+scm_i_with_guile_and_parent (void *(*func)(void *), void *data, SCM parent)
{
void *res;
int really_entered;
SCM_STACKITEM base_item;
+
really_entered = scm_i_init_thread_for_guile (&base_item, parent);
- res = scm_c_with_continuation_barrier (func, data);
if (really_entered)
- scm_leave_guile ();
+ {
+ scm_i_pthread_cleanup_push (scm_leave_guile_cleanup, NULL);
+ res = scm_c_with_continuation_barrier (func, data);
+ scm_i_pthread_cleanup_pop (0);
+ scm_leave_guile ();
+ }
+ else
+ res = scm_c_with_continuation_barrier (func, data);
+
return res;
}
@@ -872,6 +911,74 @@ SCM_DEFINE (scm_yield, "yield", 0, 0, 0,
}
#undef FUNC_NAME
+SCM_DEFINE (scm_cancel_thread, "cancel-thread", 1, 0, 0,
+ (SCM thread),
+"Asynchronously force the target @var{thread} to terminate. @var{thread} "
+"cannot be the current thread, and if @var{thread} has already terminated or "
+"been signaled to terminate, this function is a no-op.")
+#define FUNC_NAME s_scm_cancel_thread
+{
+ scm_i_thread *t = NULL;
+
+ SCM_VALIDATE_THREAD (1, thread);
+ t = SCM_I_THREAD_DATA (thread);
+ scm_i_scm_pthread_mutex_lock (&thread_admin_mutex);
+ if (!t->canceled)
+ {
+ t->canceled = 1;
+ scm_i_pthread_mutex_unlock (&thread_admin_mutex);
+ scm_i_pthread_cancel (t->pthread);
+ }
+ else
+ scm_i_pthread_mutex_unlock (&thread_admin_mutex);
+
+ return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_set_thread_cleanup_x, "set-thread-cleanup!", 2, 0, 0,
+ (SCM thread, SCM proc),
+"Set the thunk @var{proc} as the cleanup handler for the thread @var{thread}. "
+"This handler will be called when the thread exits.")
+#define FUNC_NAME s_scm_set_thread_cleanup_x
+{
+ scm_i_thread *t;
+
+ SCM_VALIDATE_THREAD (1, thread);
+ if (!scm_is_false (proc))
+ SCM_VALIDATE_THUNK (2, proc);
+
+ scm_i_pthread_mutex_lock (&thread_admin_mutex);
+
+ t = SCM_I_THREAD_DATA (thread);
+ if (!(t->exited || t->canceled))
+ t->cleanup_handler = proc;
+
+ scm_i_pthread_mutex_unlock (&thread_admin_mutex);
+
+ return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_thread_cleanup, "thread-cleanup", 1, 0, 0,
+ (SCM thread),
+"Return the cleanup handler installed for the thread @var{thread}.")
+#define FUNC_NAME s_scm_thread_cleanup
+{
+ scm_i_thread *t;
+ SCM ret;
+
+ SCM_VALIDATE_THREAD (1, thread);
+
+ scm_i_pthread_mutex_lock (&thread_admin_mutex);
+ t = SCM_I_THREAD_DATA (thread);
+ ret = (t->exited || t->canceled) ? SCM_BOOL_F : t->cleanup_handler;
+ scm_i_pthread_mutex_unlock (&thread_admin_mutex);
+
+ return ret;
+}
+#undef FUNC_NAME
+
SCM_DEFINE (scm_join_thread, "join-thread", 1, 0, 0,
(SCM thread),
"Suspend execution of the calling thread until the target @var{thread} "
@@ -883,7 +990,7 @@ SCM_DEFINE (scm_join_thread, "join-thread", 1, 0, 0,
SCM_VALIDATE_THREAD (1, thread);
if (scm_is_eq (scm_current_thread (), thread))
- SCM_MISC_ERROR ("can not join the current thread", SCM_EOL);
+ SCM_MISC_ERROR ("cannot join the current thread", SCM_EOL);
scm_i_scm_pthread_mutex_lock (&thread_admin_mutex);
@@ -903,10 +1010,13 @@ SCM_DEFINE (scm_join_thread, "join-thread", 1, 0, 0,
res = t->result;
scm_i_pthread_mutex_unlock (&thread_admin_mutex);
+
return res;
}
#undef FUNC_NAME
+
+
/*** Fat mutexes */
/* We implement our own mutex type since we want them to be 'fair', we
@@ -1492,8 +1602,11 @@ SCM_DEFINE (scm_all_threads, "all-threads", 0, 0, 0,
l = &list;
for (t = all_threads; t && n > 0; t = t->next_thread)
{
- SCM_SETCAR (*l, t->handle);
- l = SCM_CDRLOC (*l);
+ if (t != scm_i_signal_delivery_thread)
+ {
+ SCM_SETCAR (*l, t->handle);
+ l = SCM_CDRLOC (*l);
+ }
n--;
}
*l = SCM_EOL;
diff --git a/libguile/threads.h b/libguile/threads.h
index dced696ea..834f38525 100644
--- a/libguile/threads.h
+++ b/libguile/threads.h
@@ -3,7 +3,7 @@
#ifndef SCM_THREADS_H
#define SCM_THREADS_H
-/* Copyright (C) 1996,1997,1998,2000,2001, 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 1996,1997,1998,2000,2001, 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -49,9 +49,11 @@ typedef struct scm_i_thread {
SCM handle;
scm_i_pthread_t pthread;
-
+
+ SCM cleanup_handler;
SCM join_queue;
SCM result;
+ int canceled;
int exited;
SCM sleep_object;
@@ -158,6 +160,9 @@ do { \
SCM_API SCM scm_call_with_new_thread (SCM thunk, SCM handler);
SCM_API SCM scm_yield (void);
+SCM_API SCM scm_cancel_thread (SCM t);
+SCM_API SCM scm_set_thread_cleanup_x (SCM thread, SCM proc);
+SCM_API SCM scm_thread_cleanup (SCM thread);
SCM_API SCM scm_join_thread (SCM t);
SCM_API SCM scm_make_mutex (void);