diff options
author | Andy Wingo <wingo@pobox.com> | 2012-02-17 11:47:52 +0100 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2012-02-17 12:09:28 +0100 |
commit | f609480611cfd1585409fd6b1b90beb730b026cf (patch) | |
tree | ae054e365a2980bf9836447ba4cd9bf6c0f88e72 /libguile/weak-table.c | |
parent | 58565208bdfe7544f7e4da8762e4c331171f9876 (diff) | |
download | guile-f609480611cfd1585409fd6b1b90beb730b026cf.tar.gz |
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().
Diffstat (limited to 'libguile/weak-table.c')
-rw-r--r-- | libguile/weak-table.c | 108 |
1 files changed, 94 insertions, 14 deletions
diff --git a/libguile/weak-table.c b/libguile/weak-table.c index 38fd23d30..3d453bafd 100644 --- a/libguile/weak-table.c +++ b/libguile/weak-table.c @@ -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], ©); + 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], ©); + 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 |