}
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 = uatomic_read(&ht->count);
+ 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;
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
node = clear_flag(next);
} while (!is_end(node));
dbg_printf("number of dummy nodes: %lu\n", nr_dummy);
+ *approx_after = uatomic_read(&ht->count);
+ 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 */
}
}
+static
+void sigusr2_handler(int signo)
+{
+ unsigned long count, removed, approx_before, approx_after;
+
+ /* Accounting */
+ printf("Counting nodes... ");
+ fflush(stdout);
+ cds_lfht_count_nodes(test_ht, &approx_before, &count, &removed,
+ &approx_after);
+ printf("done.\n");
+ printf("Approximation before node accounting: %lu nodes.\n",
+ approx_before);
+ printf("Accounting of nodes in the hash table: "
+ "%lu nodes + %lu logically removed.\n",
+ count, removed);
+ printf("Approximation after node accounting: %lu nodes.\n",
+ approx_after);
+}
+
/*
* returns 0 if test should end.
*/
struct wr_count *count_writer;
unsigned long long tot_reads = 0, tot_writes = 0,
tot_add = 0, tot_add_exist = 0, tot_remove = 0;
- unsigned long count, removed;
+ unsigned long count, removed, approx_before, approx_after;
int i, a, ret;
struct sigaction act;
unsigned int remain;
perror("sigaction");
return -1;
}
+ act.sa_handler = sigusr2_handler;
+ act.sa_flags = SA_RESTART;
+ ret = sigaction(SIGUSR2, &act, NULL);
+ if (ret == -1) {
+ perror("sigaction");
+ return -1;
+ }
printf_verbose("running test for %lu seconds, %u readers, %u writers.\n",
duration, nr_readers, nr_writers);
}
printf("Counting nodes... ");
fflush(stdout);
- cds_lfht_count_nodes(test_ht, &count, &removed);
+ cds_lfht_count_nodes(test_ht, &approx_before, &count, &removed,
+ &approx_after);
printf("done.\n");
- if (count || removed)
+ if (count || removed) {
+ printf("Approximation before node accounting: %lu nodes.\n",
+ approx_before);
printf("WARNING: nodes left in the hash table upon destroy: "
- "%lu nodes + %lu logically removed.\n", count, removed);
+ "%lu nodes + %lu logically removed.\n",
+ count, removed);
+ printf("Approximation after node accounting: %lu nodes.\n",
+ approx_after);
+ }
ret = cds_lfht_destroy(test_ht, NULL);
if (ret)