summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius Vollmer <mvo@zagadka.de>2004-08-19 17:16:01 +0000
committerMarius Vollmer <mvo@zagadka.de>2004-08-19 17:16:01 +0000
commit6087fad9c7263be996e8cb91cb300a20280048be (patch)
tree6c6e1d01e6a818a14ef69b82943e91e2289c3adb
parent3ee86942a7cc519ef1c6f6a9868a5136f85558bc (diff)
downloadguile-6087fad9c7263be996e8cb91cb300a20280048be.tar.gz
(gc_section_count): Removed, thread-sleeping can not
be nested. (scm_i_thread_put_to_sleep): Call scm_i_leave_guile before locking admin mutex so that we can be put to sleep by other threads while blocking on that mutex. Lock all the heap mutex of all threads, including ourselves. (scm_i_thread_wake_up): Unlock all threads, including ourselves, call scm_i_enter_guile. (scm_thread_mark_stacks): Expect all threads to be suspended.
-rw-r--r--libguile/threads.c99
1 files changed, 29 insertions, 70 deletions
diff --git a/libguile/threads.c b/libguile/threads.c
index 25f06d6d4..d32156eb2 100644
--- a/libguile/threads.c
+++ b/libguile/threads.c
@@ -937,6 +937,7 @@ void
scm_threads_mark_stacks (void)
{
volatile SCM c;
+
for (c = all_threads; !SCM_NULLP (c); c = SCM_CDR (c))
{
scm_thread *t = SCM_THREAD_DATA (SCM_CAR (c));
@@ -945,70 +946,24 @@ scm_threads_mark_stacks (void)
/* Not fully initialized yet. */
continue;
}
+
if (t->top == NULL)
{
- long stack_len;
-#ifdef SCM_DEBUG
- if (t->thread != scm_thread_self ())
- abort ();
-#endif
- /* Active thread */
- /* stack_len is long rather than size_t in order to guarantee
- that &stack_len is long aligned */
-#if SCM_STACK_GROWS_UP
- stack_len = SCM_STACK_PTR (&t) - t->base;
-
- /* Protect from the C stack. This must be the first marking
- * done because it provides information about what objects
- * are "in-use" by the C code. "in-use" objects are those
- * for which the information about length and base address must
- * remain usable. This requirement is stricter than a liveness
- * requirement -- in particular, it constrains the implementation
- * of scm_resizuve.
+ /* Thread has not been suspended, which should never happen.
*/
- SCM_FLUSH_REGISTER_WINDOWS;
- /* This assumes that all registers are saved into the jmp_buf */
- setjmp (scm_save_regs_gc_mark);
- scm_mark_locations ((SCM_STACKITEM *) scm_save_regs_gc_mark,
- ((size_t) sizeof scm_save_regs_gc_mark
- / sizeof (SCM_STACKITEM)));
-
- scm_mark_locations (t->base, (size_t) stack_len);
-#else
- stack_len = t->base - SCM_STACK_PTR (&t);
-
- /* Protect from the C stack. This must be the first marking
- * done because it provides information about what objects
- * are "in-use" by the C code. "in-use" objects are those
- * for which the information about length and base address must
- * remain usable. This requirement is stricter than a liveness
- * requirement -- in particular, it constrains the implementation
- * of scm_resizuve.
- */
- SCM_FLUSH_REGISTER_WINDOWS;
- /* This assumes that all registers are saved into the jmp_buf */
- setjmp (scm_save_regs_gc_mark);
- scm_mark_locations ((SCM_STACKITEM *) scm_save_regs_gc_mark,
- ((size_t) sizeof scm_save_regs_gc_mark
- / sizeof (SCM_STACKITEM)));
-
- scm_mark_locations (SCM_STACK_PTR (&t), stack_len);
-#endif
+ abort ();
}
- else
- {
- /* Suspended thread */
+
#if SCM_STACK_GROWS_UP
- long stack_len = t->top - t->base;
- scm_mark_locations (t->base, stack_len);
+ long stack_len = t->top - t->base;
+ scm_mark_locations (t->base, stack_len);
#else
- long stack_len = t->base - t->top;
- scm_mark_locations (t->top, stack_len);
+ long stack_len = t->base - t->top;
+ scm_mark_locations (t->top, stack_len);
#endif
- scm_mark_locations ((SCM_STACKITEM *) t->regs,
- ((size_t) sizeof(t->regs)
- / sizeof (SCM_STACKITEM)));
- }
+ scm_mark_locations ((SCM_STACKITEM *) t->regs,
+ ((size_t) sizeof(t->regs)
+ / sizeof (SCM_STACKITEM)));
}
}
@@ -1189,25 +1144,29 @@ scm_c_thread_exited_p (SCM thread)
static scm_t_cond wake_up_cond;
int scm_i_thread_go_to_sleep;
-static int gc_section_count = 0;
static int threads_initialized_p = 0;
void
scm_i_thread_put_to_sleep ()
{
- if (threads_initialized_p && !gc_section_count++)
+ if (threads_initialized_p)
{
SCM threads;
+
+ /* We leave Guile completely before locking the
+ thread_admin_mutex. This ensures that other threads can put
+ us to sleep while we block on that mutex.
+ */
+ scm_i_leave_guile ();
scm_i_plugin_mutex_lock (&thread_admin_mutex);
threads = all_threads;
/* Signal all threads to go to sleep */
scm_i_thread_go_to_sleep = 1;
for (; !SCM_NULLP (threads); threads = SCM_CDR (threads))
- if (SCM_CAR (threads) != cur_thread)
- {
- scm_thread *t = SCM_THREAD_DATA (SCM_CAR (threads));
- scm_i_plugin_mutex_lock (&t->heap_mutex);
- }
+ {
+ scm_thread *t = SCM_THREAD_DATA (SCM_CAR (threads));
+ scm_i_plugin_mutex_lock (&t->heap_mutex);
+ }
scm_i_thread_go_to_sleep = 0;
}
}
@@ -1228,18 +1187,18 @@ scm_i_thread_invalidate_freelists ()
void
scm_i_thread_wake_up ()
{
- if (threads_initialized_p && !--gc_section_count)
+ if (threads_initialized_p)
{
SCM threads;
threads = all_threads;
scm_i_plugin_cond_broadcast (&wake_up_cond);
for (; !SCM_NULLP (threads); threads = SCM_CDR (threads))
- if (SCM_CAR (threads) != cur_thread)
- {
- scm_thread *t = SCM_THREAD_DATA (SCM_CAR (threads));
- scm_i_plugin_mutex_unlock (&t->heap_mutex);
- }
+ {
+ scm_thread *t = SCM_THREAD_DATA (SCM_CAR (threads));
+ scm_i_plugin_mutex_unlock (&t->heap_mutex);
+ }
scm_i_plugin_mutex_unlock (&thread_admin_mutex);
+ scm_i_enter_guile (SCM_CURRENT_THREAD);
}
}