<div dir="ltr">Hello, is there any other comment on this patch? Thanks </div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Apr 15, 2024 at 2:26 PM Abdullah Ömer Yamaç <<a href="mailto:aomeryamac@gmail.com">aomeryamac@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">This patch adds a new feature to the hash library to allow the user to<br>
reclaim the defer queue. This is useful when the user wants to force<br>
reclaim resources that are not being used. This API is only available<br>
if the RCU is enabled.<br>
<br>
Signed-off-by: Abdullah Ömer Yamaç <<a href="mailto:aomeryamac@gmail.com" target="_blank">aomeryamac@gmail.com</a>><br>
---<br>
 app/test/test_hash.c       | 97 ++++++++++++++++++++++++++++++++++++++<br>
 lib/hash/rte_cuckoo_hash.c | 23 +++++++++<br>
 lib/hash/rte_hash.h        | 24 ++++++++++<br>
 lib/hash/version.map       |  7 +++<br>
 4 files changed, 151 insertions(+)<br>
<br>
diff --git a/app/test/test_hash.c b/app/test/test_hash.c<br>
index d586878a22..ebeda8c322 100644<br>
--- a/app/test/test_hash.c<br>
+++ b/app/test/test_hash.c<br>
@@ -2183,6 +2183,100 @@ test_hash_rcu_qsbr_sync_mode(uint8_t ext_bkt)<br>
<br>
 }<br>
<br>
+/*<br>
+ * rte_hash_rcu_qsbr_dq_reclaim unit test.<br>
+ */<br>
+static int<br>
+test_hash_rcu_qsbr_dq_reclaim(void)<br>
+{<br>
+       size_t sz;<br>
+       int32_t status;<br>
+       unsigned int total_entries = 8;<br>
+       unsigned int freed, pending, available;<br>
+       uint32_t reclaim_keys[8] = {10, 11, 12, 13, 14, 15, 16, 17};<br>
+       struct rte_hash_rcu_config rcu_cfg = {0};<br>
+       struct rte_hash_parameters hash_params = {<br>
+               .name = "test_hash_rcu_qsbr_dq_reclaim",<br>
+               .entries = total_entries,<br>
+               .key_len = sizeof(uint32_t),<br>
+               .hash_func = NULL,<br>
+               .hash_func_init_val = 0,<br>
+               .socket_id = 0,<br>
+       };<br>
+<br>
+       hash_params.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF;<br>
+<br>
+       g_qsv = NULL;<br>
+       g_handle = NULL;<br>
+<br>
+       printf("\n# Running RCU QSBR DQ mode, reclaim defer queue functional test\n");<br>
+<br>
+       g_handle = rte_hash_create(&hash_params);<br>
+       RETURN_IF_ERROR_RCU_QSBR(g_handle == NULL, "Hash creation failed");<br>
+<br>
+       /* Create RCU QSBR variable */<br>
+       sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);<br>
+       g_qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,<br>
+                                       RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);<br>
+       RETURN_IF_ERROR_RCU_QSBR(g_qsv == NULL,<br>
+                                                        "RCU QSBR variable creation failed");<br>
+<br>
+       status = rte_rcu_qsbr_init(g_qsv, RTE_MAX_LCORE);<br>
+       RETURN_IF_ERROR_RCU_QSBR(status != 0,<br>
+                                                        "RCU QSBR variable initialization failed");<br>
+<br>
+       rcu_cfg.v = g_qsv;<br>
+       rcu_cfg.dq_size = total_entries;<br>
+       rcu_cfg.mode = RTE_HASH_QSBR_MODE_DQ;<br>
+<br>
+       /* Attach RCU QSBR to hash table */<br>
+       status = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg);<br>
+       RETURN_IF_ERROR_RCU_QSBR(status != 0,<br>
+                                                        "Attach RCU QSBR to hash table failed");<br>
+<br>
+       /* Register pseudo reader */<br>
+       status = rte_rcu_qsbr_thread_register(g_qsv, 0);<br>
+       RETURN_IF_ERROR_RCU_QSBR(status != 0,<br>
+                                                        "RCU QSBR thread registration failed");<br>
+       rte_rcu_qsbr_thread_online(g_qsv, 0);<br>
+<br>
+       /* Fill half of the hash table */<br>
+       for (size_t i = 0; i < total_entries / 2; i++)<br>
+               status = rte_hash_add_key(g_handle, &reclaim_keys[i]);<br>
+<br>
+       /* Lookup inserted elements*/<br>
+       for (size_t i = 0; i < total_entries / 2; i++)<br>
+               rte_hash_lookup(g_handle, &reclaim_keys[i]);<br>
+<br>
+       /* Try to put these elements into the defer queue*/<br>
+       for (size_t i = 0; i < total_entries / 2; i++)<br>
+               rte_hash_del_key(g_handle, &reclaim_keys[i]);<br>
+<br>
+       /* Reader quiescent */<br>
+       rte_rcu_qsbr_quiescent(g_qsv, 0);<br>
+<br>
+       status = rte_hash_add_key(g_handle, &reclaim_keys[0]);<br>
+       RETURN_IF_ERROR_RCU_QSBR(status < 0,<br>
+                                                        "failed to add key (pos[%u]=%d)", 0,<br>
+                                                        status);<br>
+<br>
+       /* This should be (total_entries / 2) + 1 (last add) */<br>
+       unsigned int hash_size = rte_hash_count(g_handle);<br>
+<br>
+       /* Freed size should be (total_entries / 2) */<br>
+       rte_hash_rcu_qsbr_dq_reclaim(g_handle, &freed, &pending, &available);<br>
+<br>
+       rte_hash_free(g_handle);<br>
+       rte_free(g_qsv);<br>
+<br>
+       if (hash_size != (total_entries / 2 + 1) || freed != (total_entries / 2)) {<br>
+               printf("Failed to reclaim defer queue\n");<br>
+               return -1;<br>
+       }<br>
+<br>
+       return 0;<br>
+}<br>
+<br>
 /*<br>
  * Do all unit and performance tests.<br>
  */<br>
@@ -2261,6 +2355,9 @@ test_hash(void)<br>
        if (test_hash_rcu_qsbr_sync_mode(1) < 0)<br>
                return -1;<br>
<br>
+       if (test_hash_rcu_qsbr_dq_reclaim() < 0)<br>
+               return -1;<br>
+<br>
        return 0;<br>
 }<br>
<br>
diff --git a/lib/hash/rte_cuckoo_hash.c b/lib/hash/rte_cuckoo_hash.c<br>
index 9cf94645f6..4a44aadd9a 100644<br>
--- a/lib/hash/rte_cuckoo_hash.c<br>
+++ b/lib/hash/rte_cuckoo_hash.c<br>
@@ -1588,6 +1588,29 @@ rte_hash_rcu_qsbr_add(struct rte_hash *h, struct rte_hash_rcu_config *cfg)<br>
        return 0;<br>
 }<br>
<br>
+int<br>
+rte_hash_rcu_qsbr_dq_reclaim(struct rte_hash *h, unsigned int *freed,<br>
+                                       unsigned int *pending, unsigned int *available)<br>
+{<br>
+       int ret;<br>
+<br>
+       if (h == NULL || h->hash_rcu_cfg == NULL) {<br>
+               rte_errno = EINVAL;<br>
+               return 1;<br>
+       }<br>
+<br>
+       ret = rte_rcu_qsbr_dq_reclaim(h->dq, h->hash_rcu_cfg->max_reclaim_size,<br>
+                                                                 freed, pending, available);<br>
+       if (ret != 0) {<br>
+               HASH_LOG(ERR,<br>
+                                "%s: could not reclaim the defer queue in hash table",<br>
+                                __func__);<br>
+               return 1;<br>
+       }<br>
+<br>
+       return 0;<br>
+}<br>
+<br>
 static inline void<br>
 remove_entry(const struct rte_hash *h, struct rte_hash_bucket *bkt,<br>
                unsigned int i)<br>
diff --git a/lib/hash/rte_hash.h b/lib/hash/rte_hash.h<br>
index 7ecc021111..edfa262aca 100644<br>
--- a/lib/hash/rte_hash.h<br>
+++ b/lib/hash/rte_hash.h<br>
@@ -674,6 +674,30 @@ rte_hash_iterate(const struct rte_hash *h, const void **key, void **data, uint32<br>
  */<br>
 int rte_hash_rcu_qsbr_add(struct rte_hash *h, struct rte_hash_rcu_config *cfg);<br>
<br>
+/**<br>
+ * Reclaim resources from the defer queue.<br>
+ * This API reclaim the resources from the defer queue if rcu is enabled.<br>
+ *<br>
+ * @param h<br>
+ *   The hash object to reclaim resources.<br>
+ * @param freed<br>
+ *   Number of resources that were freed.<br>
+ * @param pending<br>
+ *   Number of resources pending on the defer queue.<br>
+ *   This number might not be accurate if multi-thread safety is configured.<br>
+ * @param available<br>
+ *   Number of resources that can be added to the defer queue.<br>
+ *   This number might not be accurate if multi-thread safety is configured.<br>
+ * @return<br>
+ *   On success - 0<br>
+ *   On error - 1 with error code set in rte_errno.<br>
+ *   Possible rte_errno codes are:<br>
+ *   - EINVAL - invalid pointer<br>
+ */<br>
+__rte_experimental<br>
+int rte_hash_rcu_qsbr_dq_reclaim(struct rte_hash *h, unsigned int *freed,<br>
+               unsigned int *pending, unsigned int *available);<br>
+<br>
 #ifdef __cplusplus<br>
 }<br>
 #endif<br>
diff --git a/lib/hash/version.map b/lib/hash/version.map<br>
index 6f4bcdb71b..d348dd9196 100644<br>
--- a/lib/hash/version.map<br>
+++ b/lib/hash/version.map<br>
@@ -53,3 +53,10 @@ INTERNAL {<br>
        rte_thash_gfni_stub;<br>
        rte_thash_gfni_bulk_stub;<br>
 };<br>
+<br>
+EXPERIMENTAL {<br>
+       global:<br>
+<br>
+       # added in 24.07<br>
+       rte_hash_rcu_qsbr_dq_reclaim;<br>
+};<br>
-- <br>
2.34.1<br>
<br>
</blockquote></div>