From patchwork Wed Feb 17 10:16:51 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxim Uvarov X-Patchwork-Id: 62096 Delivered-To: patch@linaro.org Received: by 10.112.43.199 with SMTP id y7csp2191681lbl; Wed, 17 Feb 2016 02:17:39 -0800 (PST) X-Received: by 10.55.31.20 with SMTP id f20mr784895qkf.42.1455704259176; Wed, 17 Feb 2016 02:17:39 -0800 (PST) Return-Path: Received: from lists.linaro.org (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTP id p29si554833qki.116.2016.02.17.02.17.38; Wed, 17 Feb 2016 02:17:39 -0800 (PST) Received-SPF: pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Authentication-Results: mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dkim=neutral (body hash did not verify) header.i=@linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 83F1161722; Wed, 17 Feb 2016 10:17:38 +0000 (UTC) Authentication-Results: lists.linaro.org; dkim=fail reason="verification failed; unprotected key" header.d=linaro.org header.i=@linaro.org header.b=fGJua9JG; dkim-adsp=none (unprotected policy); dkim-atps=neutral X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on ip-10-142-244-252 X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID, URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from [127.0.0.1] (localhost [127.0.0.1]) by lists.linaro.org (Postfix) with ESMTP id 6F36061796; Wed, 17 Feb 2016 10:17:09 +0000 (UTC) X-Original-To: lng-odp@lists.linaro.org Delivered-To: lng-odp@lists.linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id EA2BB617B0; Wed, 17 Feb 2016 10:17:04 +0000 (UTC) Received: from mail-lf0-f47.google.com (mail-lf0-f47.google.com [209.85.215.47]) by lists.linaro.org (Postfix) with ESMTPS id 4409461786 for ; Wed, 17 Feb 2016 10:17:00 +0000 (UTC) Received: by mail-lf0-f47.google.com with SMTP id l143so7517530lfe.2 for ; Wed, 17 Feb 2016 02:17:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=mMBGp68YnnTEZE2lMJTuykNGmzsu//AYDx44fhrNjC0=; b=fGJua9JGKqx192+4uoH3PR95oVMTtEywai9ALF4UEWdGBjp+gp36OYkhP7BbXptGFe mfbzVTerhpwtSWjx950tXovEq2fr/DqmcGmV2/JaIvavIUqpw/XBPkt/zdSrZb0Vh59T 71DM7aOsxstVwICBp0lETtfyHP92pe+OazkQU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=mMBGp68YnnTEZE2lMJTuykNGmzsu//AYDx44fhrNjC0=; b=V15Cs2mAzgUbtp7RTcalTLfImZxJSUs7wI7PvjDUtqwL3LomBKUOQBwPje53ZrrB+v T6vqKlEUB7Ar2ovVJHKv3bCbRLZ5+zOKeWZfCYb2kDEpMfkPZyDN3BiStBK6NMCgapKL DaUC9t8BeaCe2cklAALkHNZUa5/07GYsPzpYAHpSzZS3CyJ6b0zOU1a3wraJ3zJwOCPz qqL1fSuujGUyCOyO77fqpNVuel7dyDHkxMMAxSD5w9Xk7mfHzet8rCGriOG0adqXoZlX REodN1XwPl3f28zjmfxdfIA/YdztlVoTuUi0lZOnPn5x37B56AwN5C/mYEC3p4hDXv4z GmEg== X-Gm-Message-State: AG10YOR2zGxC7kHK0iA4/z5bKgxno2y4hXz4AdNlhCLopMoX5wyf8SABo+ZhqGzVLNM92usCZ4U= X-Received: by 10.25.27.21 with SMTP id b21mr281427lfb.99.1455704218977; Wed, 17 Feb 2016 02:16:58 -0800 (PST) Received: from localhost.localdomain (ppp91-76-173-134.pppoe.mtu-net.ru. [91.76.173.134]) by smtp.gmail.com with ESMTPSA id a124sm97980lfa.40.2016.02.17.02.16.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 17 Feb 2016 02:16:58 -0800 (PST) From: Maxim Uvarov To: lng-odp@lists.linaro.org Date: Wed, 17 Feb 2016 13:16:51 +0300 Message-Id: <1455704211-12666-1-git-send-email-maxim.uvarov@linaro.org> X-Mailer: git-send-email 2.7.1.250.gff4ea60 X-Topics: patch Subject: [lng-odp] [PATCH] helper: remove ring code X-BeenThere: lng-odp@lists.linaro.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "The OpenDataPlane \(ODP\) List" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: lng-odp-bounces@lists.linaro.org Sender: "lng-odp" Remove ring and dead api-next code. In api-next pktio ipc patches moved ring code to linux-generic and updated that test case to the latest odp api. If we ipc pktio will be accepted to master than current api-next ring test will be used. Signed-off-by: Maxim Uvarov --- configure.ac | 1 - helper/Makefile.am | 2 - helper/include/odp/helper/ring.h | 577 ----------------------------------- helper/ring.c | 634 --------------------------------------- test/Makefile.am | 2 +- test/api_test/.gitignore | 2 - test/api_test/Makefile.am | 16 - test/api_test/odp_common.c | 91 ------ test/api_test/odp_common.h | 42 --- test/api_test/odp_ring_test.c | 470 ----------------------------- 10 files changed, 1 insertion(+), 1836 deletions(-) delete mode 100644 helper/include/odp/helper/ring.h delete mode 100644 helper/ring.c delete mode 100644 test/api_test/.gitignore delete mode 100644 test/api_test/Makefile.am delete mode 100644 test/api_test/odp_common.c delete mode 100644 test/api_test/odp_common.h delete mode 100644 test/api_test/odp_ring_test.c diff --git a/configure.ac b/configure.ac index 8108ff2..a7cb035 100644 --- a/configure.ac +++ b/configure.ac @@ -336,7 +336,6 @@ AC_CONFIG_FILES([Makefile pkgconfig/libodphelper.pc scripts/Makefile test/Makefile - test/api_test/Makefile test/performance/Makefile test/validation/Makefile test/validation/atomic/Makefile diff --git a/helper/Makefile.am b/helper/Makefile.am index a8665b2..6557793 100644 --- a/helper/Makefile.am +++ b/helper/Makefile.am @@ -10,7 +10,6 @@ AM_CFLAGS += -I$(top_srcdir)/include helperincludedir = $(includedir)/odp/helper/ helperinclude_HEADERS = \ - $(srcdir)/include/odp/helper/ring.h \ $(srcdir)/include/odp/helper/linux.h \ $(srcdir)/include/odp/helper/chksum.h\ $(srcdir)/include/odp/helper/eth.h\ @@ -30,7 +29,6 @@ noinst_HEADERS = \ __LIB__libodphelper_la_SOURCES = \ linux.c \ - ring.c \ hashtable.c \ lineartable.c diff --git a/helper/include/odp/helper/ring.h b/helper/include/odp/helper/ring.h deleted file mode 100644 index 65c32ad..0000000 --- a/helper/include/odp/helper/ring.h +++ /dev/null @@ -1,577 +0,0 @@ -/* Copyright (c) 2014, Linaro Limited - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Derived from FreeBSD's bufring.c - * - ************************************************************************** - * - * Copyright (c) 2007,2008 Kip Macy kmacy@freebsd.org - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. The name of Kip Macy nor the names of other - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ***************************************************************************/ - -/** - * ODP Ring - * - * The Ring Manager is a fixed-size queue, implemented as a table of - * pointers. Head and tail pointers are modified atomically, allowing - * concurrent access to it. It has the following features: - * - * - FIFO (First In First Out) - * - Maximum size is fixed; the pointers are stored in a table. - * - Lockless implementation. - * - Multi- or single-consumer dequeue. - * - Multi- or single-producer enqueue. - * - Bulk dequeue. - * - Bulk enqueue. - * - * Note: the ring implementation is not preemptable. A lcore must not - * be interrupted by another task that uses the same ring. - * - */ - -#ifndef ODPH_RING_H_ -#define ODPH_RING_H_ - -#ifdef __cplusplus -extern "C" { -#endif - - -#include -#include -#include -#include -#include - -enum odph_ring_queue_behavior { - ODPH_RING_QUEUE_FIXED = 0, /**< Enq/Deq a fixed number - of items from a ring */ - ODPH_RING_QUEUE_VARIABLE /**< Enq/Deq as many items - a possible from ring */ -}; - - -#define ODPH_RING_NAMESIZE 32 /**< The maximum length of a ring name. */ - -/** - * An ODP ring structure. - * - * The producer and the consumer have a head and a tail index. The particularity - * of these index is that they are not between 0 and size(ring). These indexes - * are between 0 and 2^32, and we mask their value when we access the ring[] - * field. Thanks to this assumption, we can do subtractions between 2 index - * values in a modulo-32bit base: that's why the overflow of the indexes is not - * a problem. - */ -typedef struct odph_ring { - /** @private Next in list. */ - TAILQ_ENTRY(odph_ring) next; - - /** @private Name of the ring. */ - char name[ODPH_RING_NAMESIZE]; - /** @private Flags supplied at creation. */ - int flags; - - /** @private Producer */ - struct prod { - uint32_t watermark; /* Maximum items */ - uint32_t sp_enqueue; /* True, if single producer. */ - uint32_t size; /* Size of ring. */ - uint32_t mask; /* Mask (size-1) of ring. */ - uint32_t head; /* Producer head. */ - uint32_t tail; /* Producer tail. */ - } prod ODP_ALIGNED_CACHE; - - /** @private Consumer */ - struct cons { - uint32_t sc_dequeue; /* True, if single consumer. */ - uint32_t size; /* Size of the ring. */ - uint32_t mask; /* Mask (size-1) of ring. */ - uint32_t head; /* Consumer head. */ - uint32_t tail; /* Consumer tail. */ - } cons ODP_ALIGNED_CACHE; - - /** @private Memory space of ring starts here. */ - void *ring[0] ODP_ALIGNED_CACHE; -} odph_ring_t; - - -#define ODPH_RING_F_SP_ENQ 0x0001 /* The default enqueue is "single-producer".*/ -#define ODPH_RING_F_SC_DEQ 0x0002 /* The default dequeue is "single-consumer".*/ -#define ODPH_RING_QUOT_EXCEED (1 << 31) /* Quota exceed for burst ops */ -#define ODPH_RING_SZ_MASK (unsigned)(0x0fffffff) /* Ring size mask */ - - -/** - * Create a new ring named *name* in memory. - * - * This function uses odp_shm_reserve() to allocate memory. Its size is - * set to *count*, which must be a power of two. Water marking is - * disabled by default. Note that the real usable ring size is count-1 - * instead of count. - * - * @param name - * The name of the ring. - * @param count - * The size of the ring (must be a power of 2). - * @param socket_id (dummy, not included : todo) - * @param flags - * An OR of the following: - * - RING_F_SP_ENQ: If this flag is set, the default behavior when - * using ``odp_ring_enqueue()`` or ``odp_ring_enqueue_bulk()`` - * is "single-producer". Otherwise, it is "multi-producers". - * - RING_F_SC_DEQ: If this flag is set, the default behavior when - * using ``odp_ring_dequeue()`` or ``odp_ring_dequeue_bulk()`` - * is "single-consumer". Otherwise, it is "multi-consumers". - * @return - * On success, the pointer to the new allocated ring. NULL on error with - * odp_errno set appropriately. Possible errno values include: - * - EINVAL - count provided is not a power of 2 - * - ENOSPC - the maximum number of memzones has already been allocated - * - EEXIST - a memzone with the same name already exists - * - ENOMEM - no appropriate memory area found in which to create memzone - */ -odph_ring_t *odph_ring_create(const char *name, unsigned count, - unsigned flags); - - -/** - * Change the high water mark. - * - * If *count* is 0, water marking is disabled. Otherwise, it is set to the - * *count* value. The *count* value must be greater than 0 and less - * than the ring size. - * - * This function can be called at any time (not necessarily at - * initialization). - * - * @param r Pointer to the ring structure. - * @param count New water mark value. - * @return 0: Success; water mark changed. - * -EINVAL: Invalid water mark value. - */ -int odph_ring_set_water_mark(odph_ring_t *r, unsigned count); - -/** - * Dump the status of the ring to the console. - * - * @param r A pointer to the ring structure. - */ -void odph_ring_dump(const odph_ring_t *r); - -/** - * Enqueue several objects on the ring (multi-producers safe). - * - * This function uses a "compare and set" instruction to move the - * producer index atomically. - * - * @param r - * A pointer to the ring structure. - * @param obj_table - * A pointer to a table of void * pointers (objects). - * @param n - * The number of objects to add in the ring from the obj_table. - * @param behavior - * ODP_RING_QUEUE_FIXED: Enqueue a fixed number of items from a ring - * ODP_RING_QUEUE_VARIABLE: Enqueue as many items a possible from ring - * @return - * Depend on the behavior value - * if behavior = ODP_RING_QUEUE_FIXED - * - 0: Success; objects enqueue. - * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the - * high water mark is exceeded. - * - -ENOBUFS: Not enough room in the ring to enqueue, no object is enqueued. - * if behavior = ODP_RING_QUEUE_VARIABLE - * - n: Actual number of objects enqueued. - */ -int __odph_ring_mp_do_enqueue(odph_ring_t *r, void * const *obj_table, - unsigned n, - enum odph_ring_queue_behavior behavior); - -/** - * Enqueue several objects on a ring (NOT multi-producers safe). - * - * @param r - * A pointer to the ring structure. - * @param obj_table - * A pointer to a table of void * pointers (objects). - * @param n - * The number of objects to add in the ring from the obj_table. - * @param behavior - * ODP_RING_QUEUE_FIXED: Enqueue a fixed number of items from a ring - * ODP_RING_QUEUE_VARIABLE: Enqueue as many items a possible from ring - * @return - * Depend on the behavior value - * if behavior = ODP_RING_QUEUE_FIXED - * - 0: Success; objects enqueue. - * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the - * high water mark is exceeded. - * - -ENOBUFS: Not enough room in the ring to enqueue, no object is enqueued. - * if behavior = ODP_RING_QUEUE_VARIABLE - * - n: Actual number of objects enqueued. - */ -int __odph_ring_sp_do_enqueue(odph_ring_t *r, void * const *obj_table, - unsigned n, - enum odph_ring_queue_behavior behavior); - -/** - * Dequeue several objects from a ring (multi-consumers safe). When - * the request objects are more than the available objects, only dequeue the - * actual number of objects - * - * This function uses a "compare and set" instruction to move the - * consumer index atomically. - * - * @param r - * A pointer to the ring structure. - * @param obj_table - * A pointer to a table of void * pointers (objects) that will be filled. - * @param n - * The number of objects to dequeue from the ring to the obj_table. - * @param behavior - * ODP_RING_QUEUE_FIXED: Dequeue a fixed number of items from a ring - * ODP_RING_QUEUE_VARIABLE: Dequeue as many items a possible from ring - * @return - * Depend on the behavior value - * if behavior = ODP_RING_QUEUE_FIXED - * - 0: Success; objects dequeued. - * - -ENOENT: Not enough entries in the ring to dequeue; no object is - * dequeued. - * if behavior = ODP_RING_QUEUE_VARIABLE - * - n: Actual number of objects dequeued. - */ - -int __odph_ring_mc_do_dequeue(odph_ring_t *r, void **obj_table, - unsigned n, - enum odph_ring_queue_behavior behavior); - -/** - * Dequeue several objects from a ring (NOT multi-consumers safe). - * When the request objects are more than the available objects, only dequeue - * the actual number of objects - * - * @param r - * A pointer to the ring structure. - * @param obj_table - * A pointer to a table of void * pointers (objects) that will be filled. - * @param n - * The number of objects to dequeue from the ring to the obj_table. - * @param behavior - * ODP_RING_QUEUE_FIXED: Dequeue a fixed number of items from a ring - * ODP_RING_QUEUE_VARIABLE: Dequeue as many items a possible from ring - * @return - * Depend on the behavior value - * if behavior = ODP_RING_QUEUE_FIXED - * - 0: Success; objects dequeued. - * - -ENOENT: Not enough entries in the ring to dequeue; no object is - * dequeued. - * if behavior = ODP_RING_QUEUE_VARIABLE - * - n: Actual number of objects dequeued. - */ -int __odph_ring_sc_do_dequeue(odph_ring_t *r, void **obj_table, - unsigned n, - enum odph_ring_queue_behavior behavior); - -/** - * Enqueue several objects on the ring (multi-producers safe). - * - * This function uses a "compare and set" instruction to move the - * producer index atomically. - * - * @param r - * A pointer to the ring structure. - * @param obj_table - * A pointer to a table of void * pointers (objects). - * @param n - * The number of objects to add in the ring from the obj_table. - * @return - * - 0: Success; objects enqueue. - * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the - * high water mark is exceeded. - * - -ENOBUFS: Not enough room in the ring to enqueue, no object is enqueued. - */ -int odph_ring_mp_enqueue_bulk(odph_ring_t *r, void * const *obj_table, - unsigned n); - -/** - * Enqueue several objects on a ring (NOT multi-producers safe). - * - * @param r - * A pointer to the ring structure. - * @param obj_table - * A pointer to a table of void * pointers (objects). - * @param n - * The number of objects to add in the ring from the obj_table. - * @return - * - 0: Success; objects enqueued. - * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the - * high water mark is exceeded. - * - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued. - */ -int odph_ring_sp_enqueue_bulk(odph_ring_t *r, void * const *obj_table, - unsigned n); - -/** - * Dequeue several objects from a ring (multi-consumers safe). - * - * This function uses a "compare and set" instruction to move the - * consumer index atomically. - * - * @param r - * A pointer to the ring structure. - * @param obj_table - * A pointer to a table of void * pointers (objects) that will be filled. - * @param n - * The number of objects to dequeue from the ring to the obj_table. - * @return - * - 0: Success; objects dequeued. - * - -ENOENT: Not enough entries in the ring to dequeue; no object is - * dequeued. - */ -int odph_ring_mc_dequeue_bulk(odph_ring_t *r, void **obj_table, unsigned n); - -/** - * Dequeue several objects from a ring (NOT multi-consumers safe). - * - * @param r - * A pointer to the ring structure. - * @param obj_table - * A pointer to a table of void * pointers (objects) that will be filled. - * @param n - * The number of objects to dequeue from the ring to the obj_table, - * must be strictly positive. - * @return - * - 0: Success; objects dequeued. - * - -ENOENT: Not enough entries in the ring to dequeue; no object is - * dequeued. - */ -int odph_ring_sc_dequeue_bulk(odph_ring_t *r, void **obj_table, unsigned n); - -/** - * Test if a ring is full. - * - * @param r - * A pointer to the ring structure. - * @return - * - 1: The ring is full. - * - 0: The ring is not full. - */ -int odph_ring_full(const odph_ring_t *r); - -/** - * Test if a ring is empty. - * - * @param r - * A pointer to the ring structure. - * @return - * - 1: The ring is empty. - * - 0: The ring is not empty. - */ -int odph_ring_empty(const odph_ring_t *r); - -/** - * Return the number of entries in a ring. - * - * @param r - * A pointer to the ring structure. - * @return - * The number of entries in the ring. - */ -unsigned odph_ring_count(const odph_ring_t *r); - -/** - * Return the number of free entries in a ring. - * - * @param r - * A pointer to the ring structure. - * @return - * The number of free entries in the ring. - */ -unsigned odph_ring_free_count(const odph_ring_t *r); - -/** - * search ring by name - * @param name ring name to search - * @return pointer to ring otherwise NULL - */ -odph_ring_t *odph_ring_lookup(const char *name); - -/** - * Enqueue several objects on the ring (multi-producers safe). - * - * This function uses a "compare and set" instruction to move the - * producer index atomically. - * - * @param r - * A pointer to the ring structure. - * @param obj_table - * A pointer to a table of void * pointers (objects). - * @param n - * The number of objects to add in the ring from the obj_table. - * @return - * - n: Actual number of objects enqueued. - */ -int odph_ring_mp_enqueue_burst(odph_ring_t *r, void * const *obj_table, - unsigned n); - -/** - * Enqueue several objects on a ring (NOT multi-producers safe). - * - * @param r - * A pointer to the ring structure. - * @param obj_table - * A pointer to a table of void * pointers (objects). - * @param n - * The number of objects to add in the ring from the obj_table. - * @return - * - n: Actual number of objects enqueued. - */ -int odph_ring_sp_enqueue_burst(odph_ring_t *r, void * const *obj_table, - unsigned n); -/** - * Enqueue several objects on a ring. - * - * This function calls the multi-producer or the single-producer - * version depending on the default behavior that was specified at - * ring creation time (see flags). - * - * @param r - * A pointer to the ring structure. - * @param obj_table - * A pointer to a table of void * pointers (objects). - * @param n - * The number of objects to add in the ring from the obj_table. - * @return - * - n: Actual number of objects enqueued. - */ -int odph_ring_enqueue_burst(odph_ring_t *r, void * const *obj_table, - unsigned n); - -/** - * Dequeue several objects from a ring (multi-consumers safe). When the request - * objects are more than the available objects, only dequeue the actual number - * of objects - * - * This function uses a "compare and set" instruction to move the - * consumer index atomically. - * - * @param r - * A pointer to the ring structure. - * @param obj_table - * A pointer to a table of void * pointers (objects) that will be filled. - * @param n - * The number of objects to dequeue from the ring to the obj_table. - * @return - * - n: Actual number of objects dequeued, 0 if ring is empty - */ -int odph_ring_mc_dequeue_burst(odph_ring_t *r, void **obj_table, unsigned n); - -/** - * Dequeue several objects from a ring (NOT multi-consumers safe).When the - * request objects are more than the available objects, only dequeue the - * actual number of objects - * - * @param r - * A pointer to the ring structure. - * @param obj_table - * A pointer to a table of void * pointers (objects) that will be filled. - * @param n - * The number of objects to dequeue from the ring to the obj_table. - * @return - * - n: Actual number of objects dequeued, 0 if ring is empty - */ -int odph_ring_sc_dequeue_burst(odph_ring_t *r, void **obj_table, unsigned n); - -/** - * Dequeue multiple objects from a ring up to a maximum number. - * - * This function calls the multi-consumers or the single-consumer - * version, depending on the default behaviour that was specified at - * ring creation time (see flags). - * - * @param r - * A pointer to the ring structure. - * @param obj_table - * A pointer to a table of void * pointers (objects) that will be filled. - * @param n - * The number of objects to dequeue from the ring to the obj_table. - * @return - * - Number of objects dequeued, or a negative error code on error - */ -int odph_ring_dequeue_burst(odph_ring_t *r, void **obj_table, unsigned n); - -/** - * dump the status of all rings on the console - */ -void odph_ring_list_dump(void); - -/** - * initialise ring tailq - */ -void odph_ring_tailq_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/helper/ring.c b/helper/ring.c deleted file mode 100644 index 6699186..0000000 --- a/helper/ring.c +++ /dev/null @@ -1,634 +0,0 @@ -/* Copyright (c) 2014, Linaro Limited - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Derived from FreeBSD's bufring.c - * - ************************************************************************** - * - * Copyright (c) 2007,2008 Kip Macy kmacy@freebsd.org - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. The name of Kip Macy nor the names of other - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ***************************************************************************/ - -#include -#include -#include -#include -#include "odph_debug.h" -#include - -static TAILQ_HEAD(, odph_ring) odp_ring_list; - -#define RING_VAL_IS_POWER_2(x) ((((x) - 1) & (x)) == 0) - -/* - * the enqueue of pointers on the ring. - */ -#define ENQUEUE_PTRS() do { \ - const uint32_t size = r->prod.size; \ - uint32_t idx = prod_head & mask; \ - if (odp_likely(idx + n < size)) { \ - for (i = 0; i < (n & ((~(unsigned)0x3))); i += 4, idx += 4) { \ - r->ring[idx] = obj_table[i]; \ - r->ring[idx+1] = obj_table[i+1]; \ - r->ring[idx+2] = obj_table[i+2]; \ - r->ring[idx+3] = obj_table[i+3]; \ - } \ - switch (n & 0x3) { \ - case 3: \ - r->ring[idx++] = obj_table[i++]; \ - case 2: \ - r->ring[idx++] = obj_table[i++]; \ - case 1: \ - r->ring[idx++] = obj_table[i++]; \ - } \ - } else { \ - for (i = 0; idx < size; i++, idx++)\ - r->ring[idx] = obj_table[i]; \ - for (idx = 0; i < n; i++, idx++) \ - r->ring[idx] = obj_table[i]; \ - } \ -} while (0) - -/* - * the actual copy of pointers on the ring to obj_table. - */ -#define DEQUEUE_PTRS() do { \ - uint32_t idx = cons_head & mask; \ - const uint32_t size = r->cons.size; \ - if (odp_likely(idx + n < size)) { \ - for (i = 0; i < (n & (~(unsigned)0x3)); i += 4, idx += 4) {\ - obj_table[i] = r->ring[idx]; \ - obj_table[i+1] = r->ring[idx+1]; \ - obj_table[i+2] = r->ring[idx+2]; \ - obj_table[i+3] = r->ring[idx+3]; \ - } \ - switch (n & 0x3) { \ - case 3: \ - obj_table[i++] = r->ring[idx++]; \ - case 2: \ - obj_table[i++] = r->ring[idx++]; \ - case 1: \ - obj_table[i++] = r->ring[idx++]; \ - } \ - } else { \ - for (i = 0; idx < size; i++, idx++) \ - obj_table[i] = r->ring[idx]; \ - for (idx = 0; i < n; i++, idx++) \ - obj_table[i] = r->ring[idx]; \ - } \ -} while (0) - -static odp_rwlock_t qlock; /* rings tailq lock */ - -/* init tailq_ring */ -void odph_ring_tailq_init(void) -{ - TAILQ_INIT(&odp_ring_list); - odp_rwlock_init(&qlock); -} - -/* create the ring */ -odph_ring_t * -odph_ring_create(const char *name, unsigned count, unsigned flags) -{ - char ring_name[ODPH_RING_NAMESIZE]; - odph_ring_t *r; - size_t ring_size; - odp_shm_t shm; - - /* count must be a power of 2 */ - if (!RING_VAL_IS_POWER_2(count) || (count > ODPH_RING_SZ_MASK)) { - ODPH_ERR("Requested size is invalid, must be power of 2, and do not exceed the size limit %u\n", - ODPH_RING_SZ_MASK); - return NULL; - } - - snprintf(ring_name, sizeof(ring_name), "%s", name); - ring_size = count*sizeof(void *)+sizeof(odph_ring_t); - - odp_rwlock_write_lock(&qlock); - /* reserve a memory zone for this ring.*/ - shm = odp_shm_reserve(ring_name, ring_size, ODP_CACHE_LINE_SIZE, 0); - - r = odp_shm_addr(shm); - - if (r != NULL) { - /* init the ring structure */ - snprintf(r->name, sizeof(r->name), "%s", name); - r->flags = flags; - r->prod.watermark = count; - r->prod.sp_enqueue = !!(flags & ODPH_RING_F_SP_ENQ); - r->cons.sc_dequeue = !!(flags & ODPH_RING_F_SC_DEQ); - r->prod.size = count; - r->cons.size = count; - r->prod.mask = count-1; - r->cons.mask = count-1; - r->prod.head = 0; - r->cons.head = 0; - r->prod.tail = 0; - r->cons.tail = 0; - - TAILQ_INSERT_TAIL(&odp_ring_list, r, next); - } else { - ODPH_ERR("Cannot reserve memory\n"); - } - - odp_rwlock_write_unlock(&qlock); - return r; -} - -/* - * change the high water mark. If *count* is 0, water marking is - * disabled - */ -int odph_ring_set_water_mark(odph_ring_t *r, unsigned count) -{ - if (count >= r->prod.size) - return -EINVAL; - - /* if count is 0, disable the watermarking */ - if (count == 0) - count = r->prod.size; - - r->prod.watermark = count; - return 0; -} - -/** - * Enqueue several objects on the ring (multi-producers safe). - */ -int __odph_ring_mp_do_enqueue(odph_ring_t *r, void * const *obj_table, - unsigned n, enum odph_ring_queue_behavior behavior) -{ - uint32_t prod_head, prod_next; - uint32_t cons_tail, free_entries; - const unsigned max = n; - int success; - unsigned i; - uint32_t mask = r->prod.mask; - int ret; - - /* move prod.head atomically */ - do { - /* Reset n to the initial burst count */ - n = max; - - prod_head = r->prod.head; - cons_tail = r->cons.tail; - /* The subtraction is done between two unsigned 32bits value - * (the result is always modulo 32 bits even if we have - * prod_head > cons_tail). So 'free_entries' is always between 0 - * and size(ring)-1. */ - free_entries = (mask + cons_tail - prod_head); - - /* check that we have enough room in ring */ - if (odp_unlikely(n > free_entries)) { - if (behavior == ODPH_RING_QUEUE_FIXED) { - return -ENOBUFS; - } else { - /* No free entry available */ - if (odp_unlikely(free_entries == 0)) - return 0; - - n = free_entries; - } - } - - prod_next = prod_head + n; - success = __atomic_compare_exchange_n(&r->prod.head, - &prod_head, - prod_next, - false/*strong*/, - __ATOMIC_ACQUIRE, - __ATOMIC_RELAXED); - } while (odp_unlikely(success == 0)); - - /* write entries in ring */ - ENQUEUE_PTRS(); - - /* if we exceed the watermark */ - if (odp_unlikely(((mask + 1) - free_entries + n) > r->prod.watermark)) { - ret = (behavior == ODPH_RING_QUEUE_FIXED) ? -EDQUOT : - (int)(n | ODPH_RING_QUOT_EXCEED); - } else { - ret = (behavior == ODPH_RING_QUEUE_FIXED) ? 0 : n; - } - - /* - * If there are other enqueues in progress that preceded us, - * we need to wait for them to complete - */ - while (odp_unlikely(r->prod.tail != prod_head)) - odp_cpu_pause(); - - /* Release our entries and the memory they refer to */ - __atomic_thread_fence(__ATOMIC_RELEASE); - r->prod.tail = prod_next; - return ret; -} - -/** - * Enqueue several objects on a ring (NOT multi-producers safe). - */ -int __odph_ring_sp_do_enqueue(odph_ring_t *r, void * const *obj_table, - unsigned n, enum odph_ring_queue_behavior behavior) -{ - uint32_t prod_head, cons_tail; - uint32_t prod_next, free_entries; - unsigned i; - uint32_t mask = r->prod.mask; - int ret; - - prod_head = r->prod.head; - cons_tail = r->cons.tail; - /* The subtraction is done between two unsigned 32bits value - * (the result is always modulo 32 bits even if we have - * prod_head > cons_tail). So 'free_entries' is always between 0 - * and size(ring)-1. */ - free_entries = mask + cons_tail - prod_head; - - /* check that we have enough room in ring */ - if (odp_unlikely(n > free_entries)) { - if (behavior == ODPH_RING_QUEUE_FIXED) { - return -ENOBUFS; - } else { - /* No free entry available */ - if (odp_unlikely(free_entries == 0)) - return 0; - - n = free_entries; - } - } - - prod_next = prod_head + n; - r->prod.head = prod_next; - - /* write entries in ring */ - ENQUEUE_PTRS(); - - /* if we exceed the watermark */ - if (odp_unlikely(((mask + 1) - free_entries + n) > r->prod.watermark)) { - ret = (behavior == ODPH_RING_QUEUE_FIXED) ? -EDQUOT : - (int)(n | ODPH_RING_QUOT_EXCEED); - } else { - ret = (behavior == ODPH_RING_QUEUE_FIXED) ? 0 : n; - } - - /* Release our entries and the memory they refer to */ - __atomic_thread_fence(__ATOMIC_RELEASE); - r->prod.tail = prod_next; - return ret; -} - -/** - * Dequeue several objects from a ring (multi-consumers safe). - */ - -int __odph_ring_mc_do_dequeue(odph_ring_t *r, void **obj_table, - unsigned n, enum odph_ring_queue_behavior behavior) -{ - uint32_t cons_head, prod_tail; - uint32_t cons_next, entries; - const unsigned max = n; - int success; - unsigned i; - uint32_t mask = r->prod.mask; - - /* move cons.head atomically */ - do { - /* Restore n as it may change every loop */ - n = max; - - cons_head = r->cons.head; - prod_tail = r->prod.tail; - /* The subtraction is done between two unsigned 32bits value - * (the result is always modulo 32 bits even if we have - * cons_head > prod_tail). So 'entries' is always between 0 - * and size(ring)-1. */ - entries = (prod_tail - cons_head); - - /* Set the actual entries for dequeue */ - if (n > entries) { - if (behavior == ODPH_RING_QUEUE_FIXED) { - return -ENOENT; - } else { - if (odp_unlikely(entries == 0)) - return 0; - - n = entries; - } - } - - cons_next = cons_head + n; - success = __atomic_compare_exchange_n(&r->cons.head, - &cons_head, - cons_next, - false/*strong*/, - __ATOMIC_ACQUIRE, - __ATOMIC_RELAXED); - } while (odp_unlikely(success == 0)); - - /* copy in table */ - DEQUEUE_PTRS(); - - /* - * If there are other dequeues in progress that preceded us, - * we need to wait for them to complete - */ - while (odp_unlikely(r->cons.tail != cons_head)) - odp_cpu_pause(); - - /* Release our entries and the memory they refer to */ - __atomic_thread_fence(__ATOMIC_RELEASE); - r->cons.tail = cons_next; - - return behavior == ODPH_RING_QUEUE_FIXED ? 0 : n; -} - -/** - * Dequeue several objects from a ring (NOT multi-consumers safe). - */ -int __odph_ring_sc_do_dequeue(odph_ring_t *r, void **obj_table, - unsigned n, enum odph_ring_queue_behavior behavior) -{ - uint32_t cons_head, prod_tail; - uint32_t cons_next, entries; - unsigned i; - uint32_t mask = r->prod.mask; - - cons_head = r->cons.head; - prod_tail = r->prod.tail; - /* The subtraction is done between two unsigned 32bits value - * (the result is always modulo 32 bits even if we have - * cons_head > prod_tail). So 'entries' is always between 0 - * and size(ring)-1. */ - entries = prod_tail - cons_head; - - if (n > entries) { - if (behavior == ODPH_RING_QUEUE_FIXED) { - return -ENOENT; - } else { - if (odp_unlikely(entries == 0)) - return 0; - - n = entries; - } - } - - cons_next = cons_head + n; - r->cons.head = cons_next; - - /* Acquire the pointers and the memory they refer to */ - __atomic_thread_fence(__ATOMIC_ACQUIRE); - /* copy in table */ - DEQUEUE_PTRS(); - - r->cons.tail = cons_next; - return behavior == ODPH_RING_QUEUE_FIXED ? 0 : n; -} - -/** - * Enqueue several objects on the ring (multi-producers safe). - */ -int odph_ring_mp_enqueue_bulk(odph_ring_t *r, void * const *obj_table, - unsigned n) -{ - return __odph_ring_mp_do_enqueue(r, obj_table, n, - ODPH_RING_QUEUE_FIXED); -} - -/** - * Enqueue several objects on a ring (NOT multi-producers safe). - */ -int odph_ring_sp_enqueue_bulk(odph_ring_t *r, void * const *obj_table, - unsigned n) -{ - return __odph_ring_sp_do_enqueue(r, obj_table, n, - ODPH_RING_QUEUE_FIXED); -} - -/** - * Dequeue several objects from a ring (multi-consumers safe). - */ -int odph_ring_mc_dequeue_bulk(odph_ring_t *r, void **obj_table, unsigned n) -{ - return __odph_ring_mc_do_dequeue(r, obj_table, n, - ODPH_RING_QUEUE_FIXED); -} - -/** - * Dequeue several objects from a ring (NOT multi-consumers safe). - */ -int odph_ring_sc_dequeue_bulk(odph_ring_t *r, void **obj_table, unsigned n) -{ - return __odph_ring_sc_do_dequeue(r, obj_table, n, - ODPH_RING_QUEUE_FIXED); -} - -/** - * Test if a ring is full. - */ -int odph_ring_full(const odph_ring_t *r) -{ - uint32_t prod_tail = r->prod.tail; - uint32_t cons_tail = r->cons.tail; - return (((cons_tail - prod_tail - 1) & r->prod.mask) == 0); -} - -/** - * Test if a ring is empty. - */ -int odph_ring_empty(const odph_ring_t *r) -{ - uint32_t prod_tail = r->prod.tail; - uint32_t cons_tail = r->cons.tail; - return !!(cons_tail == prod_tail); -} - -/** - * Return the number of entries in a ring. - */ -unsigned odph_ring_count(const odph_ring_t *r) -{ - uint32_t prod_tail = r->prod.tail; - uint32_t cons_tail = r->cons.tail; - return (prod_tail - cons_tail) & r->prod.mask; -} - -/** - * Return the number of free entries in a ring. - */ -unsigned odph_ring_free_count(const odph_ring_t *r) -{ - uint32_t prod_tail = r->prod.tail; - uint32_t cons_tail = r->cons.tail; - return (cons_tail - prod_tail - 1) & r->prod.mask; -} - -/* dump the status of the ring on the console */ -void odph_ring_dump(const odph_ring_t *r) -{ - ODPH_DBG("ring <%s>@%p\n", r->name, r); - ODPH_DBG(" flags=%x\n", r->flags); - ODPH_DBG(" size=%" PRIu32 "\n", r->prod.size); - ODPH_DBG(" ct=%" PRIu32 "\n", r->cons.tail); - ODPH_DBG(" ch=%" PRIu32 "\n", r->cons.head); - ODPH_DBG(" pt=%" PRIu32 "\n", r->prod.tail); - ODPH_DBG(" ph=%" PRIu32 "\n", r->prod.head); - ODPH_DBG(" used=%u\n", odph_ring_count(r)); - ODPH_DBG(" avail=%u\n", odph_ring_free_count(r)); - if (r->prod.watermark == r->prod.size) - ODPH_DBG(" watermark=0\n"); - else - ODPH_DBG(" watermark=%" PRIu32 "\n", r->prod.watermark); -} - -/* dump the status of all rings on the console */ -void odph_ring_list_dump(void) -{ - const odph_ring_t *mp = NULL; - - odp_rwlock_read_lock(&qlock); - - TAILQ_FOREACH(mp, &odp_ring_list, next) { - odph_ring_dump(mp); - } - - odp_rwlock_read_unlock(&qlock); -} - -/* search a ring from its name */ -odph_ring_t *odph_ring_lookup(const char *name) -{ - odph_ring_t *r; - - odp_rwlock_read_lock(&qlock); - TAILQ_FOREACH(r, &odp_ring_list, next) { - if (strncmp(name, r->name, ODPH_RING_NAMESIZE) == 0) - break; - } - odp_rwlock_read_unlock(&qlock); - - return r; -} - -/** - * Enqueue several objects on the ring (multi-producers safe). - */ -int odph_ring_mp_enqueue_burst(odph_ring_t *r, void * const *obj_table, - unsigned n) -{ - return __odph_ring_mp_do_enqueue(r, obj_table, n, - ODPH_RING_QUEUE_VARIABLE); -} - -/** - * Enqueue several objects on a ring (NOT multi-producers safe). - */ -int odph_ring_sp_enqueue_burst(odph_ring_t *r, void * const *obj_table, - unsigned n) -{ - return __odph_ring_sp_do_enqueue(r, obj_table, n, - ODPH_RING_QUEUE_VARIABLE); -} - -/** - * Enqueue several objects on a ring. - */ -int odph_ring_enqueue_burst(odph_ring_t *r, void * const *obj_table, - unsigned n) -{ - if (r->prod.sp_enqueue) - return odph_ring_sp_enqueue_burst(r, obj_table, n); - else - return odph_ring_mp_enqueue_burst(r, obj_table, n); -} - -/** - * Dequeue several objects from a ring (multi-consumers safe). - */ -int odph_ring_mc_dequeue_burst(odph_ring_t *r, void **obj_table, unsigned n) -{ - return __odph_ring_mc_do_dequeue(r, obj_table, n, - ODPH_RING_QUEUE_VARIABLE); -} - -/** - * Dequeue several objects from a ring (NOT multi-consumers safe). - */ -int odph_ring_sc_dequeue_burst(odph_ring_t *r, void **obj_table, unsigned n) -{ - return __odph_ring_sc_do_dequeue(r, obj_table, n, - ODPH_RING_QUEUE_VARIABLE); -} - -/** - * Dequeue multiple objects from a ring up to a maximum number. - */ -int odph_ring_dequeue_burst(odph_ring_t *r, void **obj_table, unsigned n) -{ - if (r->cons.sc_dequeue) - return odph_ring_sc_dequeue_burst(r, obj_table, n); - else - return odph_ring_mc_dequeue_burst(r, obj_table, n); -} diff --git a/test/Makefile.am b/test/Makefile.am index 2ba8008..4a75364 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = api_test performance miscellaneous +SUBDIRS = performance miscellaneous if cunit_support SUBDIRS += validation diff --git a/test/api_test/.gitignore b/test/api_test/.gitignore deleted file mode 100644 index 950f443..0000000 --- a/test/api_test/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -odp_ring -odp_shm diff --git a/test/api_test/Makefile.am b/test/api_test/Makefile.am deleted file mode 100644 index 97ca5df..0000000 --- a/test/api_test/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -include $(top_srcdir)/test/Makefile.inc - -bin_PROGRAMS = odp_ring$(EXEEXT) - -odp_ring_CFLAGS = $(AM_CFLAGS) - -odp_ring_LDFLAGS = $(AM_LDFLAGS) -static - -noinst_HEADERS = \ - $(top_srcdir)/test/api_test/odp_common.h \ - $(top_srcdir)/test/test_debug.h - -dist_odp_ring_SOURCES = odp_ring_test.c odp_common.c - -#The tests will need to retain the deprecated test implementation -AM_CFLAGS += -Wno-deprecated-declarations \ No newline at end of file diff --git a/test/api_test/odp_common.c b/test/api_test/odp_common.c deleted file mode 100644 index 70aee96..0000000 --- a/test/api_test/odp_common.c +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (c) 2013, Linaro Limited - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/** - * @file - * - * ODP test application common - */ - -#include -#include -#include -#include -#include - -#define MAX_WORKERS 32 /**< Max worker threads */ - -/* Globals */ -static odph_linux_pthread_t thread_tbl[MAX_WORKERS]; /**< worker threads table*/ -static int num_workers; /**< number of workers */ - -/** - * Print system information - */ -void odp_print_system_info(void) -{ - odp_cpumask_t cpumask; - char str[ODP_CPUMASK_STR_SIZE]; - - memset(str, 1, sizeof(str)); - - odp_cpumask_zero(&cpumask); - - odp_cpumask_from_str(&cpumask, "0x1"); - (void)odp_cpumask_to_str(&cpumask, str, sizeof(str)); - - printf("\n"); - printf("ODP system info\n"); - printf("---------------\n"); - printf("ODP API version: %s\n", odp_version_api_str()); - printf("CPU model: %s\n", odp_cpu_model_str()); - printf("CPU freq (hz): %"PRIu64"\n", odp_cpu_hz_max()); - printf("Cache line size: %i\n", odp_sys_cache_line_size()); - printf("CPU count: %i\n", odp_cpu_count()); - printf("CPU mask: %s\n", str); - - printf("\n"); -} - -/** test init globals and call odp_init_global() */ -int odp_test_global_init(void) -{ - memset(thread_tbl, 0, sizeof(thread_tbl)); - - if (odp_init_global(NULL, NULL)) { - LOG_ERR("ODP global init failed.\n"); - return -1; - } - - num_workers = odp_cpu_count(); - /* force to max CPU count */ - if (num_workers > MAX_WORKERS) - num_workers = MAX_WORKERS; - - return 0; -} - -/** create test thread */ -int odp_test_thread_create(void *func_ptr(void *), pthrd_arg *arg) -{ - odp_cpumask_t cpumask; - - /* Create and init additional threads */ - odp_cpumask_default_worker(&cpumask, arg->numthrds); - odph_linux_pthread_create(thread_tbl, &cpumask, func_ptr, - (void *)arg, ODP_THREAD_WORKER); - - return 0; -} - -/** exit from test thread */ -int odp_test_thread_exit(pthrd_arg *arg) -{ - /* Wait for other threads to exit */ - odph_linux_pthread_join(thread_tbl, arg->numthrds); - - return 0; -} diff --git a/test/api_test/odp_common.h b/test/api_test/odp_common.h deleted file mode 100644 index f321b6b..0000000 --- a/test/api_test/odp_common.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (c) 2013, Linaro Limited - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/** - * @file - * - * ODP test application common headers - */ - -#ifndef ODP_COMMON_H -#define ODP_COMMON_H - -#define MAX_WORKERS 32 /**< Maximum number of work threads */ - -/** types of tests */ -typedef enum { - ODP_ATOMIC_TEST = 0, - ODP_SHM_TEST, - ODP_RING_TEST_BASIC, - ODP_RING_TEST_STRESS, - ODP_TIMER_PING_TEST, - ODP_MAX_TEST -} odp_test_case_e; - -/** - * Thread argument - */ -typedef struct { - int testcase; /**< specifies which set of API's to exercise */ - int numthrds; /**< no of pthreads to create */ -} pthrd_arg; - -extern void odp_print_system_info(void); -extern int odp_test_global_init(void); -/** create thread fro start_routine function */ -extern int odp_test_thread_create(void *(*start_routine) (void *), pthrd_arg *); -extern int odp_test_thread_exit(pthrd_arg *); - -#endif /* ODP_COMMON_H */ diff --git a/test/api_test/odp_ring_test.c b/test/api_test/odp_ring_test.c deleted file mode 100644 index e8a962a..0000000 --- a/test/api_test/odp_ring_test.c +++ /dev/null @@ -1,470 +0,0 @@ -/* Copyright (c) 2014, Linaro Limited - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2013 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -/** - * @file - * - * ODP test ring - */ - -#include -#include -#include -#include -#include -#include -#include - -#define RING_SIZE 4096 -#define MAX_BULK 32 - -#define RING_TEST_BASIC - -static int test_ring_basic(odph_ring_t *r) -{ - void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL; - int ret; - unsigned i, num_elems; - - /* alloc dummy object pointers */ - src = malloc(RING_SIZE*2*sizeof(void *)); - if (src == NULL) { - LOG_ERR("failed to allocate test ring src memory\n"); - goto fail; - } - for (i = 0; i < RING_SIZE*2; i++) - src[i] = (void *)(unsigned long)i; - - cur_src = src; - - /* alloc some room for copied objects */ - dst = malloc(RING_SIZE*2*sizeof(void *)); - if (dst == NULL) { - LOG_ERR("failed to allocate test ring dst memory\n"); - goto fail; - } - - memset(dst, 0, RING_SIZE*2*sizeof(void *)); - cur_dst = dst; - - printf("Test SP & SC basic functions\n"); - printf("enqueue 1 obj\n"); - ret = odph_ring_sp_enqueue_burst(r, cur_src, 1); - cur_src += 1; - if ((ret & ODPH_RING_SZ_MASK) != 1) { - LOG_ERR("sp_enq for 1 obj failed\n"); - goto fail; - } - - printf("enqueue 2 objs\n"); - ret = odph_ring_sp_enqueue_burst(r, cur_src, 2); - cur_src += 2; - if ((ret & ODPH_RING_SZ_MASK) != 2) { - LOG_ERR("sp_enq for 2 obj failed\n"); - goto fail; - } - - printf("enqueue MAX_BULK objs\n"); - ret = odph_ring_sp_enqueue_burst(r, cur_src, MAX_BULK); - if ((ret & ODPH_RING_SZ_MASK) != MAX_BULK) { - LOG_ERR("sp_enq for %d obj failed\n", MAX_BULK); - goto fail; - } - - printf("dequeue 1 obj\n"); - ret = odph_ring_sc_dequeue_burst(r, cur_dst, 1); - cur_dst += 1; - if ((ret & ODPH_RING_SZ_MASK) != 1) { - LOG_ERR("sc_deq for 1 obj failed\n"); - goto fail; - } - - printf("dequeue 2 objs\n"); - ret = odph_ring_sc_dequeue_burst(r, cur_dst, 2); - cur_dst += 2; - if ((ret & ODPH_RING_SZ_MASK) != 2) { - LOG_ERR("sc_deq for 2 obj failed\n"); - goto fail; - } - - printf("dequeue MAX_BULK objs\n"); - ret = odph_ring_sc_dequeue_burst(r, cur_dst, MAX_BULK); - cur_dst += MAX_BULK; - if ((ret & ODPH_RING_SZ_MASK) != MAX_BULK) { - LOG_ERR("sc_deq for %d obj failed\n", MAX_BULK); - goto fail; - } - - /* check data */ - if (memcmp(src, dst, cur_dst - dst)) { - LOG_ERR("data after dequeue is not the same\n"); - goto fail; - } - - cur_src = src; - cur_dst = dst; - - printf("Test MP & MC basic functions\n"); - - printf("enqueue 1 obj\n"); - ret = odph_ring_mp_enqueue_bulk(r, cur_src, 1); - cur_src += 1; - if (ret != 0) { - LOG_ERR("mp_enq for 1 obj failed\n"); - goto fail; - } - printf("enqueue 2 objs\n"); - ret = odph_ring_mp_enqueue_bulk(r, cur_src, 2); - cur_src += 2; - if (ret != 0) { - LOG_ERR("mp_enq for 2 obj failed\n"); - goto fail; - } - printf("enqueue MAX_BULK objs\n"); - ret = odph_ring_mp_enqueue_bulk(r, cur_src, MAX_BULK); - if (ret != 0) { - LOG_ERR("mp_enq for %d obj failed\n", MAX_BULK); - goto fail; - } - printf("dequeue 1 obj\n"); - ret = odph_ring_mc_dequeue_bulk(r, cur_dst, 1); - cur_dst += 1; - if (ret != 0) { - LOG_ERR("mc_deq for 1 obj failed\n"); - goto fail; - } - printf("dequeue 2 objs\n"); - ret = odph_ring_mc_dequeue_bulk(r, cur_dst, 2); - cur_dst += 2; - if (ret != 0) { - LOG_ERR("mc_deq for 2 obj failed\n"); - goto fail; - } - printf("dequeue MAX_BULK objs\n"); - ret = odph_ring_mc_dequeue_bulk(r, cur_dst, MAX_BULK); - cur_dst += MAX_BULK; - if (ret != 0) { - LOG_ERR("mc_deq for %d obj failed\n", MAX_BULK); - goto fail; - } - /* check data */ - if (memcmp(src, dst, cur_dst - dst)) { - LOG_ERR("data after dequeue is not the same\n"); - goto fail; - } - - printf("test watermark and default bulk enqueue / dequeue\n"); - odph_ring_set_water_mark(r, 20); - num_elems = 16; - - cur_src = src; - cur_dst = dst; - - ret = odph_ring_mp_enqueue_bulk(r, cur_src, num_elems); - cur_src += num_elems; - if (ret != 0) { - LOG_ERR("Cannot enqueue\n"); - goto fail; - } - ret = odph_ring_mp_enqueue_bulk(r, cur_src, num_elems); - if (ret != -EDQUOT) { - LOG_ERR("Watermark not exceeded\n"); - goto fail; - } - ret = odph_ring_mc_dequeue_bulk(r, cur_dst, num_elems); - cur_dst += num_elems; - if (ret != 0) { - LOG_ERR("Cannot dequeue\n"); - goto fail; - } - ret = odph_ring_mc_dequeue_bulk(r, cur_dst, num_elems); - cur_dst += num_elems; - if (ret != 0) { - LOG_ERR("Cannot dequeue2\n"); - goto fail; - } - - /* check data */ - if (memcmp(src, dst, cur_dst - dst)) { - LOG_ERR("data after dequeue is not the same\n"); - goto fail; - } - - printf("basic enqueu, dequeue test for ring <%s>@%p passed\n", - r->name, r); - - free(src); - free(dst); - return 0; - -fail: - free(src); - free(dst); - return -1; -} - -/* global shared ring used for stress testing */ -static odph_ring_t *r_stress; - -/* Stress func for Multi producer only */ -static int producer_fn(void) -{ - unsigned i; - - void **src = NULL; - - /* alloc dummy object pointers */ - src = malloc(MAX_BULK*2*sizeof(void *)); - if (src == NULL) { - LOG_ERR("failed to allocate producer memory.\n"); - return -1; - } - for (i = 0; i < MAX_BULK; i++) - src[i] = (void *)(unsigned long)i; - - do { - i = odph_ring_mp_enqueue_bulk(r_stress, src, MAX_BULK); - if (i == 0) { - free(src); - return 0; - } - } while (1); -} - -/* Stress func for Multi consumer only */ -static int consumer_fn(void) -{ - unsigned i; - void **src = NULL; - - /* alloc dummy object pointers */ - src = malloc(MAX_BULK*2*sizeof(void *)); - if (src == NULL) { - LOG_ERR("failed to allocate consumer memory.\n"); - return -1; - } - - do { - i = odph_ring_mc_dequeue_bulk(r_stress, src, MAX_BULK); - if (i == 0) { - for (i = 0; i < MAX_BULK; i++) { - if (src[i] != (void *)(unsigned long)i) { - free(src); - printf("data mismatch.. lockless ops fail\n"); - return -1; - } - } - free(src); - printf("\n Test OK !\n"); - return 0; - } - } while (1); -} - - -/* - * Note : make sure that both enqueue and dequeue - * operation starts at same time so to avoid data corruption - * Its because atomic lock will protect only indexes, but if order of - * read or write operation incorrect then data mismatch will happen - * So its resposibility of application develop to take care of order of - * data read or write. -*/ -typedef enum { - one_enq_one_deq, /* One thread to enqueue one to - dequeu at same time */ - one_enq_rest_deq, /* one thread to enq rest to - dequeue at same time */ - one_deq_rest_enq, /* one to deq and rest enq at very same time */ - multi_enq_multi_deq /* multiple enq,deq */ -} stress_type_t; - -static void test_ring_stress(stress_type_t type) -{ - int thr; - thr = odp_thread_id(); - - switch (type) { - case one_enq_one_deq: - - if (thr == 1) - producer_fn(); - if (thr == 2) - consumer_fn(); - break; - - case multi_enq_multi_deq: - if (thr%2 == 0) - producer_fn(); - else - consumer_fn(); - break; - - case one_deq_rest_enq: - case one_enq_rest_deq:/*TBD*/ - default: - LOG_ERR("Invalid stress type or test case yet not supported\n"); - } -} - -/* local struct for ring_thread argument */ -typedef struct { - pthrd_arg thrdarg; - int stress_type; -} ring_arg_t; - - -static void *test_ring(void *arg) -{ - ring_arg_t *parg = (ring_arg_t *)arg; - int thr; - char ring_name[ODPH_RING_NAMESIZE]; - odph_ring_t *r; - int result = 0; - - thr = odp_thread_id(); - - printf("Thread %i starts\n", thr); - - switch (parg->thrdarg.testcase) { - case ODP_RING_TEST_BASIC: - snprintf(ring_name, sizeof(ring_name), "test_ring_%i", thr); - - r = odph_ring_create(ring_name, RING_SIZE, - 0 /* not used, alignement - taken care inside func : todo */); - if (r == NULL) { - LOG_ERR("ring create failed\n"); - result = -1; - break; - } - /* lookup ring from its name */ - if (odph_ring_lookup(ring_name) != r) { - LOG_ERR("ring lookup failed\n"); - result = -1; - break; - } - - /* basic operations */ - if (test_ring_basic(r) < 0) { - LOG_ERR("ring basic enqueue/dequeu ops failed\n"); - result = -1; - } - - /* dump ring stats */ - odph_ring_list_dump(); - - break; - - case ODP_RING_TEST_STRESS: - test_ring_stress(parg->stress_type); - - /* dump ring stats */ - odph_ring_list_dump(); - break; - - default: - LOG_ERR("Invalid test case [%d]\n", parg->thrdarg.testcase); - result = -1; - break; - } - - LOG_DBG("result = %d\n", result); - if (result == 0) - printf("test_ring Result:pass\n"); - else - printf("test_ring Result:fail\n"); - - fflush(stdout); - - return parg; -} - - -int main(int argc __attribute__((__unused__)), - char *argv[] __attribute__((__unused__))) -{ - ring_arg_t rarg; - - if (odp_test_global_init() != 0) - return -1; - - odp_print_system_info(); - - odph_ring_tailq_init(); - - rarg.thrdarg.numthrds = odp_cpu_count(); - -#ifdef RING_TEST_BASIC - rarg.thrdarg.testcase = ODP_RING_TEST_BASIC; -#else - rarg.thrdarg.testcase = ODP_RING_TEST_STRESS; - rarg.stress_type = one_enq_one_deq; -/* rarg.stress_type = multi_enq_multi_deq;*/ - char ring_name[ODPH_RING_NAMESIZE]; - - printf("starting stess test type : %d..\n", rarg.stress_type); - /* create a ring */ - snprintf(ring_name, sizeof(ring_name), "test_ring_stress"); - - r_stress = odph_ring_create(ring_name, RING_SIZE, - 0 /* not used, alignement - taken care inside func : todo */); - if (r_stress == NULL) { - LOG_ERR("ring create failed\n"); - goto fail; - } - /* lookup ring from its name */ - if (odph_ring_lookup(ring_name) != r_stress) { - LOG_ERR("ring lookup failed\n"); - goto fail; - } -#endif - odp_test_thread_create(test_ring, (pthrd_arg *)&rarg); - -#ifndef RING_TEST_BASIC -fail: -#endif - - odp_test_thread_exit(&rarg.thrdarg); - - return 0; -} -