rcuja: free all leaf nodes at destruction
[urcu.git] / tests / test_urcu_ja.c
index 2130670e976e7466aa88e5ff0a7cbf3efe3b1529..7b64575d7bb1c0d0c2394dd921aa535e94844ae0 100644 (file)
@@ -22,6 +22,8 @@
 
 #define _GNU_SOURCE
 #include "test_urcu_ja.h"
+#include <inttypes.h>
+#include <stdint.h>
 
 DEFINE_URCU_TLS(unsigned int, rand_lookup);
 DEFINE_URCU_TLS(unsigned long, nr_add);
@@ -121,14 +123,14 @@ void rcu_copy_mutex_unlock(void)
        }
 }
 
-#if 0
 void free_node_cb(struct rcu_head *head)
 {
        struct ja_test_node *node =
-               caa_container_of(head, struct ja_test_node, head);
+               caa_container_of(head, struct ja_test_node, node.head);
        free(node);
 }
 
+#if 0
 static
 void test_delete_all_nodes(struct cds_lfht *ht)
 {
@@ -171,6 +173,255 @@ printf("        [not -u nor -s] Add entries (supports redundant keys).\n");
        printf("\n\n");
 }
 
+
+static
+int test_8bit_key(void)
+{
+       int ret;
+       uint64_t key;
+
+       /* Test with 8-bit key */
+       test_ja = cds_ja_new(8);
+       if (!test_ja) {
+               printf("Error allocating judy array.\n");
+               return -1;
+       }
+
+       /* Add keys */
+       printf("Test #1: add keys (8-bit).\n");
+       for (key = 0; key < 200; key++) {
+               struct ja_test_node *node =
+                       calloc(sizeof(*node), 1);
+
+               ja_test_node_init(node, key);
+               rcu_read_lock();
+               ret = cds_ja_add(test_ja, key, &node->node);
+               rcu_read_unlock();
+               if (ret) {
+                       fprintf(stderr, "Error (%d) adding node %" PRIu64 "\n",
+                               ret, key);
+                       assert(0);
+               }
+       }
+       printf("OK\n");
+
+       printf("Test #2: successful key lookup (8-bit).\n");
+       for (key = 0; key < 200; key++) {
+               struct cds_hlist_head head;
+
+               rcu_read_lock();
+               head = cds_ja_lookup(test_ja, key);
+               if (cds_hlist_empty(&head)) {
+                       fprintf(stderr, "Error lookup node %" PRIu64 "\n", key);
+                       assert(0);
+               }
+               rcu_read_unlock();
+       }
+       printf("OK\n");
+       printf("Test #3: unsuccessful key lookup (8-bit).\n");
+       for (key = 200; key < 240; key++) {
+               struct cds_hlist_head head;
+
+               rcu_read_lock();
+               head = cds_ja_lookup(test_ja, key);
+               if (!cds_hlist_empty(&head)) {
+                       fprintf(stderr,
+                               "Error unexpected lookup node %" PRIu64 "\n",
+                               key);
+                       assert(0);
+               }
+               rcu_read_unlock();
+       }
+       printf("OK\n");
+       printf("Test #4: remove keys (8-bit).\n");
+       for (key = 0; key < 200; key++) {
+               struct cds_hlist_head head;
+               struct ja_test_node *node;
+
+               rcu_read_lock();
+               head = cds_ja_lookup(test_ja, key);
+               node = cds_hlist_first_entry_rcu(&head, struct ja_test_node, node.list);
+               if (!node) {
+                       fprintf(stderr, "Error lookup node %" PRIu64 "\n", key);
+                       assert(0);
+               }
+               ret = cds_ja_del(test_ja, key, &node->node);
+               if (ret) {
+                       fprintf(stderr, "Error (%d) removing node %" PRIu64 "\n", ret, key);
+                       assert(0);
+               }
+               call_rcu(&node->node.head, free_node_cb);
+               rcu_read_unlock();
+       }
+       printf("OK\n");
+
+       ret = cds_ja_destroy(test_ja, free_node_cb);
+       if (ret) {
+               fprintf(stderr, "Error destroying judy array\n");
+               return -1;
+       }
+       return 0;
+}
+
+static
+int test_16bit_key(void)
+{
+       int ret;
+       uint64_t key;
+
+       /* Test with 16-bit key */
+       test_ja = cds_ja_new(16);
+       if (!test_ja) {
+               printf("Error allocating judy array.\n");
+               return -1;
+       }
+
+       /* Add keys */
+       printf("Test #1: add keys (16-bit).\n");
+       //for (key = 0; key < 10000; key++) {
+       for (key = 0; key < 65536; key+=256) {
+               struct ja_test_node *node =
+                       calloc(sizeof(*node), 1);
+
+               ja_test_node_init(node, key);
+               rcu_read_lock();
+               ret = cds_ja_add(test_ja, key, &node->node);
+               rcu_read_unlock();
+               if (ret) {
+                       fprintf(stderr, "Error (%d) adding node %" PRIu64 "\n",
+                               ret, key);
+                       assert(0);
+               }
+       }
+       printf("OK\n");
+
+       printf("Test #2: successful key lookup (16-bit).\n");
+       //for (key = 0; key < 10000; key++) {
+       for (key = 0; key < 65536; key+=256) {
+               struct cds_hlist_head head;
+
+               rcu_read_lock();
+               head = cds_ja_lookup(test_ja, key);
+               if (cds_hlist_empty(&head)) {
+                       fprintf(stderr, "Error lookup node %" PRIu64 "\n", key);
+                       assert(0);
+               }
+               rcu_read_unlock();
+       }
+       printf("OK\n");
+       printf("Test #3: unsuccessful key lookup (16-bit).\n");
+       for (key = 11000; key <= 11002; key++) {
+               struct cds_hlist_head head;
+
+               rcu_read_lock();
+               head = cds_ja_lookup(test_ja, key);
+               if (!cds_hlist_empty(&head)) {
+                       fprintf(stderr,
+                               "Error unexpected lookup node %" PRIu64 "\n",
+                               key);
+                       assert(0);
+               }
+               rcu_read_unlock();
+       }
+       printf("OK\n");
+
+       ret = cds_ja_destroy(test_ja, free_node_cb);
+       if (ret) {
+               fprintf(stderr, "Error destroying judy array\n");
+               return -1;
+       }
+       return 0;
+}
+
+static
+int test_sparse_key(unsigned int bits)
+{
+       int ret;
+       uint64_t key, max_key;
+       int zerocount;
+
+       if (bits == 64)
+               max_key = UINT64_MAX;
+       else
+               max_key = (1ULL << bits) - 1;
+
+       printf("Sparse key test begins for %u-bit keys\n", bits);
+       /* Test with 16-bit key */
+       test_ja = cds_ja_new(bits);
+       if (!test_ja) {
+               printf("Error allocating judy array.\n");
+               return -1;
+       }
+
+       /* Add keys */
+       printf("Test #1: add keys (%u-bit).\n", bits);
+       zerocount = 0;
+       for (key = 0; key <= max_key && (key != 0 || zerocount < 1); key += 1ULL << (bits - 8)) {
+               struct ja_test_node *node =
+                       calloc(sizeof(*node), 1);
+
+               ja_test_node_init(node, key);
+               rcu_read_lock();
+               ret = cds_ja_add(test_ja, key, &node->node);
+               rcu_read_unlock();
+               if (ret) {
+                       fprintf(stderr, "Error (%d) adding node %" PRIu64 "\n",
+                               ret, key);
+                       assert(0);
+               }
+               if (key == 0)
+                       zerocount++;
+       }
+       printf("OK\n");
+
+       printf("Test #2: successful key lookup (%u-bit).\n", bits);
+       zerocount = 0;
+       for (key = 0; key <= max_key && (key != 0 || zerocount < 1); key += 1ULL << (bits - 8)) {
+               struct cds_hlist_head head;
+
+               rcu_read_lock();
+               head = cds_ja_lookup(test_ja, key);
+               if (cds_hlist_empty(&head)) {
+                       fprintf(stderr, "Error lookup node %" PRIu64 "\n", key);
+                       assert(0);
+               }
+               rcu_read_unlock();
+               if (key == 0)
+                       zerocount++;
+       }
+       printf("OK\n");
+       if (bits > 8) {
+               printf("Test #3: unsuccessful key lookup (%u-bit).\n", bits);
+               zerocount = 0;
+               for (key = 0; key <= max_key && (key != 0 || zerocount < 1); key += 1ULL << (bits - 8)) {
+                       struct cds_hlist_head head;
+
+                       rcu_read_lock();
+                       head = cds_ja_lookup(test_ja, key + 42);
+                       if (!cds_hlist_empty(&head)) {
+                               fprintf(stderr,
+                                       "Error unexpected lookup node %" PRIu64 "\n",
+                                       key + 42);
+                               assert(0);
+                       }
+                       rcu_read_unlock();
+                       if (key == 0)
+                               zerocount++;
+               }
+               printf("OK\n");
+       }
+
+       ret = cds_ja_destroy(test_ja, free_node_cb);
+       if (ret) {
+               fprintf(stderr, "Error destroying judy array\n");
+               return -1;
+       }
+       printf("Test ends\n");
+
+       return 0;
+}
+
+
 int main(int argc, char **argv)
 {
        int err;
@@ -182,6 +433,7 @@ int main(int argc, char **argv)
                tot_add = 0, tot_add_exist = 0, tot_remove = 0;
        int i, a, ret;
        unsigned int remain;
+       uint64_t key;
 
        if (argc < 4) {
                show_usage(argc, argv);
@@ -300,32 +552,49 @@ int main(int argc, char **argv)
                printf("Per-CPU call_rcu() worker threads unavailable. Using default global worker thread.\n");
        }
 
-       /* Test with 8-bit key */
-       test_ja = cds_ja_new(8);
-       if (!test_ja) {
-               printf("Error allocating judy array.\n");
-               return -1;
-       }
+       rcu_register_thread();
 
-       /* Add keys */
-       for (i = 0; i < 200; i++) {
-               struct ja_test_node *node =
-                       calloc(sizeof(*node), 1);
+       printf("Test start.\n");
 
-               ja_test_node_init(node, i);
-               ret = cds_ja_add(test_ja, i, &node->node);
+       for (i = 0; i < 3; i++) {
+               ret = test_8bit_key();
                if (ret) {
-                       printf("Error adding node (%d)\n", ret);
-                       return -1;
+                       return ret;
                }
+               rcu_quiescent_state();
+       }
+       ret = test_16bit_key();
+       if (ret) {
+               return ret;
        }
+       rcu_quiescent_state();
 
-       ret = cds_ja_destroy(test_ja);
+       ret = test_sparse_key(8);
        if (ret) {
-               printf("Error destroying judy array\n");
-               return -1;
+               return ret;
        }
+       rcu_quiescent_state();
+
+       ret = test_sparse_key(16);
+       if (ret) {
+               return ret;
+       }
+       rcu_quiescent_state();
+
+       ret = test_sparse_key(32);
+       if (ret) {
+               return ret;
+       }
+       rcu_quiescent_state();
+
+       ret = test_sparse_key(64);
+       if (ret) {
+               return ret;
+       }
+       rcu_quiescent_state();
+
        printf("Test end.\n");
+       rcu_unregister_thread();
        return 0;
 
 #if 0
This page took 0.026208 seconds and 4 git commands to generate.