1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-30 03:40:34 +02:00

Fix finalizer resuscitation causing excessive GC

* libguile/finalizers.c (async_gc_finalizer):
  (scm_i_register_async_gc_callback): Replace "weak gc callback"
  mechanism with "async gc callback" mechanism.  Very similar but the
  new API is designed to be called a bounded number of times, to avoid
  running afoul of libgc heuristics.
* libguile/weak-list.h: New internal header.
* libguile/Makefile.am (noinst_HEADERS): Add weak-list.h.
* libguile/weak-set.c (vacuum_all_weak_sets):
  (scm_c_make_weak_set, scm_init_weak_set):
* libguile/weak-table.c (vacuum_all_weak_tables):
  (scm_c_make_weak_table, scm_init_weak_table): Arrange to vacuum all
  weak sets from a single async GC callback, and likewise for weak
  tables.

Thanks to Ludovic Courtès for tracking this bug down!
This commit is contained in:
Andy Wingo 2017-03-13 15:47:51 +01:00
parent e337432041
commit c9910c6042
6 changed files with 137 additions and 43 deletions

View file

@ -31,6 +31,7 @@
#include "libguile/bdw-gc.h"
#include "libguile/validate.h"
#include "libguile/weak-list.h"
#include "libguile/weak-set.h"
@ -698,6 +699,17 @@ do_vacuum_weak_set (SCM set)
scm_i_pthread_mutex_unlock (&s->lock);
}
static scm_i_pthread_mutex_t all_weak_sets_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
static SCM all_weak_sets = SCM_EOL;
static void
vacuum_all_weak_sets (void)
{
scm_i_pthread_mutex_lock (&all_weak_sets_lock);
scm_i_visit_weak_list (&all_weak_sets, do_vacuum_weak_set);
scm_i_pthread_mutex_unlock (&all_weak_sets_lock);
}
SCM
scm_c_make_weak_set (unsigned long k)
{
@ -705,7 +717,9 @@ scm_c_make_weak_set (unsigned long k)
ret = make_weak_set (k);
scm_i_register_weak_gc_callback (ret, do_vacuum_weak_set);
scm_i_pthread_mutex_lock (&all_weak_sets_lock);
all_weak_sets = scm_i_weak_cons (ret, all_weak_sets);
scm_i_pthread_mutex_unlock (&all_weak_sets_lock);
return ret;
}
@ -883,6 +897,8 @@ void
scm_init_weak_set ()
{
#include "libguile/weak-set.x"
scm_i_register_async_gc_callback (vacuum_all_weak_sets);
}
/*