diff options
author | Marius Vollmer <mvo@zagadka.de> | 2004-08-19 17:16:01 +0000 |
---|---|---|
committer | Marius Vollmer <mvo@zagadka.de> | 2004-08-19 17:16:01 +0000 |
commit | 6087fad9c7263be996e8cb91cb300a20280048be (patch) | |
tree | 6c6e1d01e6a818a14ef69b82943e91e2289c3adb | |
parent | 3ee86942a7cc519ef1c6f6a9868a5136f85558bc (diff) | |
download | guile-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.c | 99 |
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); } } |