rculfhash: handle small and negative table size approximation
[urcu.git] / rculfhash.c
index 1487980c832c115154937cda4b185024636f9e44..9a95be260783e66aea715fa3806f0e5f0571e66f 100644 (file)
@@ -556,7 +556,7 @@ void ht_count_add(struct cds_lfht *ht, unsigned long size)
                return;
        percpu_count = uatomic_add_return(&ht->percpu_count[cpu].add, 1);
        if (unlikely(!(percpu_count & ((1UL << COUNT_COMMIT_ORDER) - 1)))) {
-               unsigned long count;
+               long count;
 
                dbg_printf("add percpu %lu\n", percpu_count);
                count = uatomic_add_return(&ht->count,
@@ -565,7 +565,13 @@ void ht_count_add(struct cds_lfht *ht, unsigned long size)
                if (!(count & (count - 1))) {
                        if ((count >> CHAIN_LEN_RESIZE_THRESHOLD) < size)
                                return;
-                       dbg_printf("add set global %lu\n", count);
+                       dbg_printf("add set global %ld\n", count);
+                       /*
+                        * Don't resize table if the number of nodes is below a
+                        * certain threshold.
+                        */
+                       if (count < (1UL << COUNT_COMMIT_ORDER))
+                               return;
                        cds_lfht_resize_lazy_count(ht, size,
                                count >> (CHAIN_LEN_TARGET - 1));
                }
@@ -583,9 +589,9 @@ void ht_count_del(struct cds_lfht *ht, unsigned long size)
        cpu = ht_get_cpu();
        if (unlikely(cpu < 0))
                return;
-       percpu_count = uatomic_add_return(&ht->percpu_count[cpu].del, -1);
+       percpu_count = uatomic_add_return(&ht->percpu_count[cpu].del, 1);
        if (unlikely(!(percpu_count & ((1UL << COUNT_COMMIT_ORDER) - 1)))) {
-               unsigned long count;
+               long count;
 
                dbg_printf("del percpu %lu\n", percpu_count);
                count = uatomic_add_return(&ht->count,
@@ -594,7 +600,13 @@ void ht_count_del(struct cds_lfht *ht, unsigned long size)
                if (!(count & (count - 1))) {
                        if ((count >> CHAIN_LEN_RESIZE_THRESHOLD) >= size)
                                return;
-                       dbg_printf("del set global %lu\n", count);
+                       dbg_printf("del set global %ld\n", count);
+                       /*
+                        * Don't resize table if the number of nodes is below a
+                        * certain threshold.
+                        */
+                       if (count < (1UL << COUNT_COMMIT_ORDER))
+                               return;
                        cds_lfht_resize_lazy_count(ht, size,
                                count >> (CHAIN_LEN_TARGET - 1));
                }
@@ -1446,13 +1458,25 @@ int cds_lfht_destroy(struct cds_lfht *ht, pthread_attr_t **attr)
 }
 
 void cds_lfht_count_nodes(struct cds_lfht *ht,
+               unsigned long *approx_before,
                unsigned long *count,
-               unsigned long *removed)
+               unsigned long *removed,
+               unsigned long *approx_after)
 {
        struct cds_lfht_node *node, *next;
        struct _cds_lfht_node *lookup;
        unsigned long nr_dummy = 0;
 
+       *approx_before = 0;
+       if (nr_cpus_mask >= 0) {
+               int i;
+
+               for (i = 0; i < nr_cpus_mask + 1; i++) {
+                       *approx_before += uatomic_read(&ht->percpu_count[i].add);
+                       *approx_before -= uatomic_read(&ht->percpu_count[i].del);
+               }
+       }
+
        *count = 0;
        *removed = 0;
 
@@ -1462,8 +1486,10 @@ void cds_lfht_count_nodes(struct cds_lfht *ht,
        do {
                next = rcu_dereference(node->p.next);
                if (is_removed(next)) {
-                       assert(!is_dummy(next));
-                       (*removed)++;
+                       if (!is_dummy(next))
+                               (*removed)++;
+                       else
+                               (nr_dummy)++;
                } else if (!is_dummy(next))
                        (*count)++;
                else
@@ -1471,6 +1497,15 @@ void cds_lfht_count_nodes(struct cds_lfht *ht,
                node = clear_flag(next);
        } while (!is_end(node));
        dbg_printf("number of dummy nodes: %lu\n", nr_dummy);
+       *approx_after = 0;
+       if (nr_cpus_mask >= 0) {
+               int i;
+
+               for (i = 0; i < nr_cpus_mask + 1; i++) {
+                       *approx_after += uatomic_read(&ht->percpu_count[i].add);
+                       *approx_after -= uatomic_read(&ht->percpu_count[i].del);
+               }
+       }
 }
 
 /* called with resize mutex held */
This page took 0.024414 seconds and 4 git commands to generate.