get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 66002,
    "url": "http://patches.dpdk.org/api/patches/66002/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20200224113515.1744-2-konstantin.ananyev@intel.com/",
    "project": {
        "id": 1,
        "url": "http://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": "<20200224113515.1744-2-konstantin.ananyev@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200224113515.1744-2-konstantin.ananyev@intel.com",
    "date": "2020-02-24T11:35:10",
    "name": "[RFC,1/6] test/ring: add contention stress test",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "5d8e9ad0a7f1fa3d68a00d203ea003803ce7ad58",
    "submitter": {
        "id": 33,
        "url": "http://patches.dpdk.org/api/people/33/?format=api",
        "name": "Ananyev, Konstantin",
        "email": "konstantin.ananyev@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20200224113515.1744-2-konstantin.ananyev@intel.com/mbox/",
    "series": [
        {
            "id": 8659,
            "url": "http://patches.dpdk.org/api/series/8659/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=8659",
            "date": "2020-02-24T11:35:09",
            "name": "New sync modes for ring",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/8659/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/66002/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/66002/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 A4E38A0524;\n\tMon, 24 Feb 2020 12:35:33 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id D7C5B1BFAC;\n\tMon, 24 Feb 2020 12:35:25 +0100 (CET)",
            "from mga02.intel.com (mga02.intel.com [134.134.136.20])\n by dpdk.org (Postfix) with ESMTP id 5F5FA1BFA5\n for <dev@dpdk.org>; Mon, 24 Feb 2020 12:35:23 +0100 (CET)",
            "from fmsmga005.fm.intel.com ([10.253.24.32])\n by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n 24 Feb 2020 03:35:22 -0800",
            "from sivswdev08.ir.intel.com ([10.237.217.47])\n by fmsmga005.fm.intel.com with ESMTP; 24 Feb 2020 03:35:19 -0800"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.70,480,1574150400\"; d=\"scan'208\";a=\"435878528\"",
        "From": "Konstantin Ananyev <konstantin.ananyev@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "olivier.matz@6wind.com, Konstantin Ananyev <konstantin.ananyev@intel.com>",
        "Date": "Mon, 24 Feb 2020 11:35:10 +0000",
        "Message-Id": "<20200224113515.1744-2-konstantin.ananyev@intel.com>",
        "X-Mailer": "git-send-email 2.18.0",
        "In-Reply-To": "<20200224113515.1744-1-konstantin.ananyev@intel.com>",
        "References": "<20200224113515.1744-1-konstantin.ananyev@intel.com>",
        "Subject": "[dpdk-dev] [RFC 1/6] 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 new test-case to measure ring perfomance under contention\n(miltiple producers/consumers).\nStarts dequeue/enqueue loop on all available slave lcores.\n\nSigned-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>\n---\n app/test/Makefile           |   1 +\n app/test/meson.build        |   1 +\n app/test/test_ring_stress.c |  27 ++\n app/test/test_ring_stress.h | 477 ++++++++++++++++++++++++++++++++++++\n 4 files changed, 506 insertions(+)\n create mode 100644 app/test/test_ring_stress.c\n create mode 100644 app/test/test_ring_stress.h",
    "diff": "diff --git a/app/test/Makefile b/app/test/Makefile\nindex 1f080d162..4f586d95f 100644\n--- a/app/test/Makefile\n+++ b/app/test/Makefile\n@@ -78,6 +78,7 @@ SRCS-y += test_rand_perf.c\n \n SRCS-y += test_ring.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 0a2ce710f..84dde28ad 100644\n--- a/app/test/meson.build\n+++ b/app/test/meson.build\n@@ -101,6 +101,7 @@ test_sources = files('commands.c',\n \t'test_rib6.c',\n \t'test_ring.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_stress.c b/app/test/test_ring_stress.c\nnew file mode 100644\nindex 000000000..5689e06c8\n--- /dev/null\n+++ b/app/test/test_ring_stress.c\n@@ -0,0 +1,27 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include \"test_ring_stress.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+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..c6f0bc9f1\n--- /dev/null\n+++ b/app/test/test_ring_stress.h\n@@ -0,0 +1,477 @@\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+\n+#include \"test.h\"\n+\n+/*\n+ * Measures performance of ring enqueue/dequeue under high contention\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+\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(lc=%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_prcs(void *arg)\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 = rte_rdtsc_precise();\n+\t\tn = _st_ring_dequeue_bulk(la->rng, (void **)obj, num, NULL);\n+\t\ttm0 = rte_rdtsc_precise() - tm0;\n+\n+\t\t/* check return value and objects */\n+\t\trc = check_ring_op(num, n, lc, __func__,\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 = rte_rdtsc_precise();\n+\t\tn = _st_ring_enqueue_bulk(la->rng, (void **)obj, num, NULL);\n+\t\ttm1 = rte_rdtsc_precise() - tm1;\n+\n+\t\t/* check return value */\n+\t\trc = check_ring_op(num, n, lc, __func__,\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, 1);\n+\n+\t} while (wrk_cmd == WRK_CMD_RUN);\n+\n+\tla->stats.nb_cycle = rte_rdtsc_precise() - cl;\n+\treturn rc;\n+}\n+\n+static int\n+test_worker_avg(void *arg)\n+{\n+\tint32_t rc;\n+\tuint32_t lc, n, num;\n+\tuint64_t cl;\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\tn = _st_ring_dequeue_bulk(la->rng, (void **)obj, num, NULL);\n+\n+\t\t/* check return value and objects */\n+\t\trc = check_ring_op(num, n, lc, __func__,\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\tn = _st_ring_enqueue_bulk(la->rng, (void **)obj, num, NULL);\n+\n+\t\t/* check return value */\n+\t\trc = check_ring_op(num, n, lc, __func__,\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, 0, 0);\n+\n+\t} while (wrk_cmd == WRK_CMD_RUN);\n+\n+\t/* final stats update */\n+\tcl = rte_rdtsc_precise() - cl;\n+\tlcore_stat_update(&la->stats, 0, 0, cl, 0);\n+\tla->stats.nb_cycle = cl;\n+\n+\treturn rc;\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+\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: alloca(%zu) for FIFO with %u elems failed\",\n+\t\t\t__func__, sz, nr);\n+\t\treturn -ENOMEM;\n+\t}\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+\t*rng = r;\n+\t*data = elm;\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_dump(stdout, lc, &arg[lc].stats);\n+\t\tlcore_stat_aggr(&arg[mc].stats, &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 int\n+test_ring_stress(void)\n+{\n+\tint32_t rc;\n+\tuint32_t i, k;\n+\n+\tconst struct {\n+\t\tconst char *name;\n+\t\tint (*func)(int (*)(void *));\n+\t\tint (*wfunc)(void *arg);\n+\t} tests[] = {\n+\t\t{\n+\t\t\t.name = \"MT-WRK_ENQ_DEQ-MST_NONE-PRCS\",\n+\t\t\t.func = test_mt1,\n+\t\t\t.wfunc = test_worker_prcs,\n+\t\t},\n+\t\t{\n+\t\t\t.name = \"MT-WRK_ENQ_DEQ-MST_NONE-AVG\",\n+\t\t\t.func = test_mt1,\n+\t\t\t.wfunc = test_worker_avg,\n+\t\t},\n+\t};\n+\n+\tfor (i = 0, k = 0; i != RTE_DIM(tests); i++) {\n+\n+\t\tprintf(\"TEST %s START\\n\", tests[i].name);\n+\n+\t\trc = tests[i].func(tests[i].wfunc);\n+\t\tk += (rc == 0);\n+\n+\t\tif (rc != 0)\n+\t\t\tprintf(\"TEST-CASE %s FAILED\\n\", tests[i].name);\n+\t\telse\n+\t\t\tprintf(\"TEST-CASE %s OK\\n\", tests[i].name);\n+\t}\n+\n+\tprintf(\"Number of tests:\\t%u\\nSuccess:\\t%u\\nFailed:\\t%u\\n\",\n+\t\ti, k, i - k);\n+\treturn (k != i);\n+}\n",
    "prefixes": [
        "RFC",
        "1/6"
    ]
}