get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 94868,
    "url": "https://patches.dpdk.org/api/patches/94868/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/6c48562add728df4e2f22b3a41170d624c63e233.1624629506.git.anatoly.burakov@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": "<6c48562add728df4e2f22b3a41170d624c63e233.1624629506.git.anatoly.burakov@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/6c48562add728df4e2f22b3a41170d624c63e233.1624629506.git.anatoly.burakov@intel.com",
    "date": "2021-06-25T14:00:06",
    "name": "[v2,3/7] eal: add power monitor for multiple events",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "2fe9ce96315e85a62b0e7b831a26292c34b7ae3b",
    "submitter": {
        "id": 4,
        "url": "https://patches.dpdk.org/api/people/4/?format=api",
        "name": "Anatoly Burakov",
        "email": "anatoly.burakov@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/6c48562add728df4e2f22b3a41170d624c63e233.1624629506.git.anatoly.burakov@intel.com/mbox/",
    "series": [
        {
            "id": 17490,
            "url": "https://patches.dpdk.org/api/series/17490/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=17490",
            "date": "2021-06-25T14:00:03",
            "name": "Enhancements for PMD power management",
            "version": 2,
            "mbox": "https://patches.dpdk.org/series/17490/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/94868/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/94868/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 mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 4864AA0547;\n\tFri, 25 Jun 2021 16:00:59 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 20C37410E7;\n\tFri, 25 Jun 2021 16:00:51 +0200 (CEST)",
            "from mga11.intel.com (mga11.intel.com [192.55.52.93])\n by mails.dpdk.org (Postfix) with ESMTP id 798D5410E2\n for <dev@dpdk.org>; Fri, 25 Jun 2021 16:00:47 +0200 (CEST)",
            "from fmsmga003.fm.intel.com ([10.253.24.29])\n by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 25 Jun 2021 07:00:21 -0700",
            "from silpixa00399498.ir.intel.com (HELO\n silpixa00399498.ger.corp.intel.com) ([10.237.223.53])\n by FMSMGA003.fm.intel.com with ESMTP; 25 Jun 2021 07:00:18 -0700"
        ],
        "IronPort-SDR": [
            "\n 0v6uHKufOVPmoqU7XREPWBHs8J5XLwtojb7bsKj3NltIGXxYIoCuKl5ECtjv7v0TKoS3Fgxqpd\n kbY162y31K3w==",
            "\n /bfNX/jMu5gFdb6h+O4ZlS0eVaVKZs7vBetKbFRnzwsYEv5s+eaHXF+aRtb/4k+qhK7kgOUYk3\n cLCry3OwZJFg=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6200,9189,10026\"; a=\"204664512\"",
            "E=Sophos;i=\"5.83,298,1616482800\"; d=\"scan'208\";a=\"204664512\"",
            "E=Sophos;i=\"5.83,298,1616482800\"; d=\"scan'208\";a=\"481858703\""
        ],
        "X-ExtLoop1": "1",
        "From": "Anatoly Burakov <anatoly.burakov@intel.com>",
        "To": "dev@dpdk.org, Jerin Jacob <jerinj@marvell.com>,\n Ruifeng Wang <ruifeng.wang@arm.com>,\n Jan Viktorin <viktorin@rehivetech.com>,\n David Christensen <drc@linux.vnet.ibm.com>, Ray Kinsella <mdr@ashroe.eu>,\n Neil Horman <nhorman@tuxdriver.com>,\n Bruce Richardson <bruce.richardson@intel.com>,\n Konstantin Ananyev <konstantin.ananyev@intel.com>",
        "Cc": "david.hunt@intel.com,\n\tciara.loftus@intel.com",
        "Date": "Fri, 25 Jun 2021 14:00:06 +0000",
        "Message-Id": "\n <6c48562add728df4e2f22b3a41170d624c63e233.1624629506.git.anatoly.burakov@intel.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<cover.1624629506.git.anatoly.burakov@intel.com>",
        "References": "<cover.1622548381.git.anatoly.burakov@intel.com>\n <cover.1624629506.git.anatoly.burakov@intel.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH v2 3/7] eal: add power monitor for multiple events",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "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": "Use RTM and WAITPKG instructions to perform a wait-for-writes similar to\nwhat UMWAIT does, but without the limitation of having to listen for\njust one event. This works because the optimized power state used by the\nTPAUSE instruction will cause a wake up on RTM transaction abort, so if\nwe add the addresses we're interested in to the read-set, any write to\nthose addresses will wake us up.\n\nSigned-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>\nSigned-off-by: Anatoly Burakov <anatoly.burakov@intel.com>\n---\n\nNotes:\n    v2:\n    - Adapt to callback mechanism\n\n doc/guides/rel_notes/release_21_08.rst        |  2 +\n lib/eal/arm/rte_power_intrinsics.c            | 11 +++\n lib/eal/include/generic/rte_cpuflags.h        |  2 +\n .../include/generic/rte_power_intrinsics.h    | 35 ++++++++++\n lib/eal/ppc/rte_power_intrinsics.c            | 11 +++\n lib/eal/version.map                           |  3 +\n lib/eal/x86/rte_cpuflags.c                    |  2 +\n lib/eal/x86/rte_power_intrinsics.c            | 69 +++++++++++++++++++\n 8 files changed, 135 insertions(+)",
    "diff": "diff --git a/doc/guides/rel_notes/release_21_08.rst b/doc/guides/rel_notes/release_21_08.rst\nindex c84ac280f5..9d1cfac395 100644\n--- a/doc/guides/rel_notes/release_21_08.rst\n+++ b/doc/guides/rel_notes/release_21_08.rst\n@@ -55,6 +55,8 @@ New Features\n      Also, make sure to start the actual text at the margin.\n      =======================================================\n \n+* eal: added ``rte_power_monitor_multi`` to support waiting for multiple events.\n+\n \n Removed Items\n -------------\ndiff --git a/lib/eal/arm/rte_power_intrinsics.c b/lib/eal/arm/rte_power_intrinsics.c\nindex e83f04072a..78f55b7203 100644\n--- a/lib/eal/arm/rte_power_intrinsics.c\n+++ b/lib/eal/arm/rte_power_intrinsics.c\n@@ -38,3 +38,14 @@ rte_power_monitor_wakeup(const unsigned int lcore_id)\n \n \treturn -ENOTSUP;\n }\n+\n+int\n+rte_power_monitor_multi(const struct rte_power_monitor_cond pmc[],\n+\t\tconst uint32_t num, const uint64_t tsc_timestamp)\n+{\n+\tRTE_SET_USED(pmc);\n+\tRTE_SET_USED(num);\n+\tRTE_SET_USED(tsc_timestamp);\n+\n+\treturn -ENOTSUP;\n+}\ndiff --git a/lib/eal/include/generic/rte_cpuflags.h b/lib/eal/include/generic/rte_cpuflags.h\nindex 28a5aecde8..d35551e931 100644\n--- a/lib/eal/include/generic/rte_cpuflags.h\n+++ b/lib/eal/include/generic/rte_cpuflags.h\n@@ -24,6 +24,8 @@ struct rte_cpu_intrinsics {\n \t/**< indicates support for rte_power_monitor function */\n \tuint32_t power_pause : 1;\n \t/**< indicates support for rte_power_pause function */\n+\tuint32_t power_monitor_multi : 1;\n+\t/**< indicates support for rte_power_monitor_multi function */\n };\n \n /**\ndiff --git a/lib/eal/include/generic/rte_power_intrinsics.h b/lib/eal/include/generic/rte_power_intrinsics.h\nindex 046667ade6..877fb282cb 100644\n--- a/lib/eal/include/generic/rte_power_intrinsics.h\n+++ b/lib/eal/include/generic/rte_power_intrinsics.h\n@@ -124,4 +124,39 @@ int rte_power_monitor_wakeup(const unsigned int lcore_id);\n __rte_experimental\n int rte_power_pause(const uint64_t tsc_timestamp);\n \n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * Monitor a set of addresses for changes. This will cause the CPU to enter an\n+ * architecture-defined optimized power state until either one of the specified\n+ * memory addresses is written to, a certain TSC timestamp is reached, or other\n+ * reasons cause the CPU to wake up.\n+ *\n+ * Additionally, `expected` 64-bit values and 64-bit masks are provided. If\n+ * mask is non-zero, the current value pointed to by the `p` pointer will be\n+ * checked against the expected value, and if they do not match, the entering of\n+ * optimized power state may be aborted.\n+ *\n+ * @warning It is responsibility of the user to check if this function is\n+ *   supported at runtime using `rte_cpu_get_intrinsics_support()` API call.\n+ *   Failing to do so may result in an illegal CPU instruction error.\n+ *\n+ * @param pmc\n+ *   An array of monitoring condition structures.\n+ * @param num\n+ *   Length of the `pmc` array.\n+ * @param tsc_timestamp\n+ *   Maximum TSC timestamp to wait for. Note that the wait behavior is\n+ *   architecture-dependent.\n+ *\n+ * @return\n+ *   0 on success\n+ *   -EINVAL on invalid parameters\n+ *   -ENOTSUP if unsupported\n+ */\n+__rte_experimental\n+int rte_power_monitor_multi(const struct rte_power_monitor_cond pmc[],\n+\t\tconst uint32_t num, const uint64_t tsc_timestamp);\n+\n #endif /* _RTE_POWER_INTRINSIC_H_ */\ndiff --git a/lib/eal/ppc/rte_power_intrinsics.c b/lib/eal/ppc/rte_power_intrinsics.c\nindex 7fc9586da7..f00b58ade5 100644\n--- a/lib/eal/ppc/rte_power_intrinsics.c\n+++ b/lib/eal/ppc/rte_power_intrinsics.c\n@@ -38,3 +38,14 @@ rte_power_monitor_wakeup(const unsigned int lcore_id)\n \n \treturn -ENOTSUP;\n }\n+\n+int\n+rte_power_monitor_multi(const struct rte_power_monitor_cond pmc[],\n+\t\tconst uint32_t num, const uint64_t tsc_timestamp)\n+{\n+\tRTE_SET_USED(pmc);\n+\tRTE_SET_USED(num);\n+\tRTE_SET_USED(tsc_timestamp);\n+\n+\treturn -ENOTSUP;\n+}\ndiff --git a/lib/eal/version.map b/lib/eal/version.map\nindex fe5c3dac98..4ccd5475d6 100644\n--- a/lib/eal/version.map\n+++ b/lib/eal/version.map\n@@ -423,6 +423,9 @@ EXPERIMENTAL {\n \trte_version_release; # WINDOWS_NO_EXPORT\n \trte_version_suffix; # WINDOWS_NO_EXPORT\n \trte_version_year; # WINDOWS_NO_EXPORT\n+\n+\t# added in 21.08\n+\trte_power_monitor_multi; # WINDOWS_NO_EXPORT\n };\n \n INTERNAL {\ndiff --git a/lib/eal/x86/rte_cpuflags.c b/lib/eal/x86/rte_cpuflags.c\nindex a96312ff7f..d339734a8c 100644\n--- a/lib/eal/x86/rte_cpuflags.c\n+++ b/lib/eal/x86/rte_cpuflags.c\n@@ -189,5 +189,7 @@ rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics *intrinsics)\n \tif (rte_cpu_get_flag_enabled(RTE_CPUFLAG_WAITPKG)) {\n \t\tintrinsics->power_monitor = 1;\n \t\tintrinsics->power_pause = 1;\n+\t\tif (rte_cpu_get_flag_enabled(RTE_CPUFLAG_RTM))\n+\t\t\tintrinsics->power_monitor_multi = 1;\n \t}\n }\ndiff --git a/lib/eal/x86/rte_power_intrinsics.c b/lib/eal/x86/rte_power_intrinsics.c\nindex 3c5c9ce7ad..3fc6f62ef5 100644\n--- a/lib/eal/x86/rte_power_intrinsics.c\n+++ b/lib/eal/x86/rte_power_intrinsics.c\n@@ -4,6 +4,7 @@\n \n #include <rte_common.h>\n #include <rte_lcore.h>\n+#include <rte_rtm.h>\n #include <rte_spinlock.h>\n \n #include \"rte_power_intrinsics.h\"\n@@ -28,6 +29,7 @@ __umwait_wakeup(volatile void *addr)\n }\n \n static bool wait_supported;\n+static bool wait_multi_supported;\n \n static inline uint64_t\n __get_umwait_val(const volatile void *p, const uint8_t sz)\n@@ -164,6 +166,8 @@ RTE_INIT(rte_power_intrinsics_init) {\n \n \tif (i.power_monitor && i.power_pause)\n \t\twait_supported = 1;\n+\tif (i.power_monitor_multi)\n+\t\twait_multi_supported = 1;\n }\n \n int\n@@ -202,6 +206,9 @@ rte_power_monitor_wakeup(const unsigned int lcore_id)\n \t * In this case, since we've already woken up, the \"wakeup\" was\n \t * unneeded, and since T1 is still waiting on T2 releasing the lock, the\n \t * wakeup address is still valid so it's perfectly safe to write it.\n+\t *\n+\t * For multi-monitor case, the act of locking will in itself trigger the\n+\t * wakeup, so no additional writes necessary.\n \t */\n \trte_spinlock_lock(&s->lock);\n \tif (s->monitor_addr != NULL)\n@@ -210,3 +217,65 @@ rte_power_monitor_wakeup(const unsigned int lcore_id)\n \n \treturn 0;\n }\n+\n+int\n+rte_power_monitor_multi(const struct rte_power_monitor_cond pmc[],\n+\t\tconst uint32_t num, const uint64_t tsc_timestamp)\n+{\n+\tconst unsigned int lcore_id = rte_lcore_id();\n+\tstruct power_wait_status *s = &wait_status[lcore_id];\n+\tuint32_t i, rc;\n+\n+\t/* check if supported */\n+\tif (!wait_multi_supported)\n+\t\treturn -ENOTSUP;\n+\n+\tif (pmc == NULL || num == 0)\n+\t\treturn -EINVAL;\n+\n+\t/* we are already inside transaction region, return */\n+\tif (rte_xtest() != 0)\n+\t\treturn 0;\n+\n+\t/* start new transaction region */\n+\trc = rte_xbegin();\n+\n+\t/* transaction abort, possible write to one of wait addresses */\n+\tif (rc != RTE_XBEGIN_STARTED)\n+\t\treturn 0;\n+\n+\t/*\n+\t * the mere act of reading the lock status here adds the lock to\n+\t * the read set. This means that when we trigger a wakeup from another\n+\t * thread, even if we don't have a defined wakeup address and thus don't\n+\t * actually cause any writes, the act of locking our lock will itself\n+\t * trigger the wakeup and abort the transaction.\n+\t */\n+\trte_spinlock_is_locked(&s->lock);\n+\n+\t/*\n+\t * add all addresses to wait on into transaction read-set and check if\n+\t * any of wakeup conditions are already met.\n+\t */\n+\tfor (i = 0; i < num; i++) {\n+\t\tconst struct rte_power_monitor_cond *c = &pmc[i];\n+\n+\t\tif (pmc->fn == NULL)\n+\t\t\tcontinue;\n+\n+\t\tconst uint64_t val = __get_umwait_val(pmc->addr, pmc->size);\n+\n+\t\t/* abort if callback indicates that we need to stop */\n+\t\tif (c->fn(val, c->opaque) != 0)\n+\t\t\tbreak;\n+\t}\n+\n+\t/* none of the conditions were met, sleep until timeout */\n+\tif (i == num)\n+\t\trte_power_pause(tsc_timestamp);\n+\n+\t/* end transaction region */\n+\trte_xend();\n+\n+\treturn 0;\n+}\n",
    "prefixes": [
        "v2",
        "3/7"
    ]
}