rculfhash: use dbg_printf() for grow/shrink printout
[urcu.git] / rculfhash.c
index 50b783440edc6e4297cd1ac341bd15ce780f5045..cf822fcd620e98b47d6a718582f1385887f34496 100644 (file)
 #include <stdint.h>
 #include <string.h>
 
-#include <urcu/config.h>
+#include "config.h"
 #include <urcu.h>
 #include <urcu-call-rcu.h>
 #include <urcu/arch.h>
@@ -255,7 +255,7 @@ struct rcu_resize_work {
 };
 
 struct partition_resize_work {
-       struct rcu_head head;
+       pthread_t thread_id;
        struct cds_lfht *ht;
        unsigned long i, start, len;
        void (*fct)(struct cds_lfht *ht, unsigned long i,
@@ -608,7 +608,7 @@ 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 = -1;
+static const long nr_cpus_mask = -2;
 
 static
 struct ht_items_count *alloc_per_cpu_items_count(void)
@@ -1034,18 +1034,20 @@ void partition_resize_helper(struct cds_lfht *ht, unsigned long i,
        struct partition_resize_work *work;
        int thread, ret;
        unsigned long nr_threads;
-       pthread_t *thread_id;
 
        /*
         * Note: nr_cpus_mask + 1 is always power of 2.
         * We spawn just the number of threads we need to satisfy the minimum
         * partition size, up to the number of CPUs in the system.
         */
-       nr_threads = min(nr_cpus_mask + 1,
-                        len >> MIN_PARTITION_PER_THREAD_ORDER);
+       if (nr_cpus_mask > 0) {
+               nr_threads = min(nr_cpus_mask + 1,
+                                len >> MIN_PARTITION_PER_THREAD_ORDER);
+       } else {
+               nr_threads = 1;
+       }
        partition_len = len >> get_count_order_ulong(nr_threads);
        work = calloc(nr_threads, sizeof(*work));
-       thread_id = calloc(nr_threads, sizeof(*thread_id));
        assert(work);
        for (thread = 0; thread < nr_threads; thread++) {
                work[thread].ht = ht;
@@ -1053,16 +1055,15 @@ void partition_resize_helper(struct cds_lfht *ht, unsigned long i,
                work[thread].len = partition_len;
                work[thread].start = thread * partition_len;
                work[thread].fct = fct;
-               ret = pthread_create(&thread_id[thread], ht->resize_attr,
+               ret = pthread_create(&(work[thread].thread_id), ht->resize_attr,
                        partition_resize_thread, &work[thread]);
                assert(!ret);
        }
        for (thread = 0; thread < nr_threads; thread++) {
-               ret = pthread_join(thread_id[thread], NULL);
+               ret = pthread_join(work[thread].thread_id, NULL);
                assert(!ret);
        }
        free(work);
-       free(thread_id);
 }
 
 /*
@@ -1093,8 +1094,6 @@ void init_table_populate_partition(struct cds_lfht *ht, unsigned long i,
                        bit_reverse_ulong(!i ? 0 : (1UL << (i - 1)) + j);
                (void) _cds_lfht_add(ht, !i ? 0 : (1UL << (i - 1)),
                                new_node, ADD_DEFAULT, 1);
-               if (CMM_LOAD_SHARED(ht->in_progress_destroy))
-                       break;
        }
        ht->cds_lfht_rcu_read_unlock();
 }
@@ -1196,8 +1195,6 @@ void remove_table_partition(struct cds_lfht *ht, unsigned long i,
                        bit_reverse_ulong(!i ? 0 : (1UL << (i - 1)) + j);
                (void) _cds_lfht_del(ht, !i ? 0 : (1UL << (i - 1)),
                                fini_node, 1);
-               if (CMM_LOAD_SHARED(ht->in_progress_destroy))
-                       break;
        }
        ht->cds_lfht_rcu_read_unlock();
 }
@@ -1391,6 +1388,41 @@ void cds_lfht_next_duplicate(struct cds_lfht *ht, struct cds_lfht_iter *iter)
        iter->next = next;
 }
 
+void cds_lfht_next(struct cds_lfht *ht, struct cds_lfht_iter *iter)
+{
+       struct cds_lfht_node *node, *next;
+
+       node = clear_flag(iter->next);
+       for (;;) {
+               if (unlikely(is_end(node))) {
+                       node = next = NULL;
+                       break;
+               }
+               next = rcu_dereference(node->p.next);
+               if (likely(!is_removed(next))
+                   && !is_dummy(next)) {
+                               break;
+               }
+               node = clear_flag(next);
+       }
+       assert(!node || !is_dummy(rcu_dereference(node->p.next)));
+       iter->node = node;
+       iter->next = next;
+}
+
+void cds_lfht_first(struct cds_lfht *ht, struct cds_lfht_iter *iter)
+{
+       struct _cds_lfht_node *lookup;
+
+       /*
+        * Get next after first dummy node. The first dummy node is the
+        * first node of the linked list.
+        */
+       lookup = &ht->t.tbl[0]->nodes[0];
+       iter->next = lookup->next;
+       cds_lfht_next(ht, iter);
+}
+
 void cds_lfht_add(struct cds_lfht *ht, struct cds_lfht_node *node)
 {
        unsigned long hash, size;
@@ -1503,7 +1535,8 @@ int cds_lfht_destroy(struct cds_lfht *ht, pthread_attr_t **attr)
        int ret;
 
        /* Wait for in-flight resize operations to complete */
-       CMM_STORE_SHARED(ht->in_progress_destroy, 1);
+       _CMM_STORE_SHARED(ht->in_progress_destroy, 1);
+       cmm_smp_mb();   /* Store destroy before load resize */
        while (uatomic_read(&ht->in_progress_resize))
                poll(NULL, 0, 100);     /* wait for 100ms */
        ret = cds_lfht_delete_dummy(ht);
@@ -1576,8 +1609,8 @@ void _do_cds_lfht_grow(struct cds_lfht *ht,
 
        old_order = get_count_order_ulong(old_size) + 1;
        new_order = get_count_order_ulong(new_size) + 1;
-       printf("resize from %lu (order %lu) to %lu (order %lu) buckets\n",
-              old_size, old_order, new_size, new_order);
+       dbg_printf("resize from %lu (order %lu) to %lu (order %lu) buckets\n",
+                  old_size, old_order, new_size, new_order);
        assert(new_size > old_size);
        init_table(ht, old_order, new_order - old_order);
 }
@@ -1592,8 +1625,8 @@ void _do_cds_lfht_shrink(struct cds_lfht *ht,
        new_size = max(new_size, MIN_TABLE_SIZE);
        old_order = get_count_order_ulong(old_size) + 1;
        new_order = get_count_order_ulong(new_size) + 1;
-       printf("resize from %lu (order %lu) to %lu (order %lu) buckets\n",
-              old_size, old_order, new_size, new_order);
+       dbg_printf("resize from %lu (order %lu) to %lu (order %lu) buckets\n",
+                  old_size, old_order, new_size, new_order);
        assert(new_size < old_size);
 
        /* Remove and unlink all dummy nodes to remove. */
@@ -1611,6 +1644,9 @@ void _do_cds_lfht_resize(struct cds_lfht *ht)
         * Resize table, re-do if the target size has changed under us.
         */
        do {
+               assert(uatomic_read(&ht->in_progress_resize));
+               if (CMM_LOAD_SHARED(ht->in_progress_destroy))
+                       break;
                ht->t.resize_initiated = 1;
                old_size = ht->t.size;
                new_size = CMM_LOAD_SHARED(ht->t.resize_target);
@@ -1679,7 +1715,11 @@ void cds_lfht_resize_lazy(struct cds_lfht *ht, unsigned long size, int growth)
        cmm_smp_mb();
        if (!CMM_LOAD_SHARED(ht->t.resize_initiated) && size < target_size) {
                uatomic_inc(&ht->in_progress_resize);
-               cmm_smp_mb();   /* increment resize count before calling it */
+               cmm_smp_mb();   /* increment resize count before load destroy */
+               if (CMM_LOAD_SHARED(ht->in_progress_destroy)) {
+                       uatomic_dec(&ht->in_progress_resize);
+                       return;
+               }
                work = malloc(sizeof(*work));
                work->ht = ht;
                ht->cds_lfht_call_rcu(&work->head, do_resize_cb);
@@ -1702,7 +1742,11 @@ void cds_lfht_resize_lazy_count(struct cds_lfht *ht, unsigned long size,
        cmm_smp_mb();
        if (!CMM_LOAD_SHARED(ht->t.resize_initiated)) {
                uatomic_inc(&ht->in_progress_resize);
-               cmm_smp_mb();   /* increment resize count before calling it */
+               cmm_smp_mb();   /* increment resize count before load destroy */
+               if (CMM_LOAD_SHARED(ht->in_progress_destroy)) {
+                       uatomic_dec(&ht->in_progress_resize);
+                       return;
+               }
                work = malloc(sizeof(*work));
                work->ht = ht;
                ht->cds_lfht_call_rcu(&work->head, do_resize_cb);
This page took 0.025356 seconds and 4 git commands to generate.