get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/68952/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 68952,
    "url": "https://patches.dpdk.org/api/patches/68952/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20200420122831.16973-2-konstantin.ananyev@intel.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20200420122831.16973-2-konstantin.ananyev@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200420122831.16973-2-konstantin.ananyev@intel.com",
    "date": "2020-04-20T12:28:22",
    "name": "[v7,01/10] test/ring: add contention stress test",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "4babaf95f800f88839c3646519bf7a7596192a4b",
    "submitter": {
        "id": 33,
        "url": "https://patches.dpdk.org/api/people/33/?format=api",
        "name": "Ananyev, Konstantin",
        "email": "konstantin.ananyev@intel.com"
    },
    "delegate": {
        "id": 24651,
        "url": "https://patches.dpdk.org/api/users/24651/?format=api",
        "username": "dmarchand",
        "first_name": "David",
        "last_name": "Marchand",
        "email": "david.marchand@redhat.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20200420122831.16973-2-konstantin.ananyev@intel.com/mbox/",
    "series": [
        {
            "id": 9513,
            "url": "https://patches.dpdk.org/api/series/9513/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=9513",
            "date": "2020-04-20T12:28:21",
            "name": "New sync modes for ring",
            "version": 7,
            "mbox": "https://patches.dpdk.org/series/9513/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/68952/comments/",
    "check": "fail",
    "checks": "https://patches.dpdk.org/api/patches/68952/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 4B079A0561;\n\tMon, 20 Apr 2020 14:28:51 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 3E50E1D5CD;\n\tMon, 20 Apr 2020 14:28:48 +0200 (CEST)",
            "from mga17.intel.com (mga17.intel.com [192.55.52.151])\n by dpdk.org (Postfix) with ESMTP id 0EABB1D5C9\n for <dev@dpdk.org>; Mon, 20 Apr 2020 14:28:43 +0200 (CEST)",
            "from orsmga003.jf.intel.com ([10.7.209.27])\n by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 20 Apr 2020 05:28:43 -0700",
            "from sivswdev08.ir.intel.com ([10.237.217.47])\n by orsmga003.jf.intel.com with ESMTP; 20 Apr 2020 05:28:42 -0700"
        ],
        "IronPort-SDR": [
            "\n tK/3sU2YriMVVkWMWMspip0PrOVizP5GXnjxaCA+g9vtG3FMEwID5xMrT30Ba1FpCkNXComQ4l\n /qMhizEbTCbQ==",
            "\n HmF++8n1RRzkjF9Eotnmolp6X10Uh234xKXaG9fH+m+slOUVtuUhJ0RhHwMd88dhvdvmNWv1ae\n RFIdrn8ZUWdQ=="
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.72,406,1580803200\"; d=\"scan'208\";a=\"254923871\"",
        "From": "Konstantin Ananyev <konstantin.ananyev@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "honnappa.nagarahalli@arm.com, david.marchand@redhat.com,\n jielong.zjl@antfin.com, Konstantin Ananyev <konstantin.ananyev@intel.com>",
        "Date": "Mon, 20 Apr 2020 13:28:22 +0100",
        "Message-Id": "<20200420122831.16973-2-konstantin.ananyev@intel.com>",
        "X-Mailer": "git-send-email 2.18.0",
        "In-Reply-To": "<20200420122831.16973-1-konstantin.ananyev@intel.com>",
        "References": "<20200420121113.9327-1-konstantin.ananyev@intel.com>\n <20200420122831.16973-1-konstantin.ananyev@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v7 01/10] test/ring: add contention stress test",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Introduce stress test for ring enqueue/dequeue operations.\nPerforms the following pattern on each slave worker:\ndequeue/read-write data from the dequeued objects/enqueue.\nServes as both functional and performance test of ring\nenqueue/dequeue operations under high contention\n(for both over committed and non-over committed scenarios).\n\nSigned-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>\nAcked-by: Honnappa Nagarahalli <honnappa.nagarahalli@arm.com>\n---\n app/test/Makefile                |   2 +\n app/test/meson.build             |   2 +\n app/test/test_ring_mpmc_stress.c |  31 +++\n app/test/test_ring_stress.c      |  48 ++++\n app/test/test_ring_stress.h      |  35 +++\n app/test/test_ring_stress_impl.h | 396 +++++++++++++++++++++++++++++++\n 6 files changed, 514 insertions(+)\n create mode 100644 app/test/test_ring_mpmc_stress.c\n create mode 100644 app/test/test_ring_stress.c\n create mode 100644 app/test/test_ring_stress.h\n create mode 100644 app/test/test_ring_stress_impl.h",
    "diff": "diff --git a/app/test/Makefile b/app/test/Makefile\nindex be53d33c3..a23a011df 100644\n--- a/app/test/Makefile\n+++ b/app/test/Makefile\n@@ -77,7 +77,9 @@ SRCS-y += test_external_mem.c\n SRCS-y += test_rand_perf.c\n \n SRCS-y += test_ring.c\n+SRCS-y += test_ring_mpmc_stress.c\n SRCS-y += test_ring_perf.c\n+SRCS-y += test_ring_stress.c\n SRCS-y += test_pmd_perf.c\n \n ifeq ($(CONFIG_RTE_LIBRTE_TABLE),y)\ndiff --git a/app/test/meson.build b/app/test/meson.build\nindex 04b59cffa..8824f366c 100644\n--- a/app/test/meson.build\n+++ b/app/test/meson.build\n@@ -100,7 +100,9 @@ test_sources = files('commands.c',\n \t'test_rib.c',\n \t'test_rib6.c',\n \t'test_ring.c',\n+\t'test_ring_mpmc_stress.c',\n \t'test_ring_perf.c',\n+\t'test_ring_stress.c',\n \t'test_rwlock.c',\n \t'test_sched.c',\n \t'test_service_cores.c',\ndiff --git a/app/test/test_ring_mpmc_stress.c b/app/test/test_ring_mpmc_stress.c\nnew file mode 100644\nindex 000000000..1524b0248\n--- /dev/null\n+++ b/app/test/test_ring_mpmc_stress.c\n@@ -0,0 +1,31 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include \"test_ring_stress_impl.h\"\n+\n+static inline uint32_t\n+_st_ring_dequeue_bulk(struct rte_ring *r, void **obj, uint32_t n,\n+\tuint32_t *avail)\n+{\n+\treturn rte_ring_mc_dequeue_bulk(r, obj, n, avail);\n+}\n+\n+static inline uint32_t\n+_st_ring_enqueue_bulk(struct rte_ring *r, void * const *obj, uint32_t n,\n+\tuint32_t *free)\n+{\n+\treturn rte_ring_mp_enqueue_bulk(r, obj, n, free);\n+}\n+\n+static int\n+_st_ring_init(struct rte_ring *r, const char *name, uint32_t num)\n+{\n+\treturn rte_ring_init(r, name, num, 0);\n+}\n+\n+const struct test test_ring_mpmc_stress = {\n+\t.name = \"MP/MC\",\n+\t.nb_case = RTE_DIM(tests),\n+\t.cases = tests,\n+};\ndiff --git a/app/test/test_ring_stress.c b/app/test/test_ring_stress.c\nnew file mode 100644\nindex 000000000..60706f799\n--- /dev/null\n+++ b/app/test/test_ring_stress.c\n@@ -0,0 +1,48 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include \"test_ring_stress.h\"\n+\n+static int\n+run_test(const struct test *test)\n+{\n+\tint32_t rc;\n+\tuint32_t i, k;\n+\n+\tfor (i = 0, k = 0; i != test->nb_case; i++) {\n+\n+\t\tprintf(\"TEST-CASE %s %s START\\n\",\n+\t\t\ttest->name, test->cases[i].name);\n+\n+\t\trc = test->cases[i].func(test->cases[i].wfunc);\n+\t\tk += (rc == 0);\n+\n+\t\tif (rc != 0)\n+\t\t\tprintf(\"TEST-CASE %s %s FAILED\\n\",\n+\t\t\t\ttest->name, test->cases[i].name);\n+\t\telse\n+\t\t\tprintf(\"TEST-CASE %s %s OK\\n\",\n+\t\t\t\ttest->name, test->cases[i].name);\n+\t}\n+\n+\treturn k;\n+}\n+\n+static int\n+test_ring_stress(void)\n+{\n+\tuint32_t n, k;\n+\n+\tn = 0;\n+\tk = 0;\n+\n+\tn += test_ring_mpmc_stress.nb_case;\n+\tk += run_test(&test_ring_mpmc_stress);\n+\n+\tprintf(\"Number of tests:\\t%u\\nSuccess:\\t%u\\nFailed:\\t%u\\n\",\n+\t\tn, k, n - k);\n+\treturn (k != n);\n+}\n+\n+REGISTER_TEST_COMMAND(ring_stress_autotest, test_ring_stress);\ndiff --git a/app/test/test_ring_stress.h b/app/test/test_ring_stress.h\nnew file mode 100644\nindex 000000000..60eac6216\n--- /dev/null\n+++ b/app/test/test_ring_stress.h\n@@ -0,0 +1,35 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+\n+#include <inttypes.h>\n+#include <stddef.h>\n+#include <stdalign.h>\n+#include <string.h>\n+#include <stdio.h>\n+#include <unistd.h>\n+\n+#include <rte_ring.h>\n+#include <rte_cycles.h>\n+#include <rte_launch.h>\n+#include <rte_pause.h>\n+#include <rte_random.h>\n+#include <rte_malloc.h>\n+#include <rte_spinlock.h>\n+\n+#include \"test.h\"\n+\n+struct test_case {\n+\tconst char *name;\n+\tint (*func)(int (*)(void *));\n+\tint (*wfunc)(void *arg);\n+};\n+\n+struct test {\n+\tconst char *name;\n+\tuint32_t nb_case;\n+\tconst struct test_case *cases;\n+};\n+\n+extern const struct test test_ring_mpmc_stress;\ndiff --git a/app/test/test_ring_stress_impl.h b/app/test/test_ring_stress_impl.h\nnew file mode 100644\nindex 000000000..222d62bc4\n--- /dev/null\n+++ b/app/test/test_ring_stress_impl.h\n@@ -0,0 +1,396 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include \"test_ring_stress.h\"\n+\n+/**\n+ * Stress test for ring enqueue/dequeue operations.\n+ * Performs the following pattern on each slave worker:\n+ * dequeue/read-write data from the dequeued objects/enqueue.\n+ * Serves as both functional and performance test of ring\n+ * enqueue/dequeue operations under high contention\n+ * (for both over committed and non-over committed scenarios).\n+ */\n+\n+#define RING_NAME\t\"RING_STRESS\"\n+#define BULK_NUM\t32\n+#define RING_SIZE\t(2 * BULK_NUM * RTE_MAX_LCORE)\n+\n+enum {\n+\tWRK_CMD_STOP,\n+\tWRK_CMD_RUN,\n+};\n+\n+static volatile uint32_t wrk_cmd __rte_cache_aligned;\n+\n+/* test run-time in seconds */\n+static const uint32_t run_time = 60;\n+static const uint32_t verbose;\n+\n+struct lcore_stat {\n+\tuint64_t nb_cycle;\n+\tstruct {\n+\t\tuint64_t nb_call;\n+\t\tuint64_t nb_obj;\n+\t\tuint64_t nb_cycle;\n+\t\tuint64_t max_cycle;\n+\t\tuint64_t min_cycle;\n+\t} op;\n+};\n+\n+struct lcore_arg {\n+\tstruct rte_ring *rng;\n+\tstruct lcore_stat stats;\n+} __rte_cache_aligned;\n+\n+struct ring_elem {\n+\tuint32_t cnt[RTE_CACHE_LINE_SIZE / sizeof(uint32_t)];\n+} __rte_cache_aligned;\n+\n+/*\n+ * redefinable functions\n+ */\n+static uint32_t\n+_st_ring_dequeue_bulk(struct rte_ring *r, void **obj, uint32_t n,\n+\tuint32_t *avail);\n+\n+static uint32_t\n+_st_ring_enqueue_bulk(struct rte_ring *r, void * const *obj, uint32_t n,\n+\tuint32_t *free);\n+\n+static int\n+_st_ring_init(struct rte_ring *r, const char *name, uint32_t num);\n+\n+\n+static void\n+lcore_stat_update(struct lcore_stat *ls, uint64_t call, uint64_t obj,\n+\tuint64_t tm, int32_t prcs)\n+{\n+\tls->op.nb_call += call;\n+\tls->op.nb_obj += obj;\n+\tls->op.nb_cycle += tm;\n+\tif (prcs) {\n+\t\tls->op.max_cycle = RTE_MAX(ls->op.max_cycle, tm);\n+\t\tls->op.min_cycle = RTE_MIN(ls->op.min_cycle, tm);\n+\t}\n+}\n+\n+static void\n+lcore_op_stat_aggr(struct lcore_stat *ms, const struct lcore_stat *ls)\n+{\n+\n+\tms->op.nb_call += ls->op.nb_call;\n+\tms->op.nb_obj += ls->op.nb_obj;\n+\tms->op.nb_cycle += ls->op.nb_cycle;\n+\tms->op.max_cycle = RTE_MAX(ms->op.max_cycle, ls->op.max_cycle);\n+\tms->op.min_cycle = RTE_MIN(ms->op.min_cycle, ls->op.min_cycle);\n+}\n+\n+static void\n+lcore_stat_aggr(struct lcore_stat *ms, const struct lcore_stat *ls)\n+{\n+\tms->nb_cycle = RTE_MAX(ms->nb_cycle, ls->nb_cycle);\n+\tlcore_op_stat_aggr(ms, ls);\n+}\n+\n+static void\n+lcore_stat_dump(FILE *f, uint32_t lc, const struct lcore_stat *ls)\n+{\n+\tlong double st;\n+\n+\tst = (long double)rte_get_timer_hz() / US_PER_S;\n+\n+\tif (lc == UINT32_MAX)\n+\t\tfprintf(f, \"%s(AGGREGATE)={\\n\", __func__);\n+\telse\n+\t\tfprintf(f, \"%s(lcore=%u)={\\n\", __func__, lc);\n+\n+\tfprintf(f, \"\\tnb_cycle=%\" PRIu64 \"(%.2Lf usec),\\n\",\n+\t\tls->nb_cycle, (long double)ls->nb_cycle / st);\n+\n+\tfprintf(f, \"\\tDEQ+ENQ={\\n\");\n+\n+\tfprintf(f, \"\\t\\tnb_call=%\" PRIu64 \",\\n\", ls->op.nb_call);\n+\tfprintf(f, \"\\t\\tnb_obj=%\" PRIu64 \",\\n\", ls->op.nb_obj);\n+\tfprintf(f, \"\\t\\tnb_cycle=%\" PRIu64 \",\\n\", ls->op.nb_cycle);\n+\tfprintf(f, \"\\t\\tobj/call(avg): %.2Lf\\n\",\n+\t\t(long double)ls->op.nb_obj / ls->op.nb_call);\n+\tfprintf(f, \"\\t\\tcycles/obj(avg): %.2Lf\\n\",\n+\t\t(long double)ls->op.nb_cycle / ls->op.nb_obj);\n+\tfprintf(f, \"\\t\\tcycles/call(avg): %.2Lf\\n\",\n+\t\t(long double)ls->op.nb_cycle / ls->op.nb_call);\n+\n+\t/* if min/max cycles per call stats was collected */\n+\tif (ls->op.min_cycle != UINT64_MAX) {\n+\t\tfprintf(f, \"\\t\\tmax cycles/call=%\" PRIu64 \"(%.2Lf usec),\\n\",\n+\t\t\tls->op.max_cycle,\n+\t\t\t(long double)ls->op.max_cycle / st);\n+\t\tfprintf(f, \"\\t\\tmin cycles/call=%\" PRIu64 \"(%.2Lf usec),\\n\",\n+\t\t\tls->op.min_cycle,\n+\t\t\t(long double)ls->op.min_cycle / st);\n+\t}\n+\n+\tfprintf(f, \"\\t},\\n\");\n+\tfprintf(f, \"};\\n\");\n+}\n+\n+static void\n+fill_ring_elm(struct ring_elem *elm, uint32_t fill)\n+{\n+\tuint32_t i;\n+\n+\tfor (i = 0; i != RTE_DIM(elm->cnt); i++)\n+\t\telm->cnt[i] = fill;\n+}\n+\n+static int32_t\n+check_updt_elem(struct ring_elem *elm[], uint32_t num,\n+\tconst struct ring_elem *check, const struct ring_elem *fill)\n+{\n+\tuint32_t i;\n+\n+\tstatic rte_spinlock_t dump_lock;\n+\n+\tfor (i = 0; i != num; i++) {\n+\t\tif (memcmp(check, elm[i], sizeof(*check)) != 0) {\n+\t\t\trte_spinlock_lock(&dump_lock);\n+\t\t\tprintf(\"%s(lc=%u, num=%u) failed at %u-th iter, \"\n+\t\t\t\t\"offending object: %p\\n\",\n+\t\t\t\t__func__, rte_lcore_id(), num, i, elm[i]);\n+\t\t\trte_memdump(stdout, \"expected\", check, sizeof(*check));\n+\t\t\trte_memdump(stdout, \"result\", elm[i], sizeof(elm[i]));\n+\t\t\trte_spinlock_unlock(&dump_lock);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t\tmemcpy(elm[i], fill, sizeof(*elm[i]));\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+check_ring_op(uint32_t exp, uint32_t res, uint32_t lc,\n+\tconst char *fname, const char *opname)\n+{\n+\tif (exp != res) {\n+\t\tprintf(\"%s(lc=%u) failure: %s expected: %u, returned %u\\n\",\n+\t\t\tfname, lc, opname, exp, res);\n+\t\treturn -ENOSPC;\n+\t}\n+\treturn 0;\n+}\n+\n+static int\n+test_worker(void *arg, const char *fname, int32_t prcs)\n+{\n+\tint32_t rc;\n+\tuint32_t lc, n, num;\n+\tuint64_t cl, tm0, tm1;\n+\tstruct lcore_arg *la;\n+\tstruct ring_elem def_elm, loc_elm;\n+\tstruct ring_elem *obj[2 * BULK_NUM];\n+\n+\tla = arg;\n+\tlc = rte_lcore_id();\n+\n+\tfill_ring_elm(&def_elm, UINT32_MAX);\n+\tfill_ring_elm(&loc_elm, lc);\n+\n+\twhile (wrk_cmd != WRK_CMD_RUN) {\n+\t\trte_smp_rmb();\n+\t\trte_pause();\n+\t}\n+\n+\tcl = rte_rdtsc_precise();\n+\n+\tdo {\n+\t\t/* num in interval [7/8, 11/8] of BULK_NUM */\n+\t\tnum = 7 * BULK_NUM / 8 + rte_rand() % (BULK_NUM / 2);\n+\n+\t\t/* reset all pointer values */\n+\t\tmemset(obj, 0, sizeof(obj));\n+\n+\t\t/* dequeue num elems */\n+\t\ttm0 = (prcs != 0) ? rte_rdtsc_precise() : 0;\n+\t\tn = _st_ring_dequeue_bulk(la->rng, (void **)obj, num, NULL);\n+\t\ttm0 = (prcs != 0) ? rte_rdtsc_precise() - tm0 : 0;\n+\n+\t\t/* check return value and objects */\n+\t\trc = check_ring_op(num, n, lc, fname,\n+\t\t\tRTE_STR(_st_ring_dequeue_bulk));\n+\t\tif (rc == 0)\n+\t\t\trc = check_updt_elem(obj, num, &def_elm, &loc_elm);\n+\t\tif (rc != 0)\n+\t\t\tbreak;\n+\n+\t\t/* enqueue num elems */\n+\t\trte_compiler_barrier();\n+\t\trc = check_updt_elem(obj, num, &loc_elm, &def_elm);\n+\t\tif (rc != 0)\n+\t\t\tbreak;\n+\n+\t\ttm1 = (prcs != 0) ? rte_rdtsc_precise() : 0;\n+\t\tn = _st_ring_enqueue_bulk(la->rng, (void **)obj, num, NULL);\n+\t\ttm1 = (prcs != 0) ? rte_rdtsc_precise() - tm1 : 0;\n+\n+\t\t/* check return value */\n+\t\trc = check_ring_op(num, n, lc, fname,\n+\t\t\tRTE_STR(_st_ring_enqueue_bulk));\n+\t\tif (rc != 0)\n+\t\t\tbreak;\n+\n+\t\tlcore_stat_update(&la->stats, 1, num, tm0 + tm1, prcs);\n+\n+\t} while (wrk_cmd == WRK_CMD_RUN);\n+\n+\tcl = rte_rdtsc_precise() - cl;\n+\tif (prcs == 0)\n+\t\tlcore_stat_update(&la->stats, 0, 0, cl, 0);\n+\tla->stats.nb_cycle = cl;\n+\treturn rc;\n+}\n+static int\n+test_worker_prcs(void *arg)\n+{\n+\treturn test_worker(arg, __func__, 1);\n+}\n+\n+static int\n+test_worker_avg(void *arg)\n+{\n+\treturn test_worker(arg, __func__, 0);\n+}\n+\n+static void\n+mt1_fini(struct rte_ring *rng, void *data)\n+{\n+\trte_free(rng);\n+\trte_free(data);\n+}\n+\n+static int\n+mt1_init(struct rte_ring **rng, void **data, uint32_t num)\n+{\n+\tint32_t rc;\n+\tsize_t sz;\n+\tuint32_t i, nr;\n+\tstruct rte_ring *r;\n+\tstruct ring_elem *elm;\n+\tvoid *p;\n+\n+\t*rng = NULL;\n+\t*data = NULL;\n+\n+\tsz = num * sizeof(*elm);\n+\telm = rte_zmalloc(NULL, sz, __alignof__(*elm));\n+\tif (elm == NULL) {\n+\t\tprintf(\"%s: alloc(%zu) for %u elems data failed\",\n+\t\t\t__func__, sz, num);\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\t*data = elm;\n+\n+\t/* alloc ring */\n+\tnr = 2 * num;\n+\tsz = rte_ring_get_memsize(nr);\n+\tr = rte_zmalloc(NULL, sz, __alignof__(*r));\n+\tif (r == NULL) {\n+\t\tprintf(\"%s: alloc(%zu) for FIFO with %u elems failed\",\n+\t\t\t__func__, sz, nr);\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\t*rng = r;\n+\n+\trc = _st_ring_init(r, RING_NAME, nr);\n+\tif (rc != 0) {\n+\t\tprintf(\"%s: _st_ring_init(%p, %u) failed, error: %d(%s)\\n\",\n+\t\t\t__func__, r, nr, rc, strerror(-rc));\n+\t\treturn rc;\n+\t}\n+\n+\tfor (i = 0; i != num; i++) {\n+\t\tfill_ring_elm(elm + i, UINT32_MAX);\n+\t\tp = elm + i;\n+\t\tif (_st_ring_enqueue_bulk(r, &p, 1, NULL) != 1)\n+\t\t\tbreak;\n+\t}\n+\n+\tif (i != num) {\n+\t\tprintf(\"%s: _st_ring_enqueue(%p, %u) returned %u\\n\",\n+\t\t\t__func__, r, num, i);\n+\t\treturn -ENOSPC;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+test_mt1(int (*test)(void *))\n+{\n+\tint32_t rc;\n+\tuint32_t lc, mc;\n+\tstruct rte_ring *r;\n+\tvoid *data;\n+\tstruct lcore_arg arg[RTE_MAX_LCORE];\n+\n+\tstatic const struct lcore_stat init_stat = {\n+\t\t.op.min_cycle = UINT64_MAX,\n+\t};\n+\n+\trc = mt1_init(&r, &data, RING_SIZE);\n+\tif (rc != 0) {\n+\t\tmt1_fini(r, data);\n+\t\treturn rc;\n+\t}\n+\n+\tmemset(arg, 0, sizeof(arg));\n+\n+\t/* launch on all slaves */\n+\tRTE_LCORE_FOREACH_SLAVE(lc) {\n+\t\targ[lc].rng = r;\n+\t\targ[lc].stats = init_stat;\n+\t\trte_eal_remote_launch(test, &arg[lc], lc);\n+\t}\n+\n+\t/* signal worker to start test */\n+\twrk_cmd = WRK_CMD_RUN;\n+\trte_smp_wmb();\n+\n+\tusleep(run_time * US_PER_S);\n+\n+\t/* signal worker to start test */\n+\twrk_cmd = WRK_CMD_STOP;\n+\trte_smp_wmb();\n+\n+\t/* wait for slaves and collect stats. */\n+\tmc = rte_lcore_id();\n+\targ[mc].stats = init_stat;\n+\n+\trc = 0;\n+\tRTE_LCORE_FOREACH_SLAVE(lc) {\n+\t\trc |= rte_eal_wait_lcore(lc);\n+\t\tlcore_stat_aggr(&arg[mc].stats, &arg[lc].stats);\n+\t\tif (verbose != 0)\n+\t\t\tlcore_stat_dump(stdout, lc, &arg[lc].stats);\n+\t}\n+\n+\tlcore_stat_dump(stdout, UINT32_MAX, &arg[mc].stats);\n+\tmt1_fini(r, data);\n+\treturn rc;\n+}\n+\n+static const struct test_case tests[] = {\n+\t{\n+\t\t.name = \"MT-WRK_ENQ_DEQ-MST_NONE-PRCS\",\n+\t\t.func = test_mt1,\n+\t\t.wfunc = test_worker_prcs,\n+\t},\n+\t{\n+\t\t.name = \"MT-WRK_ENQ_DEQ-MST_NONE-AVG\",\n+\t\t.func = test_mt1,\n+\t\t.wfunc = test_worker_avg,\n+\t},\n+};\n",
    "prefixes": [
        "v7",
        "01/10"
    ]
}