From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from EUR02-HE1-obe.outbound.protection.outlook.com (mail-eopbgr10071.outbound.protection.outlook.com [40.107.1.71]) by dpdk.org (Postfix) with ESMTP id 3A9544CB3 for ; Mon, 3 Sep 2018 00:05:42 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector1-arm-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Zw4iEj1DEtfqpxM4cwgXaL8mSoLXyOUUudrDV/ROSa4=; b=pCfLaiGH2r4xth5XEzLmqBrFv9OR9EkhDGST4gywkGQUz3JbkOepZfs1HVXiFM41wWS8g98CaMnmHPgzp2JVJQw4wObdIXlyX22P+UaqrRl7KdMElpLLIr7HzchWzog7EMDsyMu7rb1JVKmLAsnthp8la1/b1+8o1+6oWnjQKXo= Received: from AM6PR08MB3672.eurprd08.prod.outlook.com (20.177.115.29) by AM6PR08MB3128.eurprd08.prod.outlook.com (52.135.164.13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1101.16; Sun, 2 Sep 2018 22:05:40 +0000 Received: from AM6PR08MB3672.eurprd08.prod.outlook.com ([fe80::649b:b10d:ef69:7fd2]) by AM6PR08MB3672.eurprd08.prod.outlook.com ([fe80::649b:b10d:ef69:7fd2%4]) with mapi id 15.20.1080.015; Sun, 2 Sep 2018 22:05:40 +0000 From: Honnappa Nagarahalli To: Qiaobin Fu , "bruce.richardson@intel.com" , "pablo.de.lara.guarch@intel.com" CC: "dev@dpdk.org" , "doucette@bu.edu" , "keith.wiles@intel.com" , "sameh.gobriel@intel.com" , "charlie.tai@intel.com" , "stephen@networkplumber.org" , nd , "yipeng1.wang@intel.com" , "michel@digirati.com.br" Thread-Topic: [PATCH v3] hash table: add an iterator over conflicting entries Thread-Index: AQHUQUrktx3ADshLHUm/2g6PS6B8FKTdbJBQ Date: Sun, 2 Sep 2018 22:05:40 +0000 Message-ID: References: <20180831165101.20026-1-qiaobinf@bu.edu> In-Reply-To: <20180831165101.20026-1-qiaobinf@bu.edu> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: spf=none (sender IP is ) smtp.mailfrom=Honnappa.Nagarahalli@arm.com; x-originating-ip: [213.120.252.178] x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1; AM6PR08MB3128; 6:b5MoKTiFzu3nPO89oG+qI8pfBsBubiGfsop5JW6Y5FKpZ3oD3upagqSsWDT+Ld9RxBwlKc62Vj/MhmE57bL7EPfzifFQu08mqcmjfMzhmHuPf1PFSiN/bQbvhInTfV+O05ibptUfwTqbNPtBiRaGDVa2ur5HUsaPjJAPgdqAs6NbI10TzmzaVZy6D5qqwMjANArvoKqBdotvSfOCwQ8lfb3Y4K9JwVfdLL2XxYNuj8pZGZfRfy9J5wufV1Hw8/GudaVIWpGPjh75vRaCye9oq7hWC8KCB92AB2v6RR6t7Mix+Z2mtGQwjxUzAmWbOubngULGtt8rzxr+Usz1LMCFOGmniHeEg+1zMeCaGoICT56os+n3RHLaZoT/q1WPIGtEywDhwf1moqC+neC34VIP6a1tkbrX97tvZ1/1icxphuT6wjk4tmyMx9lXAGh04w5FDq7CqKm1MFOwJ0k88GSmHA==; 5:9Ezs0N0eSHOqUXSoqtoRclARY5uETGWWeTrm3ulgjB+9Qv3ZrmRpHaQuFKIr4IoudUzFMZ3D9NniUmeT7/PCowcLxPOR48Z1qS3k5p5AGz9Pt0RWqB//yJU+wTAr2iHM12fChldfnN6shcYCm02uVVsFKEQ9E/HJ7Wtjjd2JQU4=; 7:tJs6p0xr6luYyz0pcHAvcnAnkhzCd6tK5FFnHyNC/91hu81Hcbq+vGTO2mO0bhpk8/auYNWGiXDYtl3DUYD8hMyIH/acvwFC/X17cJuzDxL3hWHMx8lBIMTxNFHoj5H/FNFrx7DcC2eNfaykr27fkoAJkODoAQaiWeznLsuAWml3VH/uOsnjUvUdAXmr6DKiidP4dpuHx2eNJ1ZqKcnBsic948Zuw45h2ScO3Thsg3Nt9uPTywehDxBDdks6VkPq x-ms-exchange-antispam-srfa-diagnostics: SOS; x-ms-office365-filtering-correlation-id: 3f694704-c64e-48b3-8ab0-08d611203882 x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: BCL:0; PCL:0; RULEID:(7020095)(4652040)(8989137)(4534165)(4627221)(201703031133081)(201702281549075)(8990107)(5600074)(711020)(4618075)(2017052603328)(7153060)(7193020); SRVR:AM6PR08MB3128; x-ms-traffictypediagnostic: AM6PR08MB3128: nodisclaimer: True x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:(180628864354917)(238701278423138)(166494164430575)(228905959029699)(17755550239193); x-ms-exchange-senderadcheck: 1 x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(5005006)(8121501046)(823301075)(10201501046)(3002001)(93006095)(93001095)(3231311)(944501410)(52105095)(6055026)(149027)(150027)(6041310)(20161123558120)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123562045)(20161123564045)(20161123560045)(201708071742011)(7699016); SRVR:AM6PR08MB3128; BCL:0; PCL:0; RULEID:; SRVR:AM6PR08MB3128; x-forefront-prvs: 078310077C x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(39850400004)(136003)(366004)(376002)(346002)(396003)(13464003)(189003)(199004)(6436002)(99286004)(2906002)(68736007)(14454004)(8676002)(25786009)(2900100001)(2501003)(4326008)(3846002)(6116002)(33656002)(55016002)(81166006)(81156014)(229853002)(97736004)(53946003)(9686003)(53936002)(2171002)(6306002)(5250100002)(6246003)(8936002)(476003)(105586002)(106356001)(446003)(11346002)(966005)(72206003)(76176011)(14444005)(256004)(486006)(66066001)(7696005)(7416002)(2201001)(345774005)(316002)(102836004)(6506007)(53546011)(5660300001)(305945005)(7736002)(54906003)(110136005)(86362001)(186003)(74316002)(26005)(478600001); DIR:OUT; SFP:1101; SCL:1; SRVR:AM6PR08MB3128; H:AM6PR08MB3672.eurprd08.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; MX:1; A:1; received-spf: None (protection.outlook.com: arm.com does not designate permitted sender hosts) x-microsoft-antispam-message-info: UXsITZa88+08+x66Jpkx26qXVoxeMjgdiZ2mEeDFFOdK/AVJk1Ef0GAh9/VJy3Frwe5Zli7I6mNvTHhQPaEqi+ysv5CcT7nxYyTMx3WUbAO41qk2LeH47s8EepiaTjjv76Osp07SyJGig9GQe8tU8deEBHYOmYKz1ZVRxznC+8SRiZ7rD/x9Uv6INDGPzW5Gazgpp9QIPyBHQbtFC8NQF6M9fFrM35yzPagZ9Nd/zq4tqrs9BfRO/2Nppu4T4m5idF9COyDagkVSzh8QK2yLfRxpj4XgJZeODyzHJobplziCYiJ7AxiVmYDJG05MiXjSLB+Y63nY93O2cvT5IXHtgvvRns/YZbPLZtKA46vpHbM= spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-Network-Message-Id: 3f694704-c64e-48b3-8ab0-08d611203882 X-MS-Exchange-CrossTenant-originalarrivaltime: 02 Sep 2018 22:05:40.3588 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM6PR08MB3128 Subject: Re: [dpdk-dev] [PATCH v3] hash table: add an iterator over conflicting entries X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 02 Sep 2018 22:05:42 -0000 Hi Qiaobin, Thank you for the patch. Please see few comments inline. -----Original Message----- From: Qiaobin Fu =20 Sent: Friday, August 31, 2018 11:51 AM To: bruce.richardson@intel.com; pablo.de.lara.guarch@intel.com Cc: dev@dpdk.org; doucette@bu.edu; keith.wiles@intel.com; sameh.gobriel@int= el.com; charlie.tai@intel.com; stephen@networkplumber.org; nd ;= Honnappa Nagarahalli ; yipeng1.wang@intel.co= m; michel@digirati.com.br; qiaobinf@bu.edu Subject: [PATCH v3] hash table: add an iterator over conflicting entries Function rte_hash_iterate_conflict_entries() iterates over the entries that= conflict with an incoming entry. Iterating over conflicting entries enables one to decide if the incoming en= try is more valuable than the entries already in the hash table. This is pa= rticularly useful after an insertion failure. v3: * Make the rte_hash_iterate() API similar to rte_hash_iterate_conflict_entries() v2: * Fix the style issue * Make the API more universal Signed-off-by: Qiaobin Fu Reviewed-by: Cody Doucette Reviewed-by: Michel Machado Reviewed-by: Keith Wiles Reviewed-by: Yipeng Wang Reviewed-by: Honnappa Nagarahalli --- lib/librte_hash/Makefile | 1 + lib/librte_hash/rte_cuckoo_hash.c | 132 +++++++++++++++++++++++---- lib/librte_hash/rte_hash.h | 80 ++++++++++++++-- lib/librte_hash/rte_hash_version.map | 8 ++ test/test/test_hash.c | 7 +- test/test/test_hash_multiwriter.c | 8 +- test/test/test_hash_readwrite.c | 16 ++-- 7 files changed, 219 insertions(+), 33 deletions(-) diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile index c8c4= 35dfd..9be58a205 100644 --- a/lib/librte_hash/Makefile +++ b/lib/librte_hash/Makefile @@ -6,6 +6,7 @@ include $(RTE_SDK)/mk/rte.vars.mk # library name LIB =3D = librte_hash.a =20 +CFLAGS +=3D -DALLOW_EXPERIMENTAL_API CFLAGS +=3D -O3 CFLAGS +=3D $(WERROR_FLAGS) -I$(SRCDIR) LDLIBS +=3D -lrte_eal -lrte_ring diff --git a/lib/librte_hash/rte_cuckoo_hash.c b/lib/librte_hash/rte_cuckoo= _hash.c index f7b86c8c9..cf5b28196 100644 --- a/lib/librte_hash/rte_cuckoo_hash.c +++ b/lib/librte_hash/rte_cuckoo_hash.c @@ -1300,45 +1300,143 @@ rte_hash_lookup_bulk_data(const struct rte_hash *h= , const void **keys, return __builtin_popcountl(*hit_mask); } =20 +/* istate stands for internal state. */ struct rte_hash_iterator_istate=20 +{ + const struct rte_hash *h; This can be outside of this structure. This will help keep the API definiti= ons consistent with existing APIs. Please see further comments below. + uint32_t next; + uint32_t total_entries; +}; This structure can be moved to rte_cuckoo_hash.h file. + +int32_t +rte_hash_iterator_init(const struct rte_hash *h, + struct rte_hash_iterator_state *state) { + struct rte_hash_iterator_istate *__state; '__state' can be replaced by 's'. + + RETURN_IF_TRUE(((h =3D=3D NULL) || (state =3D=3D NULL)), -EINVAL); + + __state =3D (struct rte_hash_iterator_istate *)state; + __state->h =3D h; + __state->next =3D 0; + __state->total_entries =3D h->num_buckets * RTE_HASH_BUCKET_ENTRIES; + + return 0; +} IMO, creating this API can be avoided if the initialization is handled in '= rte_hash_iterate' function. The cost of doing this is very trivial (one ext= ra 'if' statement) in 'rte_hash_iterate' function. It will help keep the nu= mber of APIs to minimal. + int32_t -rte_hash_iterate(const struct rte_hash *h, const void **key, void **data, = uint32_t *next) +rte_hash_iterate( + struct rte_hash_iterator_state *state, const void **key, void **data) IMO, as suggested above, do not store 'struct rte_hash *h' in 'struct rte_h= ash_iterator_state'. Instead, change the API definition as follows: rte_hash_iterate(const struct rte_hash *h, const void **key, void **data, s= truct rte_hash_iterator_state *state) This will help keep the API signature consistent with existing APIs. This is an ABI change. Please take a look at https://doc.dpdk.org/guides/co= ntributing/versioning.html. { + struct rte_hash_iterator_istate *__state; '__state' can be replaced with 's'. uint32_t bucket_idx, idx, position; struct rte_hash_key *next_key; =20 - RETURN_IF_TRUE(((h =3D=3D NULL) || (next =3D=3D NULL)), -EINVAL); + RETURN_IF_TRUE(((state =3D=3D NULL) || (key =3D=3D NULL) || + (data =3D=3D NULL)), -EINVAL); + + __state =3D (struct rte_hash_iterator_istate *)state; =20 - const uint32_t total_entries =3D h->num_buckets * RTE_HASH_BUCKET_ENTRIES= ; /* Out of bounds */ - if (*next >=3D total_entries) + if (__state->next >=3D __state->total_entries) return -ENOENT; =20 'if (__state->next =3D=3D 0)' is required to avoid creating 'rte_hash_itera= tor_init' API. /* Calculate bucket and index of current iterator */ - bucket_idx =3D *next / RTE_HASH_BUCKET_ENTRIES; - idx =3D *next % RTE_HASH_BUCKET_ENTRIES; + bucket_idx =3D __state->next / RTE_HASH_BUCKET_ENTRIES; + idx =3D __state->next % RTE_HASH_BUCKET_ENTRIES; =20 /* If current position is empty, go to the next one */ - while (h->buckets[bucket_idx].key_idx[idx] =3D=3D EMPTY_SLOT) { - (*next)++; + while (__state->h->buckets[bucket_idx].key_idx[idx] =3D=3D EMPTY_SLOT) { + __state->next++; /* End of table */ - if (*next =3D=3D total_entries) + if (__state->next =3D=3D __state->total_entries) return -ENOENT; - bucket_idx =3D *next / RTE_HASH_BUCKET_ENTRIES; - idx =3D *next % RTE_HASH_BUCKET_ENTRIES; + bucket_idx =3D __state->next / RTE_HASH_BUCKET_ENTRIES; + idx =3D __state->next % RTE_HASH_BUCKET_ENTRIES; } - __hash_rw_reader_lock(h); + __hash_rw_reader_lock(__state->h); /* Get position of entry in key table */ - position =3D h->buckets[bucket_idx].key_idx[idx]; - next_key =3D (struct rte_hash_key *) ((char *)h->key_store + - position * h->key_entry_size); + position =3D __state->h->buckets[bucket_idx].key_idx[idx]; + next_key =3D (struct rte_hash_key *) ((char *)__state->h->key_store + + position * __state->h->key_entry_size); /* Return key and data */ *key =3D next_key->key; *data =3D next_key->pdata; =20 - __hash_rw_reader_unlock(h); + __hash_rw_reader_unlock(__state->h); =20 /* Increment iterator */ - (*next)++; + __state->next++; This comment is not related to this change, it is better to place this insi= de the lock. =20 return position - 1; } + +/* istate stands for internal state. */ struct=20 +rte_hash_iterator_conflict_entries_istate { + const struct rte_hash *h; This can be moved outside of this structure.=20 + uint32_t vnext; + uint32_t primary_bidx; + uint32_t secondary_bidx; +}; + +int32_t __rte_experimental +rte_hash_iterator_conflict_entries_init_with_hash(const struct rte_hash *h= , + hash_sig_t sig, struct rte_hash_iterator_state *state) { + struct rte_hash_iterator_conflict_entries_istate *__state; + + RETURN_IF_TRUE(((h =3D=3D NULL) || (state =3D=3D NULL)), -EINVAL); + + __state =3D (struct rte_hash_iterator_conflict_entries_istate *)state; + __state->h =3D h; + __state->vnext =3D 0; + + /* Get the primary bucket index given the precomputed hash value. */ + __state->primary_bidx =3D sig & h->bucket_bitmask; + /* Get the secondary bucket index given the precomputed hash value. */ + __state->secondary_bidx =3D + rte_hash_secondary_hash(sig) & h->bucket_bitmask; + + return 0; +} IMO, as mentioned above, it is possible to avoid creating this API. + +int32_t __rte_experimental +rte_hash_iterate_conflict_entries( + struct rte_hash_iterator_state *state, const void **key, void **data)=20 Signature of this API can be changed as follows: rte_hash_iterate_conflict_entries( struct rte_hash *h, const void **key, void **data, struct rte_hash_iterato= r_state *state) +{ + struct rte_hash_iterator_conflict_entries_istate *__state; + + RETURN_IF_TRUE(((state =3D=3D NULL) || (key =3D=3D NULL) || + (data =3D=3D NULL)), -EINVAL); + + __state =3D (struct rte_hash_iterator_conflict_entries_istate *)state; + + while (__state->vnext < RTE_HASH_BUCKET_ENTRIES * 2) { + uint32_t bidx =3D __state->vnext < RTE_HASH_BUCKET_ENTRIES ? + __state->primary_bidx : __state->secondary_bidx; + uint32_t next =3D __state->vnext & (RTE_HASH_BUCKET_ENTRIES - 1); take the reader lock before reading bucket entry + uint32_t position =3D __state->h->buckets[bidx].key_idx[next]; + struct rte_hash_key *next_key; + + /* Increment iterator. */ + __state->vnext++; + + /* + * The test below is unlikely because this iterator is meant + * to be used after a failed insert. + */ + if (unlikely(position =3D=3D EMPTY_SLOT)) + continue; + + /* Get the entry in key table. */ + next_key =3D (struct rte_hash_key *) ( + (char *)__state->h->key_store + + position * __state->h->key_entry_size); + /* Return key and data. */ + *key =3D next_key->key; + *data =3D next_key->pdata; give the reader lock + + return position - 1; + } + + return -ENOENT; +} diff --git a/lib/librte_hash/rte_hash.h b/lib/librte_hash/rte_hash.h index = 9e7d9315f..fdb01023e 100644 --- a/lib/librte_hash/rte_hash.h +++ b/lib/librte_hash/rte_hash.h @@ -14,6 +14,8 @@ #include #include =20 +#include + #ifdef __cplusplus extern "C" { #endif @@ -64,6 +66,16 @@ struct rte_hash_parameters { /** @internal A hash table structure. */ struct rte_hash; =20 +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * @internal A hash table iterator state structure. + */ +struct rte_hash_iterator_state { + uint8_t space[64]; I would call this 'state'. 64 can be replaced by 'RTE_CACHE_LINE_SIZE'. +} __rte_cache_aligned; + /** * Create a new hash table. * @@ -443,26 +455,82 @@ rte_hash_lookup_bulk(const struct rte_hash *h, const = void **keys, uint32_t num_keys, int32_t *positions); =20 /** - * Iterate through the hash table, returning key-value pairs. + * Initialize the iterator over the hash table. * * @param h - * Hash table to iterate + * Hash table to iterate. + * @param state + * Pointer to the iterator state. + * @return + * - 0 if successful. + * - -EINVAL if the parameters are invalid. + */ +int32_t +rte_hash_iterator_init(const struct rte_hash *h, + struct rte_hash_iterator_state *state); + +/** + * Iterate through the hash table, returning key-value pairs. + * + * @param state + * Pointer to the iterator state. * @param key * Output containing the key where current iterator * was pointing at * @param data * Output containing the data associated with key. * Returns NULL if data was not stored. - * @param next - * Pointer to iterator. Should be 0 to start iterating the hash table. - * Iterator is incremented after each call of this function. * @return * Position where key was stored, if successful. * - -EINVAL if the parameters are invalid. * - -ENOENT if end of the hash table. */ int32_t -rte_hash_iterate(const struct rte_hash *h, const void **key, void **data, = uint32_t *next); +rte_hash_iterate( + struct rte_hash_iterator_state *state, const void **key, void **data); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Initialize the iterator over entries that conflict with a given hash. + * + * @param h + * Hash table to iterate. + * @param sig + * Precomputed hash value with which the returning entries conflict. + * @param state + * Pointer to the iterator state. + * @return + * - 0 if successful. + * - -EINVAL if the parameters are invalid. + */ +int32_t __rte_experimental +rte_hash_iterator_conflict_entries_init_with_hash(const struct rte_hash *h= , + hash_sig_t sig, struct rte_hash_iterator_state *state); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice. + * + * Iterate over entries that conflict with a given hash. + * + * @param state + * Pointer to the iterator state. + * @param key + * Output containing the key at where the iterator is currently pointing= . + * @param data + * Output containing the data associated with key. + * Returns NULL if data was not stored. + * @return + * Position where key was stored, if successful. + * - -EINVAL if the parameters are invalid. + * - -ENOENT if there is no more conflicting entries. + */ +int32_t __rte_experimental +rte_hash_iterate_conflict_entries( + struct rte_hash_iterator_state *state, const void **key, void **data); + #ifdef __cplusplus } #endif diff --git a/lib/librte_hash/rte_hash_version.map b/lib/librte_hash/rte_has= h_version.map index e216ac8e2..301d4638c 100644 --- a/lib/librte_hash/rte_hash_version.map +++ b/lib/librte_hash/rte_hash_version.map @@ -24,6 +24,7 @@ DPDK_2.1 { =20 rte_hash_add_key_data; rte_hash_add_key_with_hash_data; + rte_hash_iterator_init; rte_hash_iterate; rte_hash_lookup_bulk_data; rte_hash_lookup_data; @@ -53,3 +54,10 @@ DPDK_18.08 { rte_hash_count; =20 } DPDK_16.07; + +EXPERIMENTAL { + global: + + rte_hash_iterator_conflict_entries_init_with_hash; + rte_hash_iterate_conflict_entries; +}; diff --git a/test/test/test_hash.c b/test/test/test_hash.c index b3db9fd10.= .bf57004c3 100644 --- a/test/test/test_hash.c +++ b/test/test/test_hash.c @@ -1170,8 +1170,8 @@ static int test_hash_iteration(void) void *next_data; void *data[NUM_ENTRIES]; unsigned added_keys; - uint32_t iter =3D 0; int ret =3D 0; + struct rte_hash_iterator_state state; =20 ut_params.entries =3D NUM_ENTRIES; ut_params.name =3D "test_hash_iteration"; @@ -1180,6 +1180,9 @@ static in= t test_hash_iteration(void) handle =3D rte_hash_create(&ut_params); RETURN_IF_ERROR(handle =3D=3D NULL, "hash creation failed"); =20 + RETURN_IF_ERROR(rte_hash_iterator_init(handle, &state) !=3D 0, + "initialization of the hash iterator failed"); + /* Add random entries until key cannot be added */ for (added_keys =3D 0; added_keys < NUM_ENTRIES; added_keys++) { data[added_keys] =3D (void *) ((uintptr_t) rte_rand()); @@ -1191,7 +1194= ,7 @@ static int test_hash_iteration(void) } =20 /* Iterate through the hash table */ - while (rte_hash_iterate(handle, &next_key, &next_data, &iter) >=3D 0) { + while (rte_hash_iterate(&state, &next_key, &next_data) >=3D 0) { /* Search for the key in the list of keys added */ for (i =3D 0; i < NUM_ENTRIES; i++) { if (memcmp(next_key, keys[i], ut_params.key_len) =3D=3D 0) { diff --git= a/test/test/test_hash_multiwriter.c b/test/test/test_hash_multiwriter.c index 6a3eb10bd..48db8007d 100644 --- a/test/test/test_hash_multiwriter.c +++ b/test/test/test_hash_multiwriter.c @@ -125,18 +125,22 @@ test_hash_multiwriter(void) =20 const void *next_key; void *next_data; - uint32_t iter =3D 0; =20 uint32_t duplicated_keys =3D 0; uint32_t lost_keys =3D 0; uint32_t count; =20 + struct rte_hash_iterator_state state; + snprintf(name, 32, "test%u", calledCount++); hash_params.name =3D name; =20 handle =3D rte_hash_create(&hash_params); RETURN_IF_ERROR(handle =3D=3D NULL, "hash creation failed"); =20 + RETURN_IF_ERROR(rte_hash_iterator_init(handle, &state) !=3D 0, + "initialization of the hash iterator failed"); + tbl_multiwriter_test_params.h =3D handle; tbl_multiwriter_test_params.nb_tsx_insertion =3D nb_total_tsx_insertion / rte_lcore_count(); @@ -203,7 +207,7 @@ test_has= h_multiwriter(void) goto err3; } =20 - while (rte_hash_iterate(handle, &next_key, &next_data, &iter) >=3D 0) { + while (rte_hash_iterate(&state, &next_key, &next_data) >=3D 0) { /* Search for the key in the list of keys added .*/ i =3D *(const uint32_t *)next_key; tbl_multiwriter_test_params.found[i]++; diff --git a/test/test/test_hash_readwrite.c b/test/test/test_hash_readwrit= e.c index 55ae33d80..9cdab9992 100644 --- a/test/test/test_hash_readwrite.c +++ b/test/test/test_hash_readwrite.c @@ -166,12 +166,13 @@ test_hash_readwrite_functional(int use_htm) unsigned int i; const void *next_key; void *next_data; - uint32_t iter =3D 0; =20 uint32_t duplicated_keys =3D 0; uint32_t lost_keys =3D 0; int use_jhash =3D 1; =20 + struct rte_hash_iterator_state state; + rte_atomic64_init(&gcycles); rte_atomic64_clear(&gcycles); =20 @@ -188,6 +189,8 @@ test_hash_readwrite_functional(int use_htm) tbl_rw_test_param.num_insert * rte_lcore_count(); =20 + rte_hash_iterator_init(tbl_rw_test_param.h, &state); + printf("++++++++Start function tests:+++++++++\n"); =20 /* Fire all threads. */ @@ -195,8 +198,7 @@ test_hash_readwrite_functional(int use_htm) NULL, CALL_MASTER); rte_eal_mp_wait_lcore(); =20 - while (rte_hash_iterate(tbl_rw_test_param.h, &next_key, - &next_data, &iter) >=3D 0) { + while (rte_hash_iterate(&state, &next_key, &next_data) >=3D 0) { /* Search for the key in the list of keys added .*/ i =3D *(const uint32_t *)next_key; tbl_rw_test_param.found[i]++; @@ -315,9 +317,10 @@ test_hash_readwrite_perf(struct perf *perf_results, in= t use_htm, =20 const void *next_key; void *next_data; - uint32_t iter =3D 0; int use_jhash =3D 0; =20 + struct rte_hash_iterator_state state; + uint32_t duplicated_keys =3D 0; uint32_t lost_keys =3D 0; =20 @@ -336,6 +339,8 @@ test_hash_readwrite_perf(struct perf *perf_results, int= use_htm, if (init_params(use_htm, use_jhash) !=3D 0) goto err; =20 + rte_hash_iterator_init(tbl_rw_test_param.h, &state); + /* * Do a readers finish faster or writers finish faster test. * When readers finish faster, we timing the readers, and when writers @@= -484,8 +489,7 @@ test_hash_readwrite_perf(struct perf *perf_results, int u= se_htm, =20 rte_eal_mp_wait_lcore(); =20 - while (rte_hash_iterate(tbl_rw_test_param.h, - &next_key, &next_data, &iter) >=3D 0) { + while (rte_hash_iterate(&state, &next_key, &next_data) >=3D 0) { /* Search for the key in the list of keys added .*/ i =3D *(const uint32_t *)next_key; tbl_rw_test_param.found[i]++; -- 2.17.1