summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libguile/threads.c95
-rw-r--r--libguile/threads.h3
2 files changed, 36 insertions, 62 deletions
diff --git a/libguile/threads.c b/libguile/threads.c
index 05ea1e774..5d1390941 100644
--- a/libguile/threads.c
+++ b/libguile/threads.c
@@ -119,7 +119,6 @@ thread_mark (SCM obj)
scm_gc_mark (t->join_queue);
scm_gc_mark (t->dynwinds);
scm_gc_mark (t->active_asyncs);
- scm_gc_mark (t->signal_asyncs);
scm_gc_mark (t->continuation_root);
return t->dynamic_state;
}
@@ -287,16 +286,17 @@ guilify_self_1 (SCM_STACKITEM *base)
t->dynamic_state = SCM_BOOL_F;
t->dynwinds = SCM_EOL;
t->active_asyncs = SCM_EOL;
- t->signal_asyncs = SCM_EOL;
t->block_asyncs = 1;
t->pending_asyncs = 1;
t->last_debug_frame = NULL;
t->base = base;
+ t->continuation_root = SCM_EOL;
t->continuation_base = base;
scm_i_pthread_cond_init (&t->sleep_cond, NULL);
t->sleep_mutex = NULL;
t->sleep_object = SCM_BOOL_F;
t->sleep_fd = -1;
+ /* XXX - check for errors. */
pipe (t->sleep_pipe);
scm_i_pthread_mutex_init (&t->heap_mutex, NULL);
t->clear_freelists_p = 0;
@@ -344,21 +344,15 @@ guilify_self_2 (SCM parent)
static void *
do_thread_exit (void *v)
{
- scm_i_thread *t = (scm_i_thread *)v, **tp;
+ scm_i_thread *t = (scm_i_thread *)v;
scm_i_scm_pthread_mutex_lock (&thread_admin_mutex);
t->exited = 1;
+ close (t->sleep_pipe[0]);
+ close (t->sleep_pipe[1]);
while (scm_is_true (unblock_from_queue (t->join_queue)))
;
-
- for (tp = &all_threads; *tp; tp = &(*tp)->next_thread)
- if (*tp == t)
- {
- *tp = t->next_thread;
- break;
- }
- thread_count--;
scm_i_pthread_mutex_unlock (&thread_admin_mutex);
return NULL;
@@ -367,8 +361,30 @@ do_thread_exit (void *v)
static void
on_thread_exit (void *v)
{
+ scm_i_thread *t = (scm_i_thread *)v, **tp;
+
scm_i_pthread_setspecific (scm_i_thread_key, v);
+
+ /* 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);
+
+ /* Removing ourself from the list of all threads needs to happen in
+ non-guile mode since all SCM values on our stack become
+ unprotected once we are no longer in the list.
+ */
+ scm_leave_guile ();
+ scm_i_pthread_mutex_lock (&thread_admin_mutex);
+ for (tp = &all_threads; *tp; tp = &(*tp)->next_thread)
+ if (*tp == t)
+ {
+ *tp = t->next_thread;
+ break;
+ }
+ thread_count--;
+ scm_i_pthread_mutex_unlock (&thread_admin_mutex);
+
scm_i_pthread_setspecific (scm_i_thread_key, NULL);
}
@@ -1406,7 +1422,6 @@ scm_c_thread_exited_p (SCM thread)
static scm_i_pthread_cond_t wake_up_cond;
int scm_i_thread_go_to_sleep;
static int threads_initialized_p = 0;
-static int sleep_level = 0;
void
scm_i_thread_put_to_sleep ()
@@ -1418,25 +1433,12 @@ scm_i_thread_put_to_sleep ()
scm_leave_guile ();
scm_i_pthread_mutex_lock (&thread_admin_mutex);
- if (sleep_level == 0)
- {
- /* Signal all threads to go to sleep
- */
- scm_i_thread_go_to_sleep = 1;
- for (t = all_threads; t; t = t->next_thread)
- scm_i_pthread_mutex_lock (&t->heap_mutex);
- scm_i_thread_go_to_sleep = 0;
- }
- else
- {
- /* We are already single threaded. Suspend again to update
- the recorded stack information.
- */
- suspend ();
- }
- sleep_level += 1;
-
- scm_i_pthread_mutex_unlock (&thread_admin_mutex);
+ /* Signal all threads to go to sleep
+ */
+ scm_i_thread_go_to_sleep = 1;
+ for (t = all_threads; t; t = t->next_thread)
+ scm_i_pthread_mutex_lock (&t->heap_mutex);
+ scm_i_thread_go_to_sleep = 0;
}
}
@@ -1457,16 +1459,10 @@ scm_i_thread_wake_up ()
if (threads_initialized_p)
{
scm_i_thread *t;
- scm_i_pthread_mutex_lock (&thread_admin_mutex);
-
- sleep_level -= 1;
- if (sleep_level == 0)
- {
- scm_i_pthread_cond_broadcast (&wake_up_cond);
- for (t = all_threads; t; t = t->next_thread)
- scm_i_pthread_mutex_unlock (&t->heap_mutex);
- }
+ scm_i_pthread_cond_broadcast (&wake_up_cond);
+ for (t = all_threads; t; t = t->next_thread)
+ scm_i_pthread_mutex_unlock (&t->heap_mutex);
scm_i_pthread_mutex_unlock (&thread_admin_mutex);
scm_enter_guile ((scm_t_guile_ticket) SCM_I_CURRENT_THREAD);
}
@@ -1480,25 +1476,6 @@ scm_i_thread_sleep_for_gc ()
resume (t);
}
-static void
-put_to_sleep (void *unused)
-{
- scm_i_thread_put_to_sleep ();
-}
-
-static void
-wake_up (void *unused)
-{
- scm_i_thread_wake_up ();
-}
-
-void
-scm_i_frame_single_threaded ()
-{
- scm_frame_rewind_handler (put_to_sleep, NULL, SCM_F_WIND_EXPLICITLY);
- scm_frame_unwind_handler (wake_up, NULL, SCM_F_WIND_EXPLICITLY);
-}
-
/* This mutex is used by SCM_CRITICAL_SECTION_START/END.
*/
scm_i_pthread_mutex_t scm_i_critical_section_mutex =
diff --git a/libguile/threads.h b/libguile/threads.h
index 8dda68f06..3e16fbbcd 100644
--- a/libguile/threads.h
+++ b/libguile/threads.h
@@ -80,8 +80,6 @@ typedef struct scm_i_thread {
*/
SCM active_asyncs; /* The thunks to be run at the next
safe point */
- SCM signal_asyncs; /* The pre-queued cells for signal handlers.
- */
unsigned int block_asyncs; /* Non-zero means that asyncs should
not be run. */
unsigned int pending_asyncs; /* Non-zero means that asyncs might be pending.
@@ -139,7 +137,6 @@ void scm_i_thread_put_to_sleep (void);
void scm_i_thread_wake_up (void);
void scm_i_thread_invalidate_freelists (void);
void scm_i_thread_sleep_for_gc (void);
-SCM_API void scm_i_frame_single_threaded (void);
void scm_threads_prehistory (SCM_STACKITEM *);
void scm_threads_init_first_thread (void);