get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 95619,
    "url": "http://patchwork.dpdk.org/api/patches/95619/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/dd19b6b96dfb320ca44927db8725e10fb549b3df.1625846394.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": "<dd19b6b96dfb320ca44927db8725e10fb549b3df.1625846394.git.anatoly.burakov@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/dd19b6b96dfb320ca44927db8725e10fb549b3df.1625846394.git.anatoly.burakov@intel.com",
    "date": "2021-07-09T16:08:10",
    "name": "[v10,1/8] eal: use callbacks for power monitoring comparison",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "ab8a9316c0ccb91a3ef8e6836c92aa7890a6b1c1",
    "submitter": {
        "id": 4,
        "url": "http://patchwork.dpdk.org/api/people/4/?format=api",
        "name": "Anatoly Burakov",
        "email": "anatoly.burakov@intel.com"
    },
    "delegate": {
        "id": 24651,
        "url": "http://patchwork.dpdk.org/api/users/24651/?format=api",
        "username": "dmarchand",
        "first_name": "David",
        "last_name": "Marchand",
        "email": "david.marchand@redhat.com"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/dd19b6b96dfb320ca44927db8725e10fb549b3df.1625846394.git.anatoly.burakov@intel.com/mbox/",
    "series": [
        {
            "id": 17744,
            "url": "http://patchwork.dpdk.org/api/series/17744/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=17744",
            "date": "2021-07-09T16:08:09",
            "name": "Enhancements for PMD power management",
            "version": 10,
            "mbox": "http://patchwork.dpdk.org/series/17744/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/95619/comments/",
    "check": "warning",
    "checks": "http://patchwork.dpdk.org/api/patches/95619/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 23A13A0548;\n\tFri,  9 Jul 2021 18:08:28 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 6BB3A416FB;\n\tFri,  9 Jul 2021 18:08:25 +0200 (CEST)",
            "from mga03.intel.com (mga03.intel.com [134.134.136.65])\n by mails.dpdk.org (Postfix) with ESMTP id A9352410FC\n for <dev@dpdk.org>; Fri,  9 Jul 2021 18:08:23 +0200 (CEST)",
            "from orsmga008.jf.intel.com ([10.7.209.65])\n by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 09 Jul 2021 09:08:23 -0700",
            "from silpixa00399498.ir.intel.com (HELO\n silpixa00399498.ger.corp.intel.com) ([10.237.223.53])\n by orsmga008.jf.intel.com with ESMTP; 09 Jul 2021 09:08:20 -0700"
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6200,9189,10039\"; a=\"209767593\"",
            "E=Sophos;i=\"5.84,226,1620716400\"; d=\"scan'208\";a=\"209767593\"",
            "E=Sophos;i=\"5.84,226,1620716400\"; d=\"scan'208\";a=\"458319531\""
        ],
        "X-ExtLoop1": "1",
        "From": "Anatoly Burakov <anatoly.burakov@intel.com>",
        "To": "dev@dpdk.org, Timothy McDaniel <timothy.mcdaniel@intel.com>,\n Beilei Xing <beilei.xing@intel.com>, Jingjing Wu <jingjing.wu@intel.com>,\n Qiming Yang <qiming.yang@intel.com>, Qi Zhang <qi.z.zhang@intel.com>,\n Haiyue Wang <haiyue.wang@intel.com>, Matan Azrad <matan@nvidia.com>,\n Shahaf Shuler <shahafs@nvidia.com>,\n Viacheslav Ovsiienko <viacheslavo@nvidia.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,  9 Jul 2021 16:08:10 +0000",
        "Message-Id": "\n <dd19b6b96dfb320ca44927db8725e10fb549b3df.1625846394.git.anatoly.burakov@intel.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<cover.1625846394.git.anatoly.burakov@intel.com>",
        "References": "<cover.1625845967.git.anatoly.burakov@intel.com>\n <cover.1625846394.git.anatoly.burakov@intel.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH v10 1/8] eal: use callbacks for power monitoring\n comparison",
        "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": "Previously, the semantics of power monitor were such that we were\nchecking current value against the expected value, and if they matched,\nthen the sleep was aborted. This is somewhat inflexible, because it only\nallowed us to check for a specific value in a specific way.\n\nThis commit replaces the comparison with a user callback mechanism, so\nthat any PMD (or other code) using `rte_power_monitor()` can define\ntheir own comparison semantics and decision making on how to detect the\nneed to abort the entering of power optimized state.\n\nExisting implementations are adjusted to follow the new semantics.\n\nSuggested-by: Konstantin Ananyev <konstantin.ananyev@intel.com>\nSigned-off-by: Anatoly Burakov <anatoly.burakov@intel.com>\nAcked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>\nTested-by: David Hunt <david.hunt@intel.com>\nAcked-by: Timothy McDaniel <timothy.mcdaniel@intel.com>\n---\n\nNotes:\n    v4:\n    - Return error if callback is set to NULL\n    - Replace raw number with a macro in monitor condition opaque data\n    \n    v2:\n    - Use callback mechanism for more flexibility\n    - Address feedback from Konstantin\n\n doc/guides/rel_notes/release_21_08.rst        |  2 ++\n drivers/event/dlb2/dlb2.c                     | 17 ++++++++--\n drivers/net/i40e/i40e_rxtx.c                  | 20 +++++++----\n drivers/net/iavf/iavf_rxtx.c                  | 20 +++++++----\n drivers/net/ice/ice_rxtx.c                    | 20 +++++++----\n drivers/net/ixgbe/ixgbe_rxtx.c                | 20 +++++++----\n drivers/net/mlx5/mlx5_rx.c                    | 17 ++++++++--\n .../include/generic/rte_power_intrinsics.h    | 33 +++++++++++++++----\n lib/eal/x86/rte_power_intrinsics.c            | 17 +++++-----\n 9 files changed, 122 insertions(+), 44 deletions(-)",
    "diff": "diff --git a/doc/guides/rel_notes/release_21_08.rst b/doc/guides/rel_notes/release_21_08.rst\nindex 476822b47f..912fb13b84 100644\n--- a/doc/guides/rel_notes/release_21_08.rst\n+++ b/doc/guides/rel_notes/release_21_08.rst\n@@ -144,6 +144,8 @@ API Changes\n * eal: ``rte_strscpy`` sets ``rte_errno`` to ``E2BIG`` in case of string\n   truncation.\n \n+* eal: the ``rte_power_intrinsics`` API changed to use a callback mechanism.\n+\n \n ABI Changes\n -----------\ndiff --git a/drivers/event/dlb2/dlb2.c b/drivers/event/dlb2/dlb2.c\nindex eca183753f..252bbd8d5e 100644\n--- a/drivers/event/dlb2/dlb2.c\n+++ b/drivers/event/dlb2/dlb2.c\n@@ -3154,6 +3154,16 @@ dlb2_port_credits_inc(struct dlb2_port *qm_port, int num)\n \t}\n }\n \n+#define CLB_MASK_IDX 0\n+#define CLB_VAL_IDX 1\n+static int\n+dlb2_monitor_callback(const uint64_t val,\n+\t\tconst uint64_t opaque[RTE_POWER_MONITOR_OPAQUE_SZ])\n+{\n+\t/* abort if the value matches */\n+\treturn (val & opaque[CLB_MASK_IDX]) == opaque[CLB_VAL_IDX] ? -1 : 0;\n+}\n+\n static inline int\n dlb2_dequeue_wait(struct dlb2_eventdev *dlb2,\n \t\t  struct dlb2_eventdev_port *ev_port,\n@@ -3194,8 +3204,11 @@ dlb2_dequeue_wait(struct dlb2_eventdev *dlb2,\n \t\t\texpected_value = 0;\n \n \t\tpmc.addr = monitor_addr;\n-\t\tpmc.val = expected_value;\n-\t\tpmc.mask = qe_mask.raw_qe[1];\n+\t\t/* store expected value and comparison mask in opaque data */\n+\t\tpmc.opaque[CLB_VAL_IDX] = expected_value;\n+\t\tpmc.opaque[CLB_MASK_IDX] = qe_mask.raw_qe[1];\n+\t\t/* set up callback */\n+\t\tpmc.fn = dlb2_monitor_callback;\n \t\tpmc.size = sizeof(uint64_t);\n \n \t\trte_power_monitor(&pmc, timeout + start_ticks);\ndiff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c\nindex e518409fe5..8489f91f1d 100644\n--- a/drivers/net/i40e/i40e_rxtx.c\n+++ b/drivers/net/i40e/i40e_rxtx.c\n@@ -81,6 +81,18 @@\n #define I40E_TX_OFFLOAD_SIMPLE_NOTSUP_MASK \\\n \t\t(PKT_TX_OFFLOAD_MASK ^ I40E_TX_OFFLOAD_SIMPLE_SUP_MASK)\n \n+static int\n+i40e_monitor_callback(const uint64_t value,\n+\t\tconst uint64_t arg[RTE_POWER_MONITOR_OPAQUE_SZ] __rte_unused)\n+{\n+\tconst uint64_t m = rte_cpu_to_le_64(1 << I40E_RX_DESC_STATUS_DD_SHIFT);\n+\t/*\n+\t * we expect the DD bit to be set to 1 if this descriptor was already\n+\t * written to.\n+\t */\n+\treturn (value & m) == m ? -1 : 0;\n+}\n+\n int\n i40e_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)\n {\n@@ -93,12 +105,8 @@ i40e_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)\n \t/* watch for changes in status bit */\n \tpmc->addr = &rxdp->wb.qword1.status_error_len;\n \n-\t/*\n-\t * we expect the DD bit to be set to 1 if this descriptor was already\n-\t * written to.\n-\t */\n-\tpmc->val = rte_cpu_to_le_64(1 << I40E_RX_DESC_STATUS_DD_SHIFT);\n-\tpmc->mask = rte_cpu_to_le_64(1 << I40E_RX_DESC_STATUS_DD_SHIFT);\n+\t/* comparison callback */\n+\tpmc->fn = i40e_monitor_callback;\n \n \t/* registers are 64-bit */\n \tpmc->size = sizeof(uint64_t);\ndiff --git a/drivers/net/iavf/iavf_rxtx.c b/drivers/net/iavf/iavf_rxtx.c\nindex f817fbc49b..d61b32fcee 100644\n--- a/drivers/net/iavf/iavf_rxtx.c\n+++ b/drivers/net/iavf/iavf_rxtx.c\n@@ -57,6 +57,18 @@ iavf_proto_xtr_type_to_rxdid(uint8_t flex_type)\n \t\t\t\trxdid_map[flex_type] : IAVF_RXDID_COMMS_OVS_1;\n }\n \n+static int\n+iavf_monitor_callback(const uint64_t value,\n+\t\tconst uint64_t arg[RTE_POWER_MONITOR_OPAQUE_SZ] __rte_unused)\n+{\n+\tconst uint64_t m = rte_cpu_to_le_64(1 << IAVF_RX_DESC_STATUS_DD_SHIFT);\n+\t/*\n+\t * we expect the DD bit to be set to 1 if this descriptor was already\n+\t * written to.\n+\t */\n+\treturn (value & m) == m ? -1 : 0;\n+}\n+\n int\n iavf_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)\n {\n@@ -69,12 +81,8 @@ iavf_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)\n \t/* watch for changes in status bit */\n \tpmc->addr = &rxdp->wb.qword1.status_error_len;\n \n-\t/*\n-\t * we expect the DD bit to be set to 1 if this descriptor was already\n-\t * written to.\n-\t */\n-\tpmc->val = rte_cpu_to_le_64(1 << IAVF_RX_DESC_STATUS_DD_SHIFT);\n-\tpmc->mask = rte_cpu_to_le_64(1 << IAVF_RX_DESC_STATUS_DD_SHIFT);\n+\t/* comparison callback */\n+\tpmc->fn = iavf_monitor_callback;\n \n \t/* registers are 64-bit */\n \tpmc->size = sizeof(uint64_t);\ndiff --git a/drivers/net/ice/ice_rxtx.c b/drivers/net/ice/ice_rxtx.c\nindex 3f6e735984..5d7ab4f047 100644\n--- a/drivers/net/ice/ice_rxtx.c\n+++ b/drivers/net/ice/ice_rxtx.c\n@@ -27,6 +27,18 @@ uint64_t rte_net_ice_dynflag_proto_xtr_ipv6_flow_mask;\n uint64_t rte_net_ice_dynflag_proto_xtr_tcp_mask;\n uint64_t rte_net_ice_dynflag_proto_xtr_ip_offset_mask;\n \n+static int\n+ice_monitor_callback(const uint64_t value,\n+\t\tconst uint64_t arg[RTE_POWER_MONITOR_OPAQUE_SZ] __rte_unused)\n+{\n+\tconst uint64_t m = rte_cpu_to_le_16(1 << ICE_RX_FLEX_DESC_STATUS0_DD_S);\n+\t/*\n+\t * we expect the DD bit to be set to 1 if this descriptor was already\n+\t * written to.\n+\t */\n+\treturn (value & m) == m ? -1 : 0;\n+}\n+\n int\n ice_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)\n {\n@@ -39,12 +51,8 @@ ice_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)\n \t/* watch for changes in status bit */\n \tpmc->addr = &rxdp->wb.status_error0;\n \n-\t/*\n-\t * we expect the DD bit to be set to 1 if this descriptor was already\n-\t * written to.\n-\t */\n-\tpmc->val = rte_cpu_to_le_16(1 << ICE_RX_FLEX_DESC_STATUS0_DD_S);\n-\tpmc->mask = rte_cpu_to_le_16(1 << ICE_RX_FLEX_DESC_STATUS0_DD_S);\n+\t/* comparison callback */\n+\tpmc->fn = ice_monitor_callback;\n \n \t/* register is 16-bit */\n \tpmc->size = sizeof(uint16_t);\ndiff --git a/drivers/net/ixgbe/ixgbe_rxtx.c b/drivers/net/ixgbe/ixgbe_rxtx.c\nindex d69f36e977..c814a28cb4 100644\n--- a/drivers/net/ixgbe/ixgbe_rxtx.c\n+++ b/drivers/net/ixgbe/ixgbe_rxtx.c\n@@ -1369,6 +1369,18 @@ const uint32_t\n \t\tRTE_PTYPE_INNER_L3_IPV4_EXT | RTE_PTYPE_INNER_L4_UDP,\n };\n \n+static int\n+ixgbe_monitor_callback(const uint64_t value,\n+\t\tconst uint64_t arg[RTE_POWER_MONITOR_OPAQUE_SZ] __rte_unused)\n+{\n+\tconst uint64_t m = rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD);\n+\t/*\n+\t * we expect the DD bit to be set to 1 if this descriptor was already\n+\t * written to.\n+\t */\n+\treturn (value & m) == m ? -1 : 0;\n+}\n+\n int\n ixgbe_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)\n {\n@@ -1381,12 +1393,8 @@ ixgbe_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)\n \t/* watch for changes in status bit */\n \tpmc->addr = &rxdp->wb.upper.status_error;\n \n-\t/*\n-\t * we expect the DD bit to be set to 1 if this descriptor was already\n-\t * written to.\n-\t */\n-\tpmc->val = rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD);\n-\tpmc->mask = rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD);\n+\t/* comparison callback */\n+\tpmc->fn = ixgbe_monitor_callback;\n \n \t/* the registers are 32-bit */\n \tpmc->size = sizeof(uint32_t);\ndiff --git a/drivers/net/mlx5/mlx5_rx.c b/drivers/net/mlx5/mlx5_rx.c\nindex 777a1d6e45..8d47637892 100644\n--- a/drivers/net/mlx5/mlx5_rx.c\n+++ b/drivers/net/mlx5/mlx5_rx.c\n@@ -269,6 +269,18 @@ mlx5_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id)\n \treturn rx_queue_count(rxq);\n }\n \n+#define CLB_VAL_IDX 0\n+#define CLB_MSK_IDX 1\n+static int\n+mlx5_monitor_callback(const uint64_t value,\n+\t\tconst uint64_t opaque[RTE_POWER_MONITOR_OPAQUE_SZ])\n+{\n+\tconst uint64_t m = opaque[CLB_MSK_IDX];\n+\tconst uint64_t v = opaque[CLB_VAL_IDX];\n+\n+\treturn (value & m) == v ? -1 : 0;\n+}\n+\n int mlx5_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)\n {\n \tstruct mlx5_rxq_data *rxq = rx_queue;\n@@ -282,8 +294,9 @@ int mlx5_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)\n \t\treturn -rte_errno;\n \t}\n \tpmc->addr = &cqe->op_own;\n-\tpmc->val =  !!idx;\n-\tpmc->mask = MLX5_CQE_OWNER_MASK;\n+\tpmc->opaque[CLB_VAL_IDX] = !!idx;\n+\tpmc->opaque[CLB_MSK_IDX] = MLX5_CQE_OWNER_MASK;\n+\tpmc->fn = mlx5_monitor_callback;\n \tpmc->size = sizeof(uint8_t);\n \treturn 0;\n }\ndiff --git a/lib/eal/include/generic/rte_power_intrinsics.h b/lib/eal/include/generic/rte_power_intrinsics.h\nindex dddca3d41c..c9aa52a86d 100644\n--- a/lib/eal/include/generic/rte_power_intrinsics.h\n+++ b/lib/eal/include/generic/rte_power_intrinsics.h\n@@ -18,19 +18,38 @@\n  * which are architecture-dependent.\n  */\n \n+/** Size of the opaque data in monitor condition */\n+#define RTE_POWER_MONITOR_OPAQUE_SZ 4\n+\n+/**\n+ * Callback definition for monitoring conditions. Callbacks with this signature\n+ * will be used by `rte_power_monitor()` to check if the entering of power\n+ * optimized state should be aborted.\n+ *\n+ * @param val\n+ *   The value read from memory.\n+ * @param opaque\n+ *   Callback-specific data.\n+ *\n+ * @return\n+ *   0 if entering of power optimized state should proceed\n+ *   -1 if entering of power optimized state should be aborted\n+ */\n+typedef int (*rte_power_monitor_clb_t)(const uint64_t val,\n+\t\tconst uint64_t opaque[RTE_POWER_MONITOR_OPAQUE_SZ]);\n struct rte_power_monitor_cond {\n \tvolatile void *addr;  /**< Address to monitor for changes */\n-\tuint64_t val;         /**< If the `mask` is non-zero, location pointed\n-\t                       *   to by `addr` will be read and compared\n-\t                       *   against this value.\n-\t                       */\n-\tuint64_t mask;   /**< 64-bit mask to extract value read from `addr` */\n-\tuint8_t size;    /**< Data size (in bytes) that will be used to compare\n-\t                  *   expected value (`val`) with data read from the\n+\tuint8_t size;    /**< Data size (in bytes) that will be read from the\n \t                  *   monitored memory location (`addr`). Can be 1, 2,\n \t                  *   4, or 8. Supplying any other value will result in\n \t                  *   an error.\n \t                  */\n+\trte_power_monitor_clb_t fn; /**< Callback to be used to check if\n+\t                             *   entering power optimized state should\n+\t                             *   be aborted.\n+\t                             */\n+\tuint64_t opaque[RTE_POWER_MONITOR_OPAQUE_SZ];\n+\t/**< Callback-specific data */\n };\n \n /**\ndiff --git a/lib/eal/x86/rte_power_intrinsics.c b/lib/eal/x86/rte_power_intrinsics.c\nindex 39ea9fdecd..66fea28897 100644\n--- a/lib/eal/x86/rte_power_intrinsics.c\n+++ b/lib/eal/x86/rte_power_intrinsics.c\n@@ -76,6 +76,7 @@ rte_power_monitor(const struct rte_power_monitor_cond *pmc,\n \tconst uint32_t tsc_h = (uint32_t)(tsc_timestamp >> 32);\n \tconst unsigned int lcore_id = rte_lcore_id();\n \tstruct power_wait_status *s;\n+\tuint64_t cur_value;\n \n \t/* prevent user from running this instruction if it's not supported */\n \tif (!wait_supported)\n@@ -91,6 +92,9 @@ rte_power_monitor(const struct rte_power_monitor_cond *pmc,\n \tif (__check_val_size(pmc->size) < 0)\n \t\treturn -EINVAL;\n \n+\tif (pmc->fn == NULL)\n+\t\treturn -EINVAL;\n+\n \ts = &wait_status[lcore_id];\n \n \t/* update sleep address */\n@@ -110,16 +114,11 @@ rte_power_monitor(const struct rte_power_monitor_cond *pmc,\n \t/* now that we've put this address into monitor, we can unlock */\n \trte_spinlock_unlock(&s->lock);\n \n-\t/* if we have a comparison mask, we might not need to sleep at all */\n-\tif (pmc->mask) {\n-\t\tconst uint64_t cur_value = __get_umwait_val(\n-\t\t\t\tpmc->addr, pmc->size);\n-\t\tconst uint64_t masked = cur_value & pmc->mask;\n+\tcur_value = __get_umwait_val(pmc->addr, pmc->size);\n \n-\t\t/* if the masked value is already matching, abort */\n-\t\tif (masked == pmc->val)\n-\t\t\tgoto end;\n-\t}\n+\t/* check if callback indicates we should abort */\n+\tif (pmc->fn(cur_value, pmc->opaque) != 0)\n+\t\tgoto end;\n \n \t/* execute UMWAIT */\n \tasm volatile(\".byte 0xf2, 0x0f, 0xae, 0xf7;\"\n",
    "prefixes": [
        "v10",
        "1/8"
    ]
}