X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=rculfhash.c;h=da37e97d38554c6def88699590be83439385e82f;hb=b5d6b20fb518bce4a39c256ac89dcb376a5f971a;hp=e94b9b224422e8e316c5dbeea4be0aff0b002b36;hpb=4c42f1b8ad898738bf5caae2682e18c57dce91d3;p=urcu.git diff --git a/rculfhash.c b/rculfhash.c index e94b9b2..da37e97 100644 --- a/rculfhash.c +++ b/rculfhash.c @@ -179,6 +179,7 @@ * tables and machines lacking per-cpu data suppport. */ #define COUNT_COMMIT_ORDER 10 +#define DEFAULT_SPLIT_COUNT_MASK 0xFUL #define CHAIN_LEN_TARGET 1 #define CHAIN_LEN_RESIZE_THRESHOLD 3 @@ -485,10 +486,12 @@ int get_count_order_ulong(unsigned long x) } #ifdef POISON_FREE -#define poison_free(ptr) \ - do { \ - memset(ptr, 0x42, sizeof(*(ptr))); \ - free(ptr); \ +#define poison_free(ptr) \ + do { \ + if (ptr) { \ + memset(ptr, 0x42, sizeof(*(ptr))); \ + free(ptr); \ + } \ } while (0) #else #define poison_free(ptr) free(ptr) @@ -497,14 +500,6 @@ int get_count_order_ulong(unsigned long x) static void cds_lfht_resize_lazy(struct cds_lfht *ht, unsigned long size, int growth); -/* - * If the sched_getcpu() and sysconf(_SC_NPROCESSORS_CONF) calls are - * available, then we support hash table item accounting. - * In the unfortunate event the number of CPUs reported would be - * inaccurate, we use modulo arithmetic on the number of CPUs we got. - */ -#if defined(HAVE_SCHED_GETCPU) && defined(HAVE_SYSCONF) - static void cds_lfht_resize_lazy_count(struct cds_lfht *ht, unsigned long size, unsigned long count); @@ -512,6 +507,7 @@ void cds_lfht_resize_lazy_count(struct cds_lfht *ht, unsigned long size, static long nr_cpus_mask = -1; static long split_count_mask = -1; +#if defined(HAVE_SYSCONF) static void ht_init_nr_cpus_mask(void) { long maxcpus; @@ -528,53 +524,72 @@ static void ht_init_nr_cpus_mask(void) maxcpus = 1UL << get_count_order_ulong(maxcpus); nr_cpus_mask = maxcpus - 1; } +#else /* #if defined(HAVE_SYSCONF) */ +static void ht_init_nr_cpus_mask(void) +{ + nr_cpus_mask = -2; +} +#endif /* #else #if defined(HAVE_SYSCONF) */ static -struct ht_items_count *alloc_split_items_count(void) +void alloc_split_items_count(struct cds_lfht *ht) { struct ht_items_count *count; if (nr_cpus_mask == -1) { ht_init_nr_cpus_mask(); - split_count_mask = nr_cpus_mask; + if (nr_cpus_mask < 0) + split_count_mask = DEFAULT_SPLIT_COUNT_MASK; + else + split_count_mask = nr_cpus_mask; } - if (split_count_mask < 0) - return NULL; - else - return calloc(split_count_mask + 1, sizeof(*count)); + assert(split_count_mask >= 0); + + if (ht->flags & CDS_LFHT_ACCOUNTING) { + ht->split_count = calloc(split_count_mask + 1, sizeof(*count)); + assert(ht->split_count); + } else { + ht->split_count = NULL; + } } static -void free_split_items_count(struct ht_items_count *count) +void free_split_items_count(struct cds_lfht *ht) { - poison_free(count); + poison_free(ht->split_count); } +#if defined(HAVE_SCHED_GETCPU) static -int ht_get_split_count_index(void) +int ht_get_split_count_index(unsigned long hash) { int cpu; assert(split_count_mask >= 0); cpu = sched_getcpu(); if (unlikely(cpu < 0)) - return cpu; + return hash & split_count_mask; else return cpu & split_count_mask; } +#else /* #if defined(HAVE_SCHED_GETCPU) */ +static +int ht_get_split_count_index(unsigned long hash) +{ + return hash & split_count_mask; +} +#endif /* #else #if defined(HAVE_SCHED_GETCPU) */ static -void ht_count_add(struct cds_lfht *ht, unsigned long size) +void ht_count_add(struct cds_lfht *ht, unsigned long size, unsigned long hash) { unsigned long split_count; int index; if (unlikely(!ht->split_count)) return; - index = ht_get_split_count_index(); - if (unlikely(index < 0)) - return; + index = ht_get_split_count_index(hash); split_count = uatomic_add_return(&ht->split_count[index].add, 1); if (unlikely(!(split_count & ((1UL << COUNT_COMMIT_ORDER) - 1)))) { long count; @@ -594,16 +609,14 @@ void ht_count_add(struct cds_lfht *ht, unsigned long size) } static -void ht_count_del(struct cds_lfht *ht, unsigned long size) +void ht_count_del(struct cds_lfht *ht, unsigned long size, unsigned long hash) { unsigned long split_count; int index; if (unlikely(!ht->split_count)) return; - index = ht_get_split_count_index(); - if (unlikely(index < 0)) - return; + index = ht_get_split_count_index(hash); split_count = uatomic_add_return(&ht->split_count[index].del, 1); if (unlikely(!(split_count & ((1UL << COUNT_COMMIT_ORDER) - 1)))) { long count; @@ -628,35 +641,6 @@ void ht_count_del(struct cds_lfht *ht, unsigned long size) } } -#else /* #if defined(HAVE_SCHED_GETCPU) && defined(HAVE_SYSCONF) */ - -static const long nr_cpus_mask = -2; -static const long split_count_mask = -2; - -static -struct ht_items_count *alloc_split_items_count(void) -{ - return NULL; -} - -static -void free_split_items_count(struct ht_items_count *count) -{ -} - -static -void ht_count_add(struct cds_lfht *ht, unsigned long size) -{ -} - -static -void ht_count_del(struct cds_lfht *ht, unsigned long size) -{ -} - -#endif /* #else #if defined(HAVE_SCHED_GETCPU) && defined(HAVE_SYSCONF) */ - - static void check_resize(struct cds_lfht *ht, unsigned long size, uint32_t chain_len) { @@ -1346,6 +1330,7 @@ struct cds_lfht *_cds_lfht_new(cds_lfht_hash_fct hash_fct, init_size = max(init_size, min_alloc_size); ht = calloc(1, sizeof(struct cds_lfht)); assert(ht); + ht->flags = flags; ht->hash_fct = hash_fct; ht->compare_fct = compare_fct; ht->hash_seed = hash_seed; @@ -1358,10 +1343,9 @@ struct cds_lfht *_cds_lfht_new(cds_lfht_hash_fct hash_fct, ht->cds_lfht_rcu_register_thread = cds_lfht_rcu_register_thread; ht->cds_lfht_rcu_unregister_thread = cds_lfht_rcu_unregister_thread; ht->resize_attr = attr; - ht->split_count = alloc_split_items_count(); + alloc_split_items_count(ht); /* this mutex should not nest in read-side C.S. */ pthread_mutex_init(&ht->resize_mutex, NULL); - ht->flags = flags; order = get_count_order_ulong(init_size); ht->t.resize_target = 1UL << order; cds_lfht_create_dummy(ht, 1UL << order); @@ -1490,7 +1474,7 @@ void cds_lfht_add(struct cds_lfht *ht, struct cds_lfht_node *node) size = rcu_dereference(ht->t.size); _cds_lfht_add(ht, size, node, NULL, 0); - ht_count_add(ht, size); + ht_count_add(ht, size, hash); } struct cds_lfht_node *cds_lfht_add_unique(struct cds_lfht *ht, @@ -1505,7 +1489,7 @@ struct cds_lfht_node *cds_lfht_add_unique(struct cds_lfht *ht, size = rcu_dereference(ht->t.size); _cds_lfht_add(ht, size, node, &iter, 0); if (iter.node == node) - ht_count_add(ht, size); + ht_count_add(ht, size, hash); return iter.node; } @@ -1522,7 +1506,7 @@ struct cds_lfht_node *cds_lfht_add_replace(struct cds_lfht *ht, for (;;) { _cds_lfht_add(ht, size, node, &iter, 0); if (iter.node == node) { - ht_count_add(ht, size); + ht_count_add(ht, size, hash); return NULL; } @@ -1543,13 +1527,15 @@ int cds_lfht_replace(struct cds_lfht *ht, struct cds_lfht_iter *old_iter, int cds_lfht_del(struct cds_lfht *ht, struct cds_lfht_iter *iter) { - unsigned long size; + unsigned long size, hash; int ret; size = rcu_dereference(ht->t.size); ret = _cds_lfht_del(ht, size, iter->node, 0); - if (!ret) - ht_count_del(ht, size); + if (!ret) { + hash = bit_reverse_ulong(iter->node->p.reverse_hash); + ht_count_del(ht, size, hash); + } return ret; } @@ -1611,7 +1597,7 @@ int cds_lfht_destroy(struct cds_lfht *ht, pthread_attr_t **attr) ret = cds_lfht_delete_dummy(ht); if (ret) return ret; - free_split_items_count(ht->split_count); + free_split_items_count(ht); if (attr) *attr = ht->resize_attr; poison_free(ht); @@ -1629,7 +1615,7 @@ void cds_lfht_count_nodes(struct cds_lfht *ht, unsigned long nr_dummy = 0; *approx_before = 0; - if (split_count_mask >= 0) { + if (ht->split_count) { int i; for (i = 0; i < split_count_mask + 1; i++) { @@ -1659,7 +1645,7 @@ void cds_lfht_count_nodes(struct cds_lfht *ht, } while (!is_end(node)); dbg_printf("number of dummy nodes: %lu\n", nr_dummy); *approx_after = 0; - if (split_count_mask >= 0) { + if (ht->split_count) { int i; for (i = 0; i < split_count_mask + 1; i++) { @@ -1796,8 +1782,6 @@ void cds_lfht_resize_lazy(struct cds_lfht *ht, unsigned long size, int growth) } } -#if defined(HAVE_SCHED_GETCPU) && defined(HAVE_SYSCONF) - static void cds_lfht_resize_lazy_count(struct cds_lfht *ht, unsigned long size, unsigned long count) @@ -1822,5 +1806,3 @@ void cds_lfht_resize_lazy_count(struct cds_lfht *ht, unsigned long size, CMM_STORE_SHARED(ht->t.resize_initiated, 1); } } - -#endif