+ if (err != 0) {
+ errno = err;
+ mainret = 1;
+ perror("pthread_join");
+ }
+ tot_writes += count_writer[i].update_ops;
+ tot_add += count_writer[i].add;
+ tot_add_exist += count_writer[i].add_exist;
+ tot_remove += count_writer[i].remove;
+ }
+
+ /* teardown counter thread */
+ act.sa_handler = SIG_IGN;
+ act.sa_flags = SA_RESTART;
+ ret = sigaction(SIGUSR2, &act, NULL);
+ if (ret == -1) {
+ mainret = 1;
+ perror("sigaction");
+ }
+ {
+ char msg[1] = { 0x42 };
+ ssize_t ret;
+
+ do {
+ ret = write(count_pipe[1], msg, 1); /* wakeup thread */
+ } while (ret == -1L && errno == EINTR);
+ }
+ err = pthread_join(tid_count, &tret);
+ if (err != 0) {
+ errno = err;
+ mainret = 1;
+ perror("pthread_join");
+ }
+
+end_close_pipe:
+ for (i = 0; i < 2; i++) {
+ err = close(count_pipe[i]);
+ if (err) {
+ mainret = 1;
+ perror("close pipe");
+ }
+ }
+ fflush(stdout);
+end_online:
+ rcu_thread_online();
+ rcu_read_lock();
+ printf("Counting nodes... ");
+ cds_lfht_count_nodes(test_ht, &approx_before, &count, &approx_after);
+ printf("done.\n");
+ test_delete_all_nodes(test_ht);
+ rcu_read_unlock();
+ rcu_thread_offline();
+ if (count) {
+ printf("Approximation before node accounting: %ld nodes.\n",
+ approx_before);
+ printf("Nodes deleted from hash table before destroy: "
+ "%lu nodes.\n",
+ count);
+ printf("Approximation after node accounting: %ld nodes.\n",
+ approx_after);
+ }
+
+ ret = cds_lfht_destroy(test_ht, NULL);
+ if (ret) {
+ printf_verbose("final delete aborted\n");
+ mainret = 1;
+ } else {
+ printf_verbose("final delete success\n");