Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/93722/?format=api
http://patchwork.dpdk.org/api/patches/93722/?format=api", "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/712a208c3e90dda2c765d3384f5be944df1258b0.1622548381.git.anatoly.burakov@intel.com/", "project": { "id": 1, "url": "http://patchwork.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": "<712a208c3e90dda2c765d3384f5be944df1258b0.1622548381.git.anatoly.burakov@intel.com>", "list_archive_url": "https://inbox.dpdk.org/dev/712a208c3e90dda2c765d3384f5be944df1258b0.1622548381.git.anatoly.burakov@intel.com", "date": "2021-06-01T12:00:32", "name": "[v1,3/7] eal: add power monitor for multiple events", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": true, "hash": "598c177eab876fb8bdb8576327b4ccf5d64dfe39", "submitter": { "id": 4, "url": "http://patchwork.dpdk.org/api/people/4/?format=api", "name": "Burakov, Anatoly", "email": "anatoly.burakov@intel.com" }, "delegate": { "id": 1, "url": "http://patchwork.dpdk.org/api/users/1/?format=api", "username": "tmonjalo", "first_name": "Thomas", "last_name": "Monjalon", "email": "thomas@monjalon.net" }, "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/712a208c3e90dda2c765d3384f5be944df1258b0.1622548381.git.anatoly.burakov@intel.com/mbox/", "series": [ { "id": 17191, "url": "http://patchwork.dpdk.org/api/series/17191/?format=api", "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=17191", "date": "2021-06-01T12:00:29", "name": "Enhancements for PMD power management", "version": 1, "mbox": "http://patchwork.dpdk.org/series/17191/mbox/" } ], "comments": "http://patchwork.dpdk.org/api/patches/93722/comments/", "check": "success", "checks": "http://patchwork.dpdk.org/api/patches/93722/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 14DD3A0524;\n\tTue, 1 Jun 2021 14:01:03 +0200 (CEST)", "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 0DC03410EF;\n\tTue, 1 Jun 2021 14:00:48 +0200 (CEST)", "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n by mails.dpdk.org (Postfix) with ESMTP id 33C73410E8\n for <dev@dpdk.org>; Tue, 1 Jun 2021 14:00:46 +0200 (CEST)", "from fmsmga001.fm.intel.com ([10.253.24.23])\n by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 01 Jun 2021 05:00:45 -0700", "from silpixa00399498.ir.intel.com (HELO\n silpixa00399498.ger.corp.intel.com) ([10.237.222.54])\n by fmsmga001.fm.intel.com with ESMTP; 01 Jun 2021 05:00:42 -0700" ], "IronPort-SDR": [ "\n 97aw+JIu0nY3VAzxORNDcRZU6AUZpCByXvKKOe+Bju9NWRQPcWNNFp/FoOQrgOtO1DrC3zoiNa\n BcaayfBHOIOQ==", "\n wlols0yPotOxme461yEfwfXmsNq4H1h1Xjh4o7KOBXByPpGXPJTZcEhyKPQY3N+gcLrdWjdvvu\n HifsFcerM6kA==" ], "X-IronPort-AV": [ "E=McAfee;i=\"6200,9189,10001\"; a=\"203528476\"", "E=Sophos;i=\"5.83,239,1616482800\"; d=\"scan'208\";a=\"203528476\"", "E=Sophos;i=\"5.83,239,1616482800\"; d=\"scan'208\";a=\"549706995\"" ], "X-ExtLoop1": "1", "From": "Anatoly Burakov <anatoly.burakov@intel.com>", "To": "dev@dpdk.org, Jan Viktorin <viktorin@rehivetech.com>,\n Ruifeng Wang <ruifeng.wang@arm.com>, Jerin Jacob <jerinj@marvell.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": "ciara.loftus@intel.com,\n\tdavid.hunt@intel.com", "Date": "Tue, 1 Jun 2021 12:00:32 +0000", "Message-Id": "\n <712a208c3e90dda2c765d3384f5be944df1258b0.1622548381.git.anatoly.burakov@intel.com>", "X-Mailer": "git-send-email 2.25.1", "In-Reply-To": "<cover.1622548381.git.anatoly.burakov@intel.com>", "References": "<cover.1622548381.git.anatoly.burakov@intel.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Subject": "[dpdk-dev] [PATCH v1 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 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 7 files changed, 133 insertions(+)", "diff": "diff --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 1006c2edfc..acb0d759ce 100644\n--- a/lib/eal/include/generic/rte_power_intrinsics.h\n+++ b/lib/eal/include/generic/rte_power_intrinsics.h\n@@ -113,4 +113,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 5d944e9aa4..4f972673ce 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@@ -170,6 +172,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@@ -208,6 +212,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@@ -216,3 +223,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+\t\tconst uint64_t val = __get_umwait_val(pmc->addr, pmc->size);\n+\t\tconst uint64_t masked = val & c->mask;\n+\n+\t\t/* if the masked value is already matching, abort */\n+\t\tif (!c->invert && masked == c->val)\n+\t\t\tbreak;\n+\t\t/* same, but for inverse check */\n+\t\tif (c->invert && masked != c->val)\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": [ "v1", "3/7" ] }{ "id": 93722, "url": "