Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/95307/?format=api
https://patches.dpdk.org/api/patches/95307/?format=api", "web_url": "https://patches.dpdk.org/project/dpdk/patch/e29c98469a4e11e00fcd10968817bb0b9f3c4853.1625498488.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": "<e29c98469a4e11e00fcd10968817bb0b9f3c4853.1625498488.git.anatoly.burakov@intel.com>", "list_archive_url": "https://inbox.dpdk.org/dev/e29c98469a4e11e00fcd10968817bb0b9f3c4853.1625498488.git.anatoly.burakov@intel.com", "date": "2021-07-05T15:21:58", "name": "[v6,3/7] eal: add power monitor for multiple events", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": true, "hash": "092820e7438d9623f3a24632f7fa0785330fe646", "submitter": { "id": 4, "url": "https://patches.dpdk.org/api/people/4/?format=api", "name": "Burakov, Anatoly", "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/e29c98469a4e11e00fcd10968817bb0b9f3c4853.1625498488.git.anatoly.burakov@intel.com/mbox/", "series": [ { "id": 17638, "url": "https://patches.dpdk.org/api/series/17638/?format=api", "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=17638", "date": "2021-07-05T15:21:55", "name": "Enhancements for PMD power management", "version": 6, "mbox": "https://patches.dpdk.org/series/17638/mbox/" } ], "comments": "https://patches.dpdk.org/api/patches/95307/comments/", "check": "warning", "checks": "https://patches.dpdk.org/api/patches/95307/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 7771CA0A0F;\n\tMon, 5 Jul 2021 17:22:26 +0200 (CEST)", "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 0ECD8411EE;\n\tMon, 5 Jul 2021 17:22:17 +0200 (CEST)", "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n by mails.dpdk.org (Postfix) with ESMTP id 93D15411EB\n for <dev@dpdk.org>; Mon, 5 Jul 2021 17:22:14 +0200 (CEST)", "from orsmga001.jf.intel.com ([10.7.209.18])\n by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 05 Jul 2021 08:22:14 -0700", "from silpixa00399498.ir.intel.com (HELO\n silpixa00399498.ger.corp.intel.com) ([10.237.223.53])\n by orsmga001.jf.intel.com with ESMTP; 05 Jul 2021 08:22:11 -0700" ], "X-IronPort-AV": [ "E=McAfee;i=\"6200,9189,10036\"; a=\"208811985\"", "E=Sophos;i=\"5.83,325,1616482800\"; d=\"scan'208\";a=\"208811985\"", "E=Sophos;i=\"5.83,325,1616482800\"; d=\"scan'208\";a=\"491028347\"" ], "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": "Mon, 5 Jul 2021 15:21:58 +0000", "Message-Id": "\n <e29c98469a4e11e00fcd10968817bb0b9f3c4853.1625498488.git.anatoly.burakov@intel.com>", "X-Mailer": "git-send-email 2.25.1", "In-Reply-To": "<cover.1625498488.git.anatoly.burakov@intel.com>", "References": "<cover.1624981669.git.anatoly.burakov@intel.com>\n <cover.1625498488.git.anatoly.burakov@intel.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Subject": "[dpdk-dev] [PATCH v6 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 v4:\n - Fixed bugs in accessing the monitor condition\n - Abort on any monitor condition not having a defined callback\n \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 | 73 +++++++++++++++++++\n 8 files changed, 139 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 c9aa52a86d..04e8c2ab37 100644\n--- a/lib/eal/include/generic/rte_power_intrinsics.h\n+++ b/lib/eal/include/generic/rte_power_intrinsics.h\n@@ -128,4 +128,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 66fea28897..f749da9b85 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@@ -166,6 +168,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@@ -204,6 +208,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@@ -212,3 +219,69 @@ 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+\trc = 0;\n+\tfor (i = 0; i < num; i++) {\n+\t\tconst struct rte_power_monitor_cond *c = &pmc[i];\n+\n+\t\t/* cannot be NULL */\n+\t\tif (c->fn == NULL) {\n+\t\t\trc = -EINVAL;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tconst uint64_t val = __get_umwait_val(c->addr, c->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 rc;\n+}\n", "prefixes": [ "v6", "3/7" ] }{ "id": 95307, "url": "