From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <arybchenko@solarflare.com>
Received: from dispatch1-us1.ppe-hosted.com (dispatch1-us1.ppe-hosted.com
 [148.163.129.52]) by dpdk.org (Postfix) with ESMTP id B71D5F04
 for <dev@dpdk.org>; Fri, 24 Nov 2017 17:07:06 +0100 (CET)
Received: from pure.maildistiller.com (dispatch1.mdlocal [10.7.20.164])
 by dispatch1-us1.ppe-hosted.com (Proofpoint Essentials ESMTP Server) with
 ESMTP id CD83760F3E; Fri, 24 Nov 2017 16:07:05 +0000 (UTC)
X-Virus-Scanned: Proofpoint Essentials engine
Received: from mx1-us3.ppe-hosted.com (us4-filterqueue.mdlocal [10.7.20.246])
 by pure.maildistiller.com (Proofpoint Essentials ESMTP Server) with
 ESMTPS id 4CD3580052; Fri, 24 Nov 2017 16:07:05 +0000 (UTC)
Received: from webmail.solarflare.com (webmail.solarflare.com [12.187.104.26])
 (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits))
 (No client certificate requested)
 by mx1-us3.ppe-hosted.com (Proofpoint Essentials ESMTP Server) with ESMTPS id
 3EF3EB4006E; Fri, 24 Nov 2017 16:07:05 +0000 (UTC)
Received: from ocex03.SolarFlarecom.com (10.20.40.36) by
 ocex03.SolarFlarecom.com (10.20.40.36) with Microsoft SMTP Server (TLS) id
 15.0.1044.25; Fri, 24 Nov 2017 08:07:02 -0800
Received: from opal.uk.solarflarecom.com (10.17.10.1) by
 ocex03.SolarFlarecom.com (10.20.40.36) with Microsoft SMTP Server (TLS) id
 15.0.1044.25 via Frontend Transport; Fri, 24 Nov 2017 08:07:02 -0800
Received: from uklogin.uk.solarflarecom.com (uklogin.uk.solarflarecom.com
 [10.17.10.10])
 by opal.uk.solarflarecom.com (8.13.8/8.13.8) with ESMTP id vAOG703N019682;
 Fri, 24 Nov 2017 16:07:00 GMT
Received: from uklogin.uk.solarflarecom.com (localhost.localdomain [127.0.0.1])
 by uklogin.uk.solarflarecom.com (8.13.8/8.13.8) with ESMTP id vAOG70SC021131; 
 Fri, 24 Nov 2017 16:07:00 GMT
From: Andrew Rybchenko <arybchenko@solarflare.com>
To: <dev@dpdk.org>
CC: Olivier Matz <olivier.matz@6wind.com>, "Artem V. Andreev"
 <Artem.Andreev@oktetlabs.ru>
Date: Fri, 24 Nov 2017 16:06:30 +0000
Message-ID: <1511539591-20966-6-git-send-email-arybchenko@solarflare.com>
X-Mailer: git-send-email 1.8.2.3
In-Reply-To: <1511539591-20966-1-git-send-email-arybchenko@solarflare.com>
References: <1511539591-20966-1-git-send-email-arybchenko@solarflare.com>
MIME-Version: 1.0
Content-Type: text/plain
X-MDID: 1511539625-lSSzNvzVIdBm
Subject: [dpdk-dev] [RFC PATCH 5/6] mempool: support block dequeue operation
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <http://dpdk.org/ml/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://dpdk.org/ml/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <http://dpdk.org/ml/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
X-List-Received-Date: Fri, 24 Nov 2017 16:07:07 -0000

From: "Artem V. Andreev" <Artem.Andreev@oktetlabs.ru>

If mempool manager supports object blocks (physically and virtual
contiguous set of objects), it is sufficient to get the first
object only and the function allows to avoid filling in of
information about each block member.

Signed-off-by: Artem V. Andreev <Artem.Andreev@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 lib/librte_mempool/rte_mempool.c     |   4 +-
 lib/librte_mempool/rte_mempool.h     | 111 +++++++++++++++++++++++++++++++++++
 lib/librte_mempool/rte_mempool_ops.c |   1 +
 3 files changed, 115 insertions(+), 1 deletion(-)

diff --git a/lib/librte_mempool/rte_mempool.c b/lib/librte_mempool/rte_mempool.c
index 43455a3..6850d6e 100644
--- a/lib/librte_mempool/rte_mempool.c
+++ b/lib/librte_mempool/rte_mempool.c
@@ -603,8 +603,10 @@ rte_mempool_populate_default(struct rte_mempool *mp)
 	ret = rte_mempool_ops_get_info(mp, &mp->info);
 	if ((ret < 0) && (ret != -ENOTSUP))
 		return ret;
-	if (ret == -ENOTSUP)
+	if (ret == -ENOTSUP) {
 		mp->info.cluster_size = 0;
+		mp->info.contig_block_size = 0;
+	}
 
 	if ((mp->info.cluster_size == 0) &&
 	    (mp_flags & MEMPOOL_F_CAPA_ALLOCATE_IN_CLUSTERS))
diff --git a/lib/librte_mempool/rte_mempool.h b/lib/librte_mempool/rte_mempool.h
index 3a52b93..4575eb2 100644
--- a/lib/librte_mempool/rte_mempool.h
+++ b/lib/librte_mempool/rte_mempool.h
@@ -223,6 +223,8 @@ struct rte_mempool_memhdr {
 struct rte_mempool_info {
 	/** Number of objects in a cluster */
 	unsigned int cluster_size;
+	/** Number of objects in the contiguous block */
+	unsigned int contig_block_size;
 };
 
 /**
@@ -431,6 +433,12 @@ typedef int (*rte_mempool_dequeue_t)(struct rte_mempool *mp,
 		void **obj_table, unsigned int n);
 
 /**
+ * Dequeue a number of contiquous object blocks from the external pool.
+ */
+typedef int (*rte_mempool_dequeue_contig_blocks_t)(struct rte_mempool *mp,
+		 void **first_obj_table, unsigned int n);
+
+/**
  * Return the number of available objects in the external pool.
  */
 typedef unsigned (*rte_mempool_get_count)(const struct rte_mempool *mp);
@@ -473,6 +481,10 @@ struct rte_mempool_ops {
 	 * Get mempool info
 	 */
 	rte_mempool_get_info_t get_info;
+	/**
+	 * Dequeue a number of contiguous object blocks.
+	 */
+	rte_mempool_dequeue_contig_blocks_t dequeue_contig_blocks;
 } __rte_cache_aligned;
 
 #define RTE_MEMPOOL_MAX_OPS_IDX 16  /**< Max registered ops structs */
@@ -551,6 +563,30 @@ rte_mempool_ops_dequeue_bulk(struct rte_mempool *mp,
 }
 
 /**
+ * @internal Wrapper for mempool_ops dequeue_contig_blocks callback.
+ *
+ * @param mp
+ *   Pointer to the memory pool.
+ * @param first_obj_table
+ *   Pointer to a table of void * pointers (first objects).
+ * @param n
+ *   Number of blocks to get.
+ * @return
+ *   - 0: Success; got n objects.
+ *   - <0: Error; code of dequeue function.
+ */
+static inline int
+rte_mempool_ops_dequeue_contig_blocks(struct rte_mempool *mp,
+		void **first_obj_table, unsigned int n)
+{
+	struct rte_mempool_ops *ops;
+
+	ops = rte_mempool_get_ops(mp->ops_index);
+	RTE_ASSERT(ops->dequeue_contig_blocks != NULL);
+	return ops->dequeue_contig_blocks(mp, first_obj_table, n);
+}
+
+/**
  * @internal wrapper for mempool_ops enqueue callback.
  *
  * @param mp
@@ -1456,6 +1492,81 @@ rte_mempool_get(struct rte_mempool *mp, void **obj_p)
 }
 
 /**
+ * @internal Get contiguous blocks of objects from the pool. Used internally.
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param first_obj_table
+ *   A pointer to a pointer to the first object in each block.
+ * @param n
+ *   A number of blocks to get.
+ * @return
+ *   - >0: Success
+ *   - <0: Error
+ */
+static __rte_always_inline int
+__mempool_generic_get_contig_blocks(struct rte_mempool *mp,
+				    void **first_obj_table, unsigned int n)
+{
+	int ret;
+
+	ret = rte_mempool_ops_dequeue_contig_blocks(mp, first_obj_table, n);
+	if (ret < 0)
+		__MEMPOOL_STAT_ADD(mp, get_fail,
+				   n * mp->info.contig_block_size);
+	else
+		__MEMPOOL_STAT_ADD(mp, get_success,
+				   n * mp->info.contig_block_size);
+
+	return ret;
+}
+
+/**
+ * Get a contiguous blocks of objects from the mempool.
+ *
+ * If cache is enabled, consider to flush it first, to reuse objects
+ * as soon as possible.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param first_obj_table
+ *   A pointer to a pointer to the first object in each block.
+ * @param n
+ *   The number of blocks to get from mempool.
+ * @return
+ *   - >0: the size of the block
+ *   - -ENOBUFS: Not enough entries in the mempool; no object is retrieved.
+ *   - -EOPNOTSUPP: The mempool driver does not support block dequeue
+ */
+static __rte_always_inline int
+rte_mempool_get_contig_blocks(struct rte_mempool *mp,
+			      void **first_obj_table, unsigned int n)
+{
+	int ret;
+
+	ret = __mempool_generic_get_contig_blocks(mp, first_obj_table, n);
+#ifdef RTE_LIBRTE_MEMPOOL_DEBUG
+	if (ret == 0) {
+		const size_t total_elt_sz =
+			mp->header_size + mp->elt_size + mp->trailer_size;
+		unsigned int i, j;
+
+		for (i = 0; i < n; ++i) {
+			void *first_obj = first_obj_table[i];
+
+			for (j = 0; j < mp->info.contig_block_size; ++j) {
+				void *obj;
+
+				obj = (void *)((uintptr_t)first_obj +
+					       j * total_elt_sz);
+				rte_mempool_check_cookies(mp, &obj, 1, 1);
+			}
+		}
+	}
+#endif
+	return ret;
+}
+
+/**
  * Return the number of entries in the mempool.
  *
  * When cache is enabled, this function has to browse the length of
diff --git a/lib/librte_mempool/rte_mempool_ops.c b/lib/librte_mempool/rte_mempool_ops.c
index 23de4db..cc38761 100644
--- a/lib/librte_mempool/rte_mempool_ops.c
+++ b/lib/librte_mempool/rte_mempool_ops.c
@@ -89,6 +89,7 @@ rte_mempool_register_ops(const struct rte_mempool_ops *h)
 	ops->get_capabilities = h->get_capabilities;
 	ops->register_memory_area = h->register_memory_area;
 	ops->get_info = h->get_info;
+	ops->dequeue_contig_blocks = h->dequeue_contig_blocks;
 
 	rte_spinlock_unlock(&rte_mempool_ops_table.sl);
 
-- 
2.7.4