From 0d14ceb26e0ff3e1d6f86cf3ec9674ee3b16e96f Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Mon, 17 Oct 2011 09:32:00 -0400 Subject: [PATCH] rculfhash: make struct rcu_level size power of 2 By adding a small slowpath overhead (added synchronize_rcu call in the last iteration of the resize), we can reduce the amount of wasted memory for memory allocators that allocate power of two memory areas. This is achieved by removing the call_rcu head from struct rcu_level. [ Edit by Mathieu Desnoyers: - add comment about need to manually update the allocation size of fields are added to struct rcu_level. - create a more explanatory title and changelog. ] Signed-off-by: Lai Jiangshan Signed-off-by: Mathieu Desnoyers --- rculfhash.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/rculfhash.c b/rculfhash.c index fe8beed..2e338f1 100644 --- a/rculfhash.c +++ b/rculfhash.c @@ -209,7 +209,7 @@ struct ht_items_count { } __attribute__((aligned(CAA_CACHE_LINE_SIZE))); struct rcu_level { - struct rcu_head head; + /* Note: manually update allocation length when adding a field */ struct _cds_lfht_node nodes[0]; }; @@ -716,14 +716,6 @@ unsigned long _uatomic_max(unsigned long *ptr, unsigned long v) return v; } -static -void cds_lfht_free_level(struct rcu_head *head) -{ - struct rcu_level *l = - caa_container_of(head, struct rcu_level, head); - poison_free(l); -} - /* * Remove all logically deleted nodes from a bucket up to a certain node key. */ @@ -1135,8 +1127,7 @@ void init_table(struct cds_lfht *ht, if (CMM_LOAD_SHARED(ht->t.resize_target) < (!i ? 1 : (1UL << i))) break; - ht->t.tbl[i] = calloc(1, sizeof(struct rcu_level) - + (len * sizeof(struct _cds_lfht_node))); + ht->t.tbl[i] = calloc(1, len * sizeof(struct _cds_lfht_node)); assert(ht->t.tbl[i]); /* @@ -1222,6 +1213,7 @@ void fini_table(struct cds_lfht *ht, unsigned long first_order, unsigned long len_order) { long i, end_order; + void *free_by_rcu = NULL; dbg_printf("fini table: first_order %lu end_order %lu\n", first_order, first_order + len_order); @@ -1247,6 +1239,8 @@ void fini_table(struct cds_lfht *ht, * return a logically removed node as insert position. */ ht->cds_lfht_synchronize_rcu(); + if (free_by_rcu) + free(free_by_rcu); /* * Set "removed" flag in dummy nodes about to be removed. @@ -1256,12 +1250,17 @@ void fini_table(struct cds_lfht *ht, */ remove_table(ht, i, len); - ht->cds_lfht_call_rcu(&ht->t.tbl[i]->head, cds_lfht_free_level); + free_by_rcu = ht->t.tbl[i]; dbg_printf("fini new size: %lu\n", 1UL << i); if (CMM_LOAD_SHARED(ht->in_progress_destroy)) break; } + + if (free_by_rcu) { + ht->cds_lfht_synchronize_rcu(); + free(free_by_rcu); + } } struct cds_lfht *_cds_lfht_new(cds_lfht_hash_fct hash_fct, -- 2.34.1