Show a patch.

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

{
    "id": 43057,
    "url": "http://patches.dpdk.org/api/patches/43057/",
    "web_url": "http://patches.dpdk.org/patch/43057/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/",
        "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"
    },
    "msgid": "<20180713142302.34576-4-david.hunt@intel.com>",
    "date": "2018-07-13T14:22:56",
    "name": "[v4,3/9] examples/vm_power: add oob monitoring functions",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "0ad52c230af792f5111f522c5f56c611fecbd5be",
    "submitter": {
        "id": 342,
        "url": "http://patches.dpdk.org/api/people/342/",
        "name": "David Hunt",
        "email": "david.hunt@intel.com"
    },
    "delegate": {
        "id": 22,
        "url": "http://patches.dpdk.org/api/users/22/",
        "username": "pdelarag",
        "first_name": "Pablo",
        "last_name": "de Lara Guarch",
        "email": "pablo.de.lara.guarch@intel.com"
    },
    "mbox": "http://patches.dpdk.org/patch/43057/mbox/",
    "series": [
        {
            "id": 568,
            "url": "http://patches.dpdk.org/api/series/568/",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=568",
            "date": "2018-07-13T14:22:53",
            "name": "examples/vm_power: 100% Busy Polling",
            "version": 4,
            "mbox": "http://patches.dpdk.org/series/568/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/43057/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/43057/checks/",
    "tags": {},
    "headers": {
        "X-Mailer": "git-send-email 2.17.1",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "Precedence": "list",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "Date": "Fri, 13 Jul 2018 15:22:56 +0100",
        "X-Mailman-Version": "2.1.15",
        "Delivered-To": "patchwork@dpdk.org",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "Cc": "david.hunt@intel.com,\n\tthomas@monjalon.net",
        "To": "dev@dpdk.org",
        "Errors-To": "dev-bounces@dpdk.org",
        "References": "<20180626092317.11031-2-david.hunt@intel.com>\n\t<20180713142302.34576-1-david.hunt@intel.com>",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>",
        "From": "David Hunt <david.hunt@intel.com>",
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-IronPort-AV": "E=Sophos;i=\"5.51,347,1526367600\"; d=\"scan'208\";a=\"56278193\"",
        "List-Post": "<mailto:dev@dpdk.org>",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 902F02C38;\n\tFri, 13 Jul 2018 16:23:26 +0200 (CEST)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n\tby dpdk.org (Postfix) with ESMTP id 9C3072BE5\n\tfor <dev@dpdk.org>; Fri, 13 Jul 2018 16:23:22 +0200 (CEST)",
            "from orsmga007.jf.intel.com ([10.7.209.58])\n\tby fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t13 Jul 2018 07:23:22 -0700",
            "from silpixa00399952.ir.intel.com (HELO\n\tsilpixa00399952.ger.corp.intel.com) ([10.237.223.64])\n\tby orsmga007.jf.intel.com with ESMTP; 13 Jul 2018 07:23:21 -0700"
        ],
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "X-Amp-File-Uploaded": "False",
        "Subject": "[dpdk-dev] [PATCH v4 3/9] examples/vm_power: add oob monitoring\n\tfunctions",
        "In-Reply-To": "<20180713142302.34576-1-david.hunt@intel.com>",
        "Message-Id": "<20180713142302.34576-4-david.hunt@intel.com>",
        "X-ExtLoop1": "1",
        "X-BeenThere": "dev@dpdk.org",
        "X-Original-To": "patchwork@dpdk.org"
    },
    "content": "This patch introduces the out-of-band (oob) core monitoring\nfunctions.\n\nThe functions are similar to the channel manager functions.\nThere are function to add and remove cores from the\nlist of cores being monitored. There is a function to initialise\nthe monitor setup, run the monitor thread, and exit the monitor.\n\nThe monitor thread runs in it's own lcore, and is separate\nfunctionality to the channel monitor which is epoll based.\nTHis thread is timer based. It loops through all monitored cores,\ncalculates the branch ratio, scales up or down the core, then\nsleeps for an interval (~250 uS).\n\nThe method it uses to read the branch counters is a pread on the\n/dev/cpu/x/msr file, so the 'msr' kernel module needs to be loaded.\nAlso, since the msr.h file has been made unavailable in recent\nkernels, we have #defines for the relevant MSRs included in the\ncode.\n\nThe makefile has a switch for x86 and non-x86 platforms,\nand compiles stub function for non-x86 platforms.\n\nSigned-off-by: David Hunt <david.hunt@intel.com>\nAcked-by: Radu Nicolau <radu.nicolau@intel.com>\n---\n examples/vm_power_manager/Makefile          |   5 +\n examples/vm_power_manager/oob_monitor.h     |  68 +++++\n examples/vm_power_manager/oob_monitor_nop.c |  38 +++\n examples/vm_power_manager/oob_monitor_x86.c | 259 ++++++++++++++++++++\n 4 files changed, 370 insertions(+)\n create mode 100644 examples/vm_power_manager/oob_monitor.h\n create mode 100644 examples/vm_power_manager/oob_monitor_nop.c\n create mode 100644 examples/vm_power_manager/oob_monitor_x86.c",
    "diff": "diff --git a/examples/vm_power_manager/Makefile b/examples/vm_power_manager/Makefile\nindex 0c925967c..13a5205ba 100644\n--- a/examples/vm_power_manager/Makefile\n+++ b/examples/vm_power_manager/Makefile\n@@ -20,6 +20,11 @@ APP = vm_power_mgr\n # all source are stored in SRCS-y\n SRCS-y := main.c vm_power_cli.c power_manager.c channel_manager.c\n SRCS-y += channel_monitor.c parse.c\n+ifeq ($(CONFIG_RTE_ARCH_X86_64),y)\n+SRCS-y += oob_monitor_x86.c\n+else\n+SRCS-y += oob_monitor_nop.c\n+endif\n \n CFLAGS += -O3 -I$(RTE_SDK)/lib/librte_power/\n CFLAGS += $(WERROR_FLAGS)\ndiff --git a/examples/vm_power_manager/oob_monitor.h b/examples/vm_power_manager/oob_monitor.h\nnew file mode 100644\nindex 000000000..b96e08df7\n--- /dev/null\n+++ b/examples/vm_power_manager/oob_monitor.h\n@@ -0,0 +1,68 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018 Intel Corporation\n+ */\n+\n+#ifndef OOB_MONITOR_H_\n+#define OOB_MONITOR_H_\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+/**\n+ * Setup the Branch Monitor resources required to initialize epoll.\n+ * Must be called first before calling other functions.\n+ *\n+ * @return\n+ *  - 0 on success.\n+ *  - Negative on error.\n+ */\n+int branch_monitor_init(void);\n+\n+/**\n+ * Run the OOB branch monitor, loops forever on on epoll_wait.\n+ *\n+ *\n+ * @return\n+ *  None\n+ */\n+void run_branch_monitor(void);\n+\n+/**\n+ * Exit the OOB Branch Monitor.\n+ *\n+ * @return\n+ *  None\n+ */\n+void branch_monitor_exit(void);\n+\n+/**\n+ * Add a core to the list of cores to monitor.\n+ *\n+ * @param core\n+ *  Core Number\n+ *\n+ * @return\n+ *  - 0 on success.\n+ *  - Negative on error.\n+ */\n+int add_core_to_monitor(int core);\n+\n+/**\n+ * Remove a previously added core from core list.\n+ *\n+ * @param core\n+ *  Core Number\n+ *\n+ * @return\n+ *  - 0 on success.\n+ *  - Negative on error.\n+ */\n+int remove_core_from_monitor(int core);\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+\n+#endif /* OOB_MONITOR_H_ */\ndiff --git a/examples/vm_power_manager/oob_monitor_nop.c b/examples/vm_power_manager/oob_monitor_nop.c\nnew file mode 100644\nindex 000000000..7e7b8bc14\n--- /dev/null\n+++ b/examples/vm_power_manager/oob_monitor_nop.c\n@@ -0,0 +1,38 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2010-2014 Intel Corporation\n+ */\n+\n+#include \"oob_monitor.h\"\n+\n+void branch_monitor_exit(void)\n+{\n+}\n+\n+__attribute__((unused)) static float\n+apply_policy(__attribute__((unused)) int core)\n+{\n+\treturn 0.0;\n+}\n+\n+int\n+add_core_to_monitor(__attribute__((unused)) int core)\n+{\n+\treturn 0;\n+}\n+\n+int\n+remove_core_from_monitor(__attribute__((unused)) int core)\n+{\n+\treturn 0;\n+}\n+\n+int\n+branch_monitor_init(void)\n+{\n+\treturn 0;\n+}\n+\n+void\n+run_branch_monitor(void)\n+{\n+}\ndiff --git a/examples/vm_power_manager/oob_monitor_x86.c b/examples/vm_power_manager/oob_monitor_x86.c\nnew file mode 100644\nindex 000000000..62d503ca5\n--- /dev/null\n+++ b/examples/vm_power_manager/oob_monitor_x86.c\n@@ -0,0 +1,259 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018 Intel Corporation\n+ */\n+\n+#include <unistd.h>\n+#include <fcntl.h>\n+#include <rte_log.h>\n+\n+#include \"oob_monitor.h\"\n+#include \"power_manager.h\"\n+#include \"channel_manager.h\"\n+\n+static volatile unsigned run_loop = 1;\n+static uint64_t g_branches, g_branch_misses;\n+static int g_active;\n+\n+void branch_monitor_exit(void)\n+{\n+\trun_loop = 0;\n+}\n+\n+/* Number of microseconds between each poll */\n+#define INTERVAL 100\n+#define PRINT_LOOP_COUNT (1000000/INTERVAL)\n+#define RATIO_THRESHOLD 0.03\n+#define IA32_PERFEVTSEL0 0x186\n+#define IA32_PERFEVTSEL1 0x187\n+#define IA32_PERFCTR0 0xc1\n+#define IA32_PERFCTR1 0xc2\n+#define IA32_PERFEVT_BRANCH_HITS 0x05300c4\n+#define IA32_PERFEVT_BRANCH_MISS 0x05300c5\n+\n+static float\n+apply_policy(int core)\n+{\n+\tstruct core_info *ci;\n+\tuint64_t counter;\n+\tuint64_t branches, branch_misses;\n+\tuint32_t last_branches, last_branch_misses;\n+\tint hits_diff, miss_diff;\n+\tfloat ratio;\n+\tint ret;\n+\n+\tg_active = 0;\n+\tci = get_core_info();\n+\n+\tlast_branches = ci->cd[core].last_branches;\n+\tlast_branch_misses = ci->cd[core].last_branch_misses;\n+\n+\tret = pread(ci->cd[core].msr_fd, &counter,\n+\t\t\tsizeof(counter), IA32_PERFCTR0);\n+\tif (ret < 0)\n+\t\tRTE_LOG(ERR, POWER_MANAGER,\n+\t\t\t\t\"unable to read counter for core %u\\n\",\n+\t\t\t\tcore);\n+\tbranches = counter;\n+\n+\tret = pread(ci->cd[core].msr_fd, &counter,\n+\t\t\tsizeof(counter), IA32_PERFCTR1);\n+\tif (ret < 0)\n+\t\tRTE_LOG(ERR, POWER_MANAGER,\n+\t\t\t\t\"unable to read counter for core %u\\n\",\n+\t\t\t\tcore);\n+\tbranch_misses = counter;\n+\n+\n+\tci->cd[core].last_branches = branches;\n+\tci->cd[core].last_branch_misses = branch_misses;\n+\n+\thits_diff = (int)branches - (int)last_branches;\n+\tif (hits_diff <= 0) {\n+\t\t/* Likely a counter overflow condition, skip this round */\n+\t\treturn -1.0;\n+\t}\n+\n+\tmiss_diff = (int)branch_misses - (int)last_branch_misses;\n+\tif (miss_diff <= 0) {\n+\t\t/* Likely a counter overflow condition, skip this round */\n+\t\treturn -1.0;\n+\t}\n+\n+\tg_branches = hits_diff;\n+\tg_branch_misses = miss_diff;\n+\n+\tif (hits_diff < (INTERVAL*100)) {\n+\t\t/* Likely no workload running on this core. Skip. */\n+\t\treturn -1.0;\n+\t}\n+\n+\tratio = (float)miss_diff * (float)100 / (float)hits_diff;\n+\n+\tif (ratio < RATIO_THRESHOLD)\n+\t\tpower_manager_scale_core_min(core);\n+\telse\n+\t\tpower_manager_scale_core_max(core);\n+\n+\tg_active = 1;\n+\treturn ratio;\n+}\n+\n+int\n+add_core_to_monitor(int core)\n+{\n+\tstruct core_info *ci;\n+\tchar proc_file[UNIX_PATH_MAX];\n+\tint ret;\n+\n+\tci = get_core_info();\n+\n+\tif (core < ci->core_count) {\n+\t\tlong setup;\n+\n+\t\tsnprintf(proc_file, UNIX_PATH_MAX, \"/dev/cpu/%d/msr\", core);\n+\t\tci->cd[core].msr_fd = open(proc_file, O_RDWR | O_SYNC);\n+\t\tif (ci->cd[core].msr_fd < 0) {\n+\t\t\tRTE_LOG(ERR, POWER_MANAGER,\n+\t\t\t\t\t\"Error opening MSR file for core %d \"\n+\t\t\t\t\t\"(is msr kernel module loaded?)\\n\",\n+\t\t\t\t\tcore);\n+\t\t\treturn -1;\n+\t\t}\n+\t\t/*\n+\t\t * Set up branch counters\n+\t\t */\n+\t\tsetup = IA32_PERFEVT_BRANCH_HITS;\n+\t\tret = pwrite(ci->cd[core].msr_fd, &setup,\n+\t\t\t\tsizeof(setup), IA32_PERFEVTSEL0);\n+\t\tif (ret < 0) {\n+\t\t\tRTE_LOG(ERR, POWER_MANAGER,\n+\t\t\t\t\t\"unable to set counter for core %u\\n\",\n+\t\t\t\t\tcore);\n+\t\t\treturn ret;\n+\t\t}\n+\t\tsetup = IA32_PERFEVT_BRANCH_MISS;\n+\t\tret = pwrite(ci->cd[core].msr_fd, &setup,\n+\t\t\t\tsizeof(setup), IA32_PERFEVTSEL1);\n+\t\tif (ret < 0) {\n+\t\t\tRTE_LOG(ERR, POWER_MANAGER,\n+\t\t\t\t\t\"unable to set counter for core %u\\n\",\n+\t\t\t\t\tcore);\n+\t\t\treturn ret;\n+\t\t}\n+\t\t/*\n+\t\t * Close the file and re-open as read only so\n+\t\t * as not to hog the resource\n+\t\t */\n+\t\tclose(ci->cd[core].msr_fd);\n+\t\tci->cd[core].msr_fd = open(proc_file, O_RDONLY);\n+\t\tif (ci->cd[core].msr_fd < 0) {\n+\t\t\tRTE_LOG(ERR, POWER_MANAGER,\n+\t\t\t\t\t\"Error opening MSR file for core %d \"\n+\t\t\t\t\t\"(is msr kernel module loaded?)\\n\",\n+\t\t\t\t\tcore);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tci->cd[core].oob_enabled = 1;\n+\t}\n+\treturn 0;\n+}\n+\n+int\n+remove_core_from_monitor(int core)\n+{\n+\tstruct core_info *ci;\n+\tchar proc_file[UNIX_PATH_MAX];\n+\tint ret;\n+\n+\tci = get_core_info();\n+\n+\tif (ci->cd[core].oob_enabled) {\n+\t\tlong setup;\n+\n+\t\t/*\n+\t\t * close the msr file, then reopen rw so we can\n+\t\t * disable the counters\n+\t\t */\n+\t\tif (ci->cd[core].msr_fd != 0)\n+\t\t\tclose(ci->cd[core].msr_fd);\n+\t\tsnprintf(proc_file, UNIX_PATH_MAX, \"/dev/cpu/%d/msr\", core);\n+\t\tci->cd[core].msr_fd = open(proc_file, O_RDWR | O_SYNC);\n+\t\tif (ci->cd[core].msr_fd < 0) {\n+\t\t\tRTE_LOG(ERR, POWER_MANAGER,\n+\t\t\t\t\t\"Error opening MSR file for core %d \"\n+\t\t\t\t\t\"(is msr kernel module loaded?)\\n\",\n+\t\t\t\t\tcore);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tsetup = 0x0; /* clear event */\n+\t\tret = pwrite(ci->cd[core].msr_fd, &setup,\n+\t\t\t\tsizeof(setup), IA32_PERFEVTSEL0);\n+\t\tif (ret < 0) {\n+\t\t\tRTE_LOG(ERR, POWER_MANAGER,\n+\t\t\t\t\t\"unable to set counter for core %u\\n\",\n+\t\t\t\t\tcore);\n+\t\t\treturn ret;\n+\t\t}\n+\t\tsetup = 0x0; /* clear event */\n+\t\tret = pwrite(ci->cd[core].msr_fd, &setup,\n+\t\t\t\tsizeof(setup), IA32_PERFEVTSEL1);\n+\t\tif (ret < 0) {\n+\t\t\tRTE_LOG(ERR, POWER_MANAGER,\n+\t\t\t\t\t\"unable to set counter for core %u\\n\",\n+\t\t\t\t\tcore);\n+\t\t\treturn ret;\n+\t\t}\n+\n+\t\tclose(ci->cd[core].msr_fd);\n+\t\tci->cd[core].msr_fd = 0;\n+\t\tci->cd[core].oob_enabled = 0;\n+\t}\n+\treturn 0;\n+}\n+\n+int\n+branch_monitor_init(void)\n+{\n+\treturn 0;\n+}\n+\n+void\n+run_branch_monitor(void)\n+{\n+\tstruct core_info *ci;\n+\tint print = 0;\n+\tfloat ratio;\n+\tint printed;\n+\tint reads = 0;\n+\n+\tci = get_core_info();\n+\n+\twhile (run_loop) {\n+\n+\t\tif (!run_loop)\n+\t\t\tbreak;\n+\t\tusleep(INTERVAL);\n+\t\tint j;\n+\t\tprint++;\n+\t\tprinted = 0;\n+\t\tfor (j = 0; j < ci->core_count; j++) {\n+\t\t\tif (ci->cd[j].oob_enabled) {\n+\t\t\t\tratio = apply_policy(j);\n+\t\t\t\tif ((print > PRINT_LOOP_COUNT) && (g_active)) {\n+\t\t\t\t\tprintf(\"  %d: %.4f {%lu} {%d}\", j,\n+\t\t\t\t\t\t\tratio, g_branches,\n+\t\t\t\t\t\t\treads);\n+\t\t\t\t\tprinted = 1;\n+\t\t\t\t\treads = 0;\n+\t\t\t\t} else {\n+\t\t\t\t\treads++;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t\tif (print > PRINT_LOOP_COUNT) {\n+\t\t\tif (printed)\n+\t\t\t\tprintf(\"\\n\");\n+\t\t\tprint = 0;\n+\t\t}\n+\t}\n+}\n",
    "prefixes": [
        "v4",
        "3/9"
    ]
}