mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 11:40:18 +02:00
(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.
This commit is contained in:
parent
3ee86942a7
commit
6087fad9c7
1 changed files with 29 additions and 70 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue