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

with a threaded guile, lock weak sets and tables during a fork

* libguile/weak-set.c (make_weak_set):
* libguile/weak-table.c (make_weak_table): If we have a threaded Guile,
* keep a weak set (table) of weak sets (tables).  Use this and the
  pthread_atfork mechanism to lock and unlock weak sets and weak tables
  during a fork().

* libguile/weak-set.h (scm_weak_set_prehistory): New internal API.
* libguile/init.c: Add call to scm_weak_set_prehistory().
This commit is contained in:
Andy Wingo 2012-02-17 11:47:52 +01:00
parent 58565208bd
commit f609480611
4 changed files with 194 additions and 28 deletions

View file

@ -383,6 +383,7 @@ scm_i_init_guile (void *base)
scm_storage_prehistory ();
scm_threads_prehistory (base); /* requires storage_prehistory */
scm_weak_set_prehistory (); /* requires storage_prehistory */
scm_weak_table_prehistory (); /* requires storage_prehistory */
#ifdef GUILE_DEBUG_MALLOC
scm_debug_malloc_prehistory ();

View file

@ -614,6 +614,74 @@ weak_set_remove_x (scm_t_weak_set *set, unsigned long hash,
static void
lock_weak_set (scm_t_weak_set *set)
{
scm_i_pthread_mutex_lock (&set->lock);
}
static void
unlock_weak_set (scm_t_weak_set *set)
{
scm_i_pthread_mutex_unlock (&set->lock);
}
/* A weak set of weak sets, for use in the pthread_atfork handler. */
static SCM all_weak_sets = SCM_BOOL_F;
#if SCM_USE_PTHREAD_THREADS
static void
lock_all_weak_sets (void)
{
scm_t_weak_set *s;
scm_t_weak_entry *entries;
unsigned long k, size;
scm_t_weak_entry copy;
s = SCM_WEAK_SET (all_weak_sets);
lock_weak_set (s);
size = s->size;
entries = s->entries;
for (k = 0; k < size; k++)
if (entries[k].hash)
{
copy_weak_entry (&entries[k], &copy);
if (copy.key)
lock_weak_set (SCM_WEAK_SET (SCM_PACK (copy.key)));
}
}
static void
unlock_all_weak_sets (void)
{
scm_t_weak_set *s;
scm_t_weak_entry *entries;
unsigned long k, size;
scm_t_weak_entry copy;
s = SCM_WEAK_SET (all_weak_sets);
size = s->size;
entries = s->entries;
for (k = 0; k < size; k++)
if (entries[k].hash)
{
copy_weak_entry (&entries[k], &copy);
if (copy.key)
unlock_weak_set (SCM_WEAK_SET (SCM_PACK (copy.key)));
}
unlock_weak_set (s);
}
#endif /* SCM_USE_PTHREAD_THREADS */
static SCM
make_weak_set (unsigned long k)
{
@ -660,7 +728,7 @@ do_vacuum_weak_set (SCM set)
if (scm_i_pthread_mutex_trylock (&s->lock) == 0)
{
vacuum_weak_set (s);
scm_i_pthread_mutex_unlock (&s->lock);
unlock_weak_set (s);
}
return;
@ -725,6 +793,9 @@ scm_c_make_weak_set (unsigned long k)
scm_c_register_weak_gc_callback (ret, do_vacuum_weak_set);
if (scm_is_true (all_weak_sets))
scm_weak_set_add_x (all_weak_sets, ret);
return ret;
}
@ -739,12 +810,12 @@ scm_weak_set_clear_x (SCM set)
{
scm_t_weak_set *s = SCM_WEAK_SET (set);
scm_i_pthread_mutex_lock (&s->lock);
lock_weak_set (s);
memset (s->entries, 0, sizeof (scm_t_weak_entry) * s->size);
s->n_items = 0;
scm_i_pthread_mutex_unlock (&s->lock);
unlock_weak_set (s);
return SCM_UNSPECIFIED;
}
@ -757,11 +828,11 @@ scm_c_weak_set_lookup (SCM set, unsigned long raw_hash,
SCM ret;
scm_t_weak_set *s = SCM_WEAK_SET (set);
scm_i_pthread_mutex_lock (&s->lock);
lock_weak_set (s);
ret = weak_set_lookup (s, raw_hash, pred, closure, dflt);
scm_i_pthread_mutex_unlock (&s->lock);
unlock_weak_set (s);
return ret;
}
@ -774,11 +845,11 @@ scm_c_weak_set_add_x (SCM set, unsigned long raw_hash,
SCM ret;
scm_t_weak_set *s = SCM_WEAK_SET (set);
scm_i_pthread_mutex_lock (&s->lock);
lock_weak_set (s);
ret = weak_set_add_x (s, raw_hash, pred, closure, obj);
scm_i_pthread_mutex_unlock (&s->lock);
unlock_weak_set (s);
return ret;
}
@ -790,11 +861,11 @@ scm_c_weak_set_remove_x (SCM set, unsigned long raw_hash,
{
scm_t_weak_set *s = SCM_WEAK_SET (set);
scm_i_pthread_mutex_lock (&s->lock);
lock_weak_set (s);
weak_set_remove_x (s, raw_hash, pred, closure);
scm_i_pthread_mutex_unlock (&s->lock);
unlock_weak_set (s);
}
static int
@ -829,7 +900,7 @@ scm_c_weak_set_fold (scm_t_set_fold_fn proc, void *closure,
s = SCM_WEAK_SET (set);
scm_i_pthread_mutex_lock (&s->lock);
lock_weak_set (s);
size = s->size;
entries = s->entries;
@ -845,14 +916,14 @@ scm_c_weak_set_fold (scm_t_set_fold_fn proc, void *closure,
if (copy.key)
{
/* Release set lock while we call the function. */
scm_i_pthread_mutex_unlock (&s->lock);
unlock_weak_set (s);
init = proc (closure, SCM_PACK (copy.key), init);
scm_i_pthread_mutex_lock (&s->lock);
lock_weak_set (s);
}
}
}
scm_i_pthread_mutex_unlock (&s->lock);
unlock_weak_set (s);
return init;
}
@ -897,6 +968,17 @@ scm_weak_set_map_to_list (SCM proc, SCM set)
}
void
scm_weak_set_prehistory (void)
{
#if SCM_USE_PTHREAD_THREADS
all_weak_sets = scm_c_make_weak_set (0);
pthread_atfork (lock_all_weak_sets, unlock_all_weak_sets, unlock_all_weak_sets);
#endif
}
void
scm_init_weak_set ()
{

View file

@ -3,7 +3,7 @@
#ifndef SCM_WEAK_SET_H
#define SCM_WEAK_SET_H
/* Copyright (C) 2011 Free Software Foundation, Inc.
/* Copyright (C) 2011, 2012 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@ -57,7 +57,10 @@ SCM_INTERNAL SCM scm_weak_set_fold (SCM proc, SCM init, SCM set);
SCM_INTERNAL SCM scm_weak_set_for_each (SCM proc, SCM set);
SCM_INTERNAL SCM scm_weak_set_map_to_list (SCM proc, SCM set);
SCM_INTERNAL void scm_i_weak_set_lock (SCM set);
SCM_INTERNAL void scm_i_weak_set_unlock (SCM set);
SCM_INTERNAL void scm_i_weak_set_print (SCM exp, SCM port, scm_print_state *pstate);
SCM_INTERNAL void scm_weak_set_prehistory (void);
SCM_INTERNAL void scm_init_weak_set (void);
#endif /* SCM_WEAK_SET_H */

View file

@ -736,10 +736,79 @@ weak_table_remove_x (scm_t_weak_table *table, unsigned long hash,
static void
lock_weak_table (scm_t_weak_table *table)
{
scm_i_pthread_mutex_lock (&table->lock);
}
static void
unlock_weak_table (scm_t_weak_table *table)
{
scm_i_pthread_mutex_unlock (&table->lock);
}
/* A weak table of weak tables, for use in the pthread_atfork handler. */
static SCM all_weak_tables = SCM_BOOL_F;
#if SCM_USE_PTHREAD_THREADS
static void
lock_all_weak_tables (void)
{
scm_t_weak_table *s;
scm_t_weak_entry *entries;
unsigned long k, size;
scm_t_weak_entry copy;
s = SCM_WEAK_TABLE (all_weak_tables);
lock_weak_table (s);
size = s->size;
entries = s->entries;
for (k = 0; k < size; k++)
if (entries[k].hash)
{
copy_weak_entry (&entries[k], &copy);
if (copy.key)
lock_weak_table (SCM_WEAK_TABLE (SCM_PACK (copy.key)));
}
}
static void
unlock_all_weak_tables (void)
{
scm_t_weak_table *s;
scm_t_weak_entry *entries;
unsigned long k, size;
scm_t_weak_entry copy;
s = SCM_WEAK_TABLE (all_weak_tables);
size = s->size;
entries = s->entries;
for (k = 0; k < size; k++)
if (entries[k].hash)
{
copy_weak_entry (&entries[k], &copy);
if (copy.key)
unlock_weak_table (SCM_WEAK_TABLE (SCM_PACK (copy.key)));
}
unlock_weak_table (s);
}
#endif /* SCM_USE_PTHREAD_THREADS */
static SCM
make_weak_table (unsigned long k, scm_t_weak_table_kind kind)
{
scm_t_weak_table *table;
SCM ret;
int i = 0, n = k ? k : 31;
while (i + 1 < HASHTABLE_SIZE_N && n > hashtable_size[i])
@ -757,7 +826,12 @@ make_weak_table (unsigned long k, scm_t_weak_table_kind kind)
table->min_size_index = i;
scm_i_pthread_mutex_init (&table->lock, NULL);
return scm_cell (scm_tc7_weak_table, (scm_t_bits)table);
ret = scm_cell (scm_tc7_weak_table, (scm_t_bits)table);
if (scm_is_true (all_weak_tables))
scm_weak_table_putq_x (all_weak_tables, ret, SCM_BOOL_T);
return ret;
}
void
@ -781,7 +855,7 @@ do_vacuum_weak_table (SCM table)
if (scm_i_pthread_mutex_trylock (&t->lock) == 0)
{
vacuum_weak_table (t);
scm_i_pthread_mutex_unlock (&t->lock);
unlock_weak_table (t);
}
return;
@ -868,11 +942,11 @@ scm_c_weak_table_ref (SCM table, unsigned long raw_hash,
t = SCM_WEAK_TABLE (table);
scm_i_pthread_mutex_lock (&t->lock);
lock_weak_table (t);
ret = weak_table_ref (t, raw_hash, pred, closure, dflt);
scm_i_pthread_mutex_unlock (&t->lock);
unlock_weak_table (t);
return ret;
}
@ -890,11 +964,11 @@ scm_c_weak_table_put_x (SCM table, unsigned long raw_hash,
t = SCM_WEAK_TABLE (table);
scm_i_pthread_mutex_lock (&t->lock);
lock_weak_table (t);
weak_table_put_x (t, raw_hash, pred, closure, key, value);
scm_i_pthread_mutex_unlock (&t->lock);
unlock_weak_table (t);
}
#undef FUNC_NAME
@ -910,11 +984,11 @@ scm_c_weak_table_remove_x (SCM table, unsigned long raw_hash,
t = SCM_WEAK_TABLE (table);
scm_i_pthread_mutex_lock (&t->lock);
lock_weak_table (t);
weak_table_remove_x (t, raw_hash, pred, closure);
scm_i_pthread_mutex_unlock (&t->lock);
unlock_weak_table (t);
}
#undef FUNC_NAME
@ -962,12 +1036,12 @@ scm_weak_table_clear_x (SCM table)
t = SCM_WEAK_TABLE (table);
scm_i_pthread_mutex_lock (&t->lock);
lock_weak_table (t);
memset (t->entries, 0, sizeof (scm_t_weak_entry) * t->size);
t->n_items = 0;
scm_i_pthread_mutex_unlock (&t->lock);
unlock_weak_table (t);
return SCM_UNSPECIFIED;
}
@ -983,7 +1057,7 @@ scm_c_weak_table_fold (scm_t_table_fold_fn proc, void *closure,
t = SCM_WEAK_TABLE (table);
scm_i_pthread_mutex_lock (&t->lock);
lock_weak_table (t);
size = t->size;
entries = t->entries;
@ -999,16 +1073,16 @@ scm_c_weak_table_fold (scm_t_table_fold_fn proc, void *closure,
if (copy.key && copy.value)
{
/* Release table lock while we call the function. */
scm_i_pthread_mutex_unlock (&t->lock);
unlock_weak_table (t);
init = proc (closure,
SCM_PACK (copy.key), SCM_PACK (copy.value),
init);
scm_i_pthread_mutex_lock (&t->lock);
lock_weak_table (t);
}
}
}
scm_i_pthread_mutex_unlock (&t->lock);
unlock_weak_table (t);
return init;
}
@ -1163,6 +1237,12 @@ scm_weak_table_prehistory (void)
GC_new_kind (GC_new_free_list (),
GC_MAKE_PROC (GC_new_proc (mark_weak_value_table), 0),
0, 0);
#if SCM_USE_PTHREAD_THREADS
all_weak_tables = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
pthread_atfork (lock_all_weak_tables, unlock_all_weak_tables,
unlock_all_weak_tables);
#endif
}
void