get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/44143/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 44143,
    "url": "http://patches.dpdk.org/api/patches/44143/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20180831165101.20026-1-qiaobinf@bu.edu/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20180831165101.20026-1-qiaobinf@bu.edu>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20180831165101.20026-1-qiaobinf@bu.edu",
    "date": "2018-08-31T16:51:01",
    "name": "[v3] hash table: add an iterator over conflicting entries",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "81034477e16cd05dc3445a24eb70134c5975a0fb",
    "submitter": {
        "id": 1064,
        "url": "http://patches.dpdk.org/api/people/1064/?format=api",
        "name": "Fu, Qiaobin",
        "email": "qiaobinf@bu.edu"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20180831165101.20026-1-qiaobinf@bu.edu/mbox/",
    "series": [
        {
            "id": 1147,
            "url": "http://patches.dpdk.org/api/series/1147/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=1147",
            "date": "2018-08-31T16:51:01",
            "name": "[v3] hash table: add an iterator over conflicting entries",
            "version": 3,
            "mbox": "http://patches.dpdk.org/series/1147/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/44143/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/44143/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id BA4671B065;\n\tFri, 31 Aug 2018 18:51:48 +0200 (CEST)",
            "from relay68.bu.edu (relay68.bu.edu [128.197.228.73])\n\tby dpdk.org (Postfix) with ESMTP id DD3901AFF7\n\tfor <dev@dpdk.org>; Fri, 31 Aug 2018 18:51:46 +0200 (CEST)",
            "from BU-AUTH (localhost.localdomain [127.0.0.1]) (authenticated\n\tbits=0)\n\tby relay68.bu.edu (8.14.3/8.14.3) with ESMTP id w7VGp24E003905\n\t(version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-GCM-SHA256 bits=128\n\tverify=NO); Fri, 31 Aug 2018 12:51:08 -0400"
        ],
        "X-Envelope-From": "qiaobinf@bu.edu",
        "X-BU-AUTH": "xia1.bu.edu [128.197.41.97]",
        "From": "Qiaobin Fu <qiaobinf@bu.edu>",
        "To": "bruce.richardson@intel.com, pablo.de.lara.guarch@intel.com",
        "Cc": "dev@dpdk.org, doucette@bu.edu, keith.wiles@intel.com,\n\tsameh.gobriel@intel.com, charlie.tai@intel.com,\n\tstephen@networkplumber.org, nd@arm.com, honnappa.nagarahalli@arm.com, \n\tyipeng1.wang@intel.com, michel@digirati.com.br, qiaobinf@bu.edu",
        "Date": "Fri, 31 Aug 2018 16:51:01 +0000",
        "Message-Id": "<20180831165101.20026-1-qiaobinf@bu.edu>",
        "X-Mailer": "git-send-email 2.17.1",
        "Subject": "[dpdk-dev] [PATCH v3] hash table: add an iterator over conflicting\n\tentries",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Function rte_hash_iterate_conflict_entries() iterates over\nthe entries that conflict with an incoming entry.\n\nIterating over conflicting entries enables one to decide\nif the incoming entry is more valuable than the entries already\nin the hash table. This is particularly useful after\nan insertion failure.\n\nv3:\n* Make the rte_hash_iterate() API similar to\n  rte_hash_iterate_conflict_entries()\n\nv2:\n* Fix the style issue\n\n* Make the API more universal\n\nSigned-off-by: Qiaobin Fu <qiaobinf@bu.edu>\nReviewed-by: Cody Doucette <doucette@bu.edu>\nReviewed-by: Michel Machado <michel@digirati.com.br>\nReviewed-by: Keith Wiles <keith.wiles@intel.com>\nReviewed-by: Yipeng Wang <yipeng1.wang@intel.com>\nReviewed-by: Honnappa Nagarahalli <honnappa.nagarahalli@arm.com>\n---\n lib/librte_hash/Makefile             |   1 +\n lib/librte_hash/rte_cuckoo_hash.c    | 132 +++++++++++++++++++++++----\n lib/librte_hash/rte_hash.h           |  80 ++++++++++++++--\n lib/librte_hash/rte_hash_version.map |   8 ++\n test/test/test_hash.c                |   7 +-\n test/test/test_hash_multiwriter.c    |   8 +-\n test/test/test_hash_readwrite.c      |  16 ++--\n 7 files changed, 219 insertions(+), 33 deletions(-)",
    "diff": "diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile\nindex c8c435dfd..9be58a205 100644\n--- a/lib/librte_hash/Makefile\n+++ b/lib/librte_hash/Makefile\n@@ -6,6 +6,7 @@ include $(RTE_SDK)/mk/rte.vars.mk\n # library name\n LIB = librte_hash.a\n \n+CFLAGS += -DALLOW_EXPERIMENTAL_API\n CFLAGS += -O3\n CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)\n LDLIBS += -lrte_eal -lrte_ring\ndiff --git a/lib/librte_hash/rte_cuckoo_hash.c b/lib/librte_hash/rte_cuckoo_hash.c\nindex f7b86c8c9..cf5b28196 100644\n--- a/lib/librte_hash/rte_cuckoo_hash.c\n+++ b/lib/librte_hash/rte_cuckoo_hash.c\n@@ -1300,45 +1300,143 @@ rte_hash_lookup_bulk_data(const struct rte_hash *h, const void **keys,\n \treturn __builtin_popcountl(*hit_mask);\n }\n \n+/* istate stands for internal state. */\n+struct rte_hash_iterator_istate {\n+\tconst struct rte_hash *h;\n+\tuint32_t              next;\n+\tuint32_t              total_entries;\n+};\n+\n+int32_t\n+rte_hash_iterator_init(const struct rte_hash *h,\n+\tstruct rte_hash_iterator_state *state)\n+{\n+\tstruct rte_hash_iterator_istate *__state;\n+\n+\tRETURN_IF_TRUE(((h == NULL) || (state == NULL)), -EINVAL);\n+\n+\t__state = (struct rte_hash_iterator_istate *)state;\n+\t__state->h = h;\n+\t__state->next = 0;\n+\t__state->total_entries = h->num_buckets * RTE_HASH_BUCKET_ENTRIES;\n+\n+\treturn 0;\n+}\n+\n int32_t\n-rte_hash_iterate(const struct rte_hash *h, const void **key, void **data, uint32_t *next)\n+rte_hash_iterate(\n+\tstruct rte_hash_iterator_state *state, const void **key, void **data)\n {\n+\tstruct rte_hash_iterator_istate *__state;\n \tuint32_t bucket_idx, idx, position;\n \tstruct rte_hash_key *next_key;\n \n-\tRETURN_IF_TRUE(((h == NULL) || (next == NULL)), -EINVAL);\n+\tRETURN_IF_TRUE(((state == NULL) || (key == NULL) ||\n+\t\t(data == NULL)), -EINVAL);\n+\n+\t__state = (struct rte_hash_iterator_istate *)state;\n \n-\tconst uint32_t total_entries = h->num_buckets * RTE_HASH_BUCKET_ENTRIES;\n \t/* Out of bounds */\n-\tif (*next >= total_entries)\n+\tif (__state->next >= __state->total_entries)\n \t\treturn -ENOENT;\n \n \t/* Calculate bucket and index of current iterator */\n-\tbucket_idx = *next / RTE_HASH_BUCKET_ENTRIES;\n-\tidx = *next % RTE_HASH_BUCKET_ENTRIES;\n+\tbucket_idx = __state->next / RTE_HASH_BUCKET_ENTRIES;\n+\tidx = __state->next % RTE_HASH_BUCKET_ENTRIES;\n \n \t/* If current position is empty, go to the next one */\n-\twhile (h->buckets[bucket_idx].key_idx[idx] == EMPTY_SLOT) {\n-\t\t(*next)++;\n+\twhile (__state->h->buckets[bucket_idx].key_idx[idx] == EMPTY_SLOT) {\n+\t\t__state->next++;\n \t\t/* End of table */\n-\t\tif (*next == total_entries)\n+\t\tif (__state->next == __state->total_entries)\n \t\t\treturn -ENOENT;\n-\t\tbucket_idx = *next / RTE_HASH_BUCKET_ENTRIES;\n-\t\tidx = *next % RTE_HASH_BUCKET_ENTRIES;\n+\t\tbucket_idx = __state->next / RTE_HASH_BUCKET_ENTRIES;\n+\t\tidx = __state->next % RTE_HASH_BUCKET_ENTRIES;\n \t}\n-\t__hash_rw_reader_lock(h);\n+\t__hash_rw_reader_lock(__state->h);\n \t/* Get position of entry in key table */\n-\tposition = h->buckets[bucket_idx].key_idx[idx];\n-\tnext_key = (struct rte_hash_key *) ((char *)h->key_store +\n-\t\t\t\tposition * h->key_entry_size);\n+\tposition = __state->h->buckets[bucket_idx].key_idx[idx];\n+\tnext_key = (struct rte_hash_key *) ((char *)__state->h->key_store +\n+\t\t\t\tposition * __state->h->key_entry_size);\n \t/* Return key and data */\n \t*key = next_key->key;\n \t*data = next_key->pdata;\n \n-\t__hash_rw_reader_unlock(h);\n+\t__hash_rw_reader_unlock(__state->h);\n \n \t/* Increment iterator */\n-\t(*next)++;\n+\t__state->next++;\n \n \treturn position - 1;\n }\n+\n+/* istate stands for internal state. */\n+struct rte_hash_iterator_conflict_entries_istate {\n+\tconst struct rte_hash *h;\n+\tuint32_t              vnext;\n+\tuint32_t              primary_bidx;\n+\tuint32_t              secondary_bidx;\n+};\n+\n+int32_t __rte_experimental\n+rte_hash_iterator_conflict_entries_init_with_hash(const struct rte_hash *h,\n+\thash_sig_t sig, struct rte_hash_iterator_state *state)\n+{\n+\tstruct rte_hash_iterator_conflict_entries_istate *__state;\n+\n+\tRETURN_IF_TRUE(((h == NULL) || (state == NULL)), -EINVAL);\n+\n+\t__state = (struct rte_hash_iterator_conflict_entries_istate *)state;\n+\t__state->h = h;\n+\t__state->vnext = 0;\n+\n+\t/* Get the primary bucket index given the precomputed hash value. */\n+\t__state->primary_bidx = sig & h->bucket_bitmask;\n+\t/* Get the secondary bucket index given the precomputed hash value. */\n+\t__state->secondary_bidx =\n+\t\trte_hash_secondary_hash(sig) & h->bucket_bitmask;\n+\n+\treturn 0;\n+}\n+\n+int32_t __rte_experimental\n+rte_hash_iterate_conflict_entries(\n+\tstruct rte_hash_iterator_state *state, const void **key, void **data)\n+{\n+\tstruct rte_hash_iterator_conflict_entries_istate *__state;\n+\n+\tRETURN_IF_TRUE(((state == NULL) || (key == NULL) ||\n+\t\t(data == NULL)), -EINVAL);\n+\n+\t__state = (struct rte_hash_iterator_conflict_entries_istate *)state;\n+\n+\twhile (__state->vnext < RTE_HASH_BUCKET_ENTRIES * 2) {\n+\t\tuint32_t bidx = __state->vnext < RTE_HASH_BUCKET_ENTRIES ?\n+\t\t\t__state->primary_bidx : __state->secondary_bidx;\n+\t\tuint32_t next = __state->vnext & (RTE_HASH_BUCKET_ENTRIES - 1);\n+\t\tuint32_t position = __state->h->buckets[bidx].key_idx[next];\n+\t\tstruct rte_hash_key *next_key;\n+\n+\t\t/* Increment iterator. */\n+\t\t__state->vnext++;\n+\n+\t\t/*\n+\t\t * The test below is unlikely because this iterator is meant\n+\t\t * to be used after a failed insert.\n+\t\t */\n+\t\tif (unlikely(position == EMPTY_SLOT))\n+\t\t\tcontinue;\n+\n+\t\t/* Get the entry in key table. */\n+\t\tnext_key = (struct rte_hash_key *) (\n+\t\t\t(char *)__state->h->key_store +\n+\t\t\tposition * __state->h->key_entry_size);\n+\t\t/* Return key and data. */\n+\t\t*key = next_key->key;\n+\t\t*data = next_key->pdata;\n+\n+\t\treturn position - 1;\n+\t}\n+\n+\treturn -ENOENT;\n+}\ndiff --git a/lib/librte_hash/rte_hash.h b/lib/librte_hash/rte_hash.h\nindex 9e7d9315f..fdb01023e 100644\n--- a/lib/librte_hash/rte_hash.h\n+++ b/lib/librte_hash/rte_hash.h\n@@ -14,6 +14,8 @@\n #include <stdint.h>\n #include <stddef.h>\n \n+#include <rte_compat.h>\n+\n #ifdef __cplusplus\n extern \"C\" {\n #endif\n@@ -64,6 +66,16 @@ struct rte_hash_parameters {\n /** @internal A hash table structure. */\n struct rte_hash;\n \n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * @internal A hash table iterator state structure.\n+ */\n+struct rte_hash_iterator_state {\n+\tuint8_t space[64];\n+} __rte_cache_aligned;\n+\n /**\n  * Create a new hash table.\n  *\n@@ -443,26 +455,82 @@ rte_hash_lookup_bulk(const struct rte_hash *h, const void **keys,\n \t\t      uint32_t num_keys, int32_t *positions);\n \n /**\n- * Iterate through the hash table, returning key-value pairs.\n+ * Initialize the iterator over the hash table.\n  *\n  * @param h\n- *   Hash table to iterate\n+ *   Hash table to iterate.\n+ * @param state\n+ *   Pointer to the iterator state.\n+ * @return\n+ *   - 0 if successful.\n+ *   - -EINVAL if the parameters are invalid.\n+ */\n+int32_t\n+rte_hash_iterator_init(const struct rte_hash *h,\n+\tstruct rte_hash_iterator_state *state);\n+\n+/**\n+ * Iterate through the hash table, returning key-value pairs.\n+ *\n+ * @param state\n+ *   Pointer to the iterator state.\n  * @param key\n  *   Output containing the key where current iterator\n  *   was pointing at\n  * @param data\n  *   Output containing the data associated with key.\n  *   Returns NULL if data was not stored.\n- * @param next\n- *   Pointer to iterator. Should be 0 to start iterating the hash table.\n- *   Iterator is incremented after each call of this function.\n  * @return\n  *   Position where key was stored, if successful.\n  *   - -EINVAL if the parameters are invalid.\n  *   - -ENOENT if end of the hash table.\n  */\n int32_t\n-rte_hash_iterate(const struct rte_hash *h, const void **key, void **data, uint32_t *next);\n+rte_hash_iterate(\n+\tstruct rte_hash_iterator_state *state, const void **key, void **data);\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Initialize the iterator over entries that conflict with a given hash.\n+ *\n+ * @param h\n+ *   Hash table to iterate.\n+ * @param sig\n+ *   Precomputed hash value with which the returning entries conflict.\n+ * @param state\n+ *   Pointer to the iterator state.\n+ * @return\n+ *   - 0 if successful.\n+ *   - -EINVAL if the parameters are invalid.\n+ */\n+int32_t __rte_experimental\n+rte_hash_iterator_conflict_entries_init_with_hash(const struct rte_hash *h,\n+\thash_sig_t sig, struct rte_hash_iterator_state *state);\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice.\n+ *\n+ * Iterate over entries that conflict with a given hash.\n+ *\n+ * @param state\n+ *   Pointer to the iterator state.\n+ * @param key\n+ *   Output containing the key at where the iterator is currently pointing.\n+ * @param data\n+ *   Output containing the data associated with key.\n+ *   Returns NULL if data was not stored.\n+ * @return\n+ *   Position where key was stored, if successful.\n+ *   - -EINVAL if the parameters are invalid.\n+ *   - -ENOENT if there is no more conflicting entries.\n+ */\n+int32_t __rte_experimental\n+rte_hash_iterate_conflict_entries(\n+\tstruct rte_hash_iterator_state *state, const void **key, void **data);\n+\n #ifdef __cplusplus\n }\n #endif\ndiff --git a/lib/librte_hash/rte_hash_version.map b/lib/librte_hash/rte_hash_version.map\nindex e216ac8e2..301d4638c 100644\n--- a/lib/librte_hash/rte_hash_version.map\n+++ b/lib/librte_hash/rte_hash_version.map\n@@ -24,6 +24,7 @@ DPDK_2.1 {\n \n \trte_hash_add_key_data;\n \trte_hash_add_key_with_hash_data;\n+\trte_hash_iterator_init;\n \trte_hash_iterate;\n \trte_hash_lookup_bulk_data;\n \trte_hash_lookup_data;\n@@ -53,3 +54,10 @@ DPDK_18.08 {\n \trte_hash_count;\n \n } DPDK_16.07;\n+\n+EXPERIMENTAL {\n+\tglobal:\n+\n+\trte_hash_iterator_conflict_entries_init_with_hash;\n+\trte_hash_iterate_conflict_entries;\n+};\ndiff --git a/test/test/test_hash.c b/test/test/test_hash.c\nindex b3db9fd10..bf57004c3 100644\n--- a/test/test/test_hash.c\n+++ b/test/test/test_hash.c\n@@ -1170,8 +1170,8 @@ static int test_hash_iteration(void)\n \tvoid *next_data;\n \tvoid *data[NUM_ENTRIES];\n \tunsigned added_keys;\n-\tuint32_t iter = 0;\n \tint ret = 0;\n+\tstruct rte_hash_iterator_state state;\n \n \tut_params.entries = NUM_ENTRIES;\n \tut_params.name = \"test_hash_iteration\";\n@@ -1180,6 +1180,9 @@ static int test_hash_iteration(void)\n \thandle = rte_hash_create(&ut_params);\n \tRETURN_IF_ERROR(handle == NULL, \"hash creation failed\");\n \n+\tRETURN_IF_ERROR(rte_hash_iterator_init(handle, &state) != 0,\n+\t\t\t\"initialization of the hash iterator failed\");\n+\n \t/* Add random entries until key cannot be added */\n \tfor (added_keys = 0; added_keys < NUM_ENTRIES; added_keys++) {\n \t\tdata[added_keys] = (void *) ((uintptr_t) rte_rand());\n@@ -1191,7 +1194,7 @@ static int test_hash_iteration(void)\n \t}\n \n \t/* Iterate through the hash table */\n-\twhile (rte_hash_iterate(handle, &next_key, &next_data, &iter) >= 0) {\n+\twhile (rte_hash_iterate(&state, &next_key, &next_data) >= 0) {\n \t\t/* Search for the key in the list of keys added */\n \t\tfor (i = 0; i < NUM_ENTRIES; i++) {\n \t\t\tif (memcmp(next_key, keys[i], ut_params.key_len) == 0) {\ndiff --git a/test/test/test_hash_multiwriter.c b/test/test/test_hash_multiwriter.c\nindex 6a3eb10bd..48db8007d 100644\n--- a/test/test/test_hash_multiwriter.c\n+++ b/test/test/test_hash_multiwriter.c\n@@ -125,18 +125,22 @@ test_hash_multiwriter(void)\n \n \tconst void *next_key;\n \tvoid *next_data;\n-\tuint32_t iter = 0;\n \n \tuint32_t duplicated_keys = 0;\n \tuint32_t lost_keys = 0;\n \tuint32_t count;\n \n+\tstruct rte_hash_iterator_state state;\n+\n \tsnprintf(name, 32, \"test%u\", calledCount++);\n \thash_params.name = name;\n \n \thandle = rte_hash_create(&hash_params);\n \tRETURN_IF_ERROR(handle == NULL, \"hash creation failed\");\n \n+\tRETURN_IF_ERROR(rte_hash_iterator_init(handle, &state) != 0,\n+\t\t\t\"initialization of the hash iterator failed\");\n+\n \ttbl_multiwriter_test_params.h = handle;\n \ttbl_multiwriter_test_params.nb_tsx_insertion =\n \t\tnb_total_tsx_insertion / rte_lcore_count();\n@@ -203,7 +207,7 @@ test_hash_multiwriter(void)\n \t\tgoto err3;\n \t}\n \n-\twhile (rte_hash_iterate(handle, &next_key, &next_data, &iter) >= 0) {\n+\twhile (rte_hash_iterate(&state, &next_key, &next_data) >= 0) {\n \t\t/* Search for the key in the list of keys added .*/\n \t\ti = *(const uint32_t *)next_key;\n \t\ttbl_multiwriter_test_params.found[i]++;\ndiff --git a/test/test/test_hash_readwrite.c b/test/test/test_hash_readwrite.c\nindex 55ae33d80..9cdab9992 100644\n--- a/test/test/test_hash_readwrite.c\n+++ b/test/test/test_hash_readwrite.c\n@@ -166,12 +166,13 @@ test_hash_readwrite_functional(int use_htm)\n \tunsigned int i;\n \tconst void *next_key;\n \tvoid *next_data;\n-\tuint32_t iter = 0;\n \n \tuint32_t duplicated_keys = 0;\n \tuint32_t lost_keys = 0;\n \tint use_jhash = 1;\n \n+\tstruct rte_hash_iterator_state state;\n+\n \trte_atomic64_init(&gcycles);\n \trte_atomic64_clear(&gcycles);\n \n@@ -188,6 +189,8 @@ test_hash_readwrite_functional(int use_htm)\n \t\ttbl_rw_test_param.num_insert\n \t\t* rte_lcore_count();\n \n+\trte_hash_iterator_init(tbl_rw_test_param.h, &state);\n+\n \tprintf(\"++++++++Start function tests:+++++++++\\n\");\n \n \t/* Fire all threads. */\n@@ -195,8 +198,7 @@ test_hash_readwrite_functional(int use_htm)\n \t\t\t\t NULL, CALL_MASTER);\n \trte_eal_mp_wait_lcore();\n \n-\twhile (rte_hash_iterate(tbl_rw_test_param.h, &next_key,\n-\t\t\t&next_data, &iter) >= 0) {\n+\twhile (rte_hash_iterate(&state, &next_key, &next_data) >= 0) {\n \t\t/* Search for the key in the list of keys added .*/\n \t\ti = *(const uint32_t *)next_key;\n \t\ttbl_rw_test_param.found[i]++;\n@@ -315,9 +317,10 @@ test_hash_readwrite_perf(struct perf *perf_results, int use_htm,\n \n \tconst void *next_key;\n \tvoid *next_data;\n-\tuint32_t iter = 0;\n \tint use_jhash = 0;\n \n+\tstruct rte_hash_iterator_state state;\n+\n \tuint32_t duplicated_keys = 0;\n \tuint32_t lost_keys = 0;\n \n@@ -336,6 +339,8 @@ test_hash_readwrite_perf(struct perf *perf_results, int use_htm,\n \tif (init_params(use_htm, use_jhash) != 0)\n \t\tgoto err;\n \n+\trte_hash_iterator_init(tbl_rw_test_param.h, &state);\n+\n \t/*\n \t * Do a readers finish faster or writers finish faster test.\n \t * When readers finish faster, we timing the readers, and when writers\n@@ -484,8 +489,7 @@ test_hash_readwrite_perf(struct perf *perf_results, int use_htm,\n \n \t\trte_eal_mp_wait_lcore();\n \n-\t\twhile (rte_hash_iterate(tbl_rw_test_param.h,\n-\t\t\t\t&next_key, &next_data, &iter) >= 0) {\n+\t\twhile (rte_hash_iterate(&state, &next_key, &next_data) >= 0) {\n \t\t\t/* Search for the key in the list of keys added .*/\n \t\t\ti = *(const uint32_t *)next_key;\n \t\t\ttbl_rw_test_param.found[i]++;\n",
    "prefixes": [
        "v3"
    ]
}