From mboxrd@z Thu Jan 1 00:00:00 1970 From: Huawei Xie Subject: [PATCH v7] mbuf: provide rte_pktmbuf_alloc_bulk API Date: Sun, 28 Feb 2016 20:44:56 +0800 Message-ID: <1456663496-32704-1-git-send-email-huawei.xie@intel.com> References: <1450049754-33635-1-git-send-email-huawei.xie@intel.com> Cc: dprovan@bivio.net To: dev@dpdk.org Return-path: Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by dpdk.org (Postfix) with ESMTP id 57AC86948 for ; Mon, 29 Feb 2016 05:38:44 +0100 (CET) In-Reply-To: <1450049754-33635-1-git-send-email-huawei.xie@intel.com> List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" v7 changes: rte_pktmbuf_alloc_bulk isn't exported as API, so shouldn't be listed in version map v6 changes: reflect the changes in release notes and library version map file revise our duff's code style a bit to make it more readable v5 changes: add comment about duff's device and our variant implementation v3 changes: move while after case 0 add context about duff's device and why we use while loop in the commit message v2 changes: unroll the loop a bit to help the performance rte_pktmbuf_alloc_bulk allocates a bulk of packet mbufs. There is related thread about this bulk API. http://dpdk.org/dev/patchwork/patch/4718/ Thanks to Konstantin's loop unrolling. Attached the wiki page about duff's device. It explains the performance optimization through loop unwinding, and also the most dramatic use of case label fall-through. https://en.wikipedia.org/wiki/Duff%27s_device In this implementation, while() loop is used because we could not assume count is strictly positive. Using while() loop saves one line of check. Signed-off-by: Gerald Rogers Signed-off-by: Huawei Xie Acked-by: Konstantin Ananyev Acked-by: Olivier Matz --- doc/guides/rel_notes/release_16_04.rst | 3 ++ lib/librte_mbuf/rte_mbuf.h | 55 ++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/doc/guides/rel_notes/release_16_04.rst b/doc/guides/rel_notes/release_16_04.rst index e2219d0..b10a11b 100644 --- a/doc/guides/rel_notes/release_16_04.rst +++ b/doc/guides/rel_notes/release_16_04.rst @@ -46,6 +46,9 @@ This section should contain new features added in this release. Sample format: * **Added vhost-user live migration support.** +* **Enable bulk allocation of mbufs.** + A new function ``rte_pktmbuf_alloc_bulk()`` has been added to allow the user + to allocate a bulk of mbufs. Resolved Issues --------------- diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h index c973e9b..c1f6bc4 100644 --- a/lib/librte_mbuf/rte_mbuf.h +++ b/lib/librte_mbuf/rte_mbuf.h @@ -1336,6 +1336,61 @@ static inline struct rte_mbuf *rte_pktmbuf_alloc(struct rte_mempool *mp) } /** + * Allocate a bulk of mbufs, initialize refcnt and reset the fields to default + * values. + * + * @param pool + * The mempool from which mbufs are allocated. + * @param mbufs + * Array of pointers to mbufs + * @param count + * Array size + * @return + * - 0: Success + */ +static inline int rte_pktmbuf_alloc_bulk(struct rte_mempool *pool, + struct rte_mbuf **mbufs, unsigned count) +{ + unsigned idx = 0; + int rc; + + rc = rte_mempool_get_bulk(pool, (void **)mbufs, count); + if (unlikely(rc)) + return rc; + + /* To understand duff's device on loop unwinding optimization, see + * https://en.wikipedia.org/wiki/Duff's_device. + * Here while() loop is used rather than do() while{} to avoid extra + * check if count is zero. + */ + switch (count % 4) { + case 0: + while (idx != count) { + RTE_MBUF_ASSERT(rte_mbuf_refcnt_read(mbufs[idx]) == 0); + rte_mbuf_refcnt_set(mbufs[idx], 1); + rte_pktmbuf_reset(mbufs[idx]); + idx++; + case 3: + RTE_MBUF_ASSERT(rte_mbuf_refcnt_read(mbufs[idx]) == 0); + rte_mbuf_refcnt_set(mbufs[idx], 1); + rte_pktmbuf_reset(mbufs[idx]); + idx++; + case 2: + RTE_MBUF_ASSERT(rte_mbuf_refcnt_read(mbufs[idx]) == 0); + rte_mbuf_refcnt_set(mbufs[idx], 1); + rte_pktmbuf_reset(mbufs[idx]); + idx++; + case 1: + RTE_MBUF_ASSERT(rte_mbuf_refcnt_read(mbufs[idx]) == 0); + rte_mbuf_refcnt_set(mbufs[idx], 1); + rte_pktmbuf_reset(mbufs[idx]); + idx++; + } + } + return 0; +} + +/** * Attach packet mbuf to another packet mbuf. * * After attachment we refer the mbuf we attached as 'indirect', -- 1.8.1.4