From patchwork Fri Jun 1 14:04:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Prarit Bhargava X-Patchwork-Id: 10443519 X-Patchwork-Delegate: lenb@kernel.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 75445603D7 for ; Fri, 1 Jun 2018 14:04:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6666C28D26 for ; Fri, 1 Jun 2018 14:04:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 59BAF28D38; Fri, 1 Jun 2018 14:04:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BE76128D26 for ; Fri, 1 Jun 2018 14:04:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751555AbeFAOEs (ORCPT ); Fri, 1 Jun 2018 10:04:48 -0400 Received: from mx1.redhat.com ([209.132.183.28]:52442 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751512AbeFAOEq (ORCPT ); Fri, 1 Jun 2018 10:04:46 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9807E82111; Fri, 1 Jun 2018 14:04:46 +0000 (UTC) Received: from prarit.bos.redhat.com (prarit-guest.khw.lab.eng.bos.redhat.com [10.16.186.145]) by smtp.corp.redhat.com (Postfix) with ESMTP id 27E345D9C6; Fri, 1 Jun 2018 14:04:46 +0000 (UTC) From: Prarit Bhargava To: linux-pm@vger.kernel.org Cc: len.brown@intel.com, Prarit Bhargava Subject: [PATCH v3 2/8] turbostat: Fix node and siblings lookup data Date: Fri, 1 Jun 2018 10:04:29 -0400 Message-Id: <20180601140435.6611-3-prarit@redhat.com> In-Reply-To: <20180601140435.6611-1-prarit@redhat.com> References: <20180601140435.6611-1-prarit@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Fri, 01 Jun 2018 14:04:46 +0000 (UTC) Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The turbostat code only looks at thread_siblings_list to determine if processing units/threads are on the same the core. This works well on Intel systems which have a shared L1 instruction and data cache. This does not work on AMD systems which have shared L1 instruction cache but separate L1 data caches. Other utilities also check sibling's core ID to determine if the processing unit shares the same core. Additionally, the cpu_topology *cpus list used in topology_probe() can be used elsewhere in the code to simplify things. Export *cpus to the entire turbostat code, and add Processing Unit/Thread IDs information to each cpu_topology struct. Confirm that the thread is on the same core as indicated by thread_siblings_list. [v2]: Fixup CPU_* usage that caused gcc malloc error. Signed-off-by: Prarit Bhargava Cc: Len Brown --- tools/power/x86/turbostat/turbostat.c | 117 ++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 35 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 48c032ccd0c1..498bdf83e1e7 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -148,6 +148,7 @@ char *progname; cpu_set_t *cpu_present_set, *cpu_affinity_set, *cpu_subset; size_t cpu_present_setsize, cpu_affinity_setsize, cpu_subset_size; #define MAX_ADDED_COUNTERS 16 +#define BITMASK_SIZE 32 struct thread_data { struct timeval tv_begin; @@ -244,6 +245,13 @@ struct system_summary { struct pkg_data packages; } average; +struct cpu_topology { + int physical_package_id; + int logical_cpu_id; + int node_id; + int physical_core_id; + cpu_set_t *put_ids; /* Processing Unit/Thread IDs */ +} *cpus; struct topo_params { int num_packages; @@ -2184,6 +2192,8 @@ void free_fd_percpu(void) void free_all_buffers(void) { + int i; + CPU_FREE(cpu_present_set); cpu_present_set = NULL; cpu_present_setsize = 0; @@ -2216,6 +2226,12 @@ void free_all_buffers(void) free(irq_column_2_cpu); free(irqs_per_cpu); + + for (i = 0; i <= topo.max_cpu_num; ++i) { + if (cpus[i].put_ids) + CPU_FREE(cpus[i].put_ids); + } + free(cpus); } @@ -2296,35 +2312,60 @@ int get_core_id(int cpu) return parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_id", cpu); } -int get_num_ht_siblings(int cpu) +int get_node_id(struct cpu_topology *thiscpu) { char path[80]; FILE *filep; - int sib1; - int matches = 0; - char character; - char str[100]; - char *ch; - - sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", cpu); - filep = fopen_or_die(path, "r"); + int i; + int cpu = thiscpu->logical_cpu_id; - /* - * file format: - * A ',' separated or '-' separated set of numbers - * (eg 1-2 or 1,3,4,5) - */ - fscanf(filep, "%d%c\n", &sib1, &character); - fseek(filep, 0, SEEK_SET); - fgets(str, 100, filep); - ch = strchr(str, character); - while (ch != NULL) { - matches++; - ch = strchr(ch+1, character); + for (i = 0; i <= topo.max_cpu_num; i++) { + sprintf(path, "/sys/devices/system/cpu/cpu%d/node%i/cpulist", + cpu, i); + filep = fopen(path, "r"); + if (!filep) + continue; + fclose(filep); + return i; } + return -1; +} +int get_thread_siblings(struct cpu_topology *thiscpu) +{ + char path[80], character; + FILE *filep; + unsigned long map; + int shift, sib_core; + int cpu = thiscpu->logical_cpu_id; + int offset = topo.max_cpu_num + 1; + size_t size; + + thiscpu->put_ids = CPU_ALLOC((topo.max_cpu_num + 1)); + if (!thiscpu->put_ids) + return -1; + + size = CPU_ALLOC_SIZE((topo.max_cpu_num + 1)); + CPU_ZERO_S(size, thiscpu->put_ids); + + sprintf(path, + "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", cpu); + filep = fopen_or_die(path, "r"); + do { + offset -= BITMASK_SIZE; + fscanf(filep, "%lx%c", &map, &character); + for (shift = 0; shift < BITMASK_SIZE; shift++) { + if ((map >> shift) & 0x1) { + sib_core = get_core_id(shift + offset); + if (sib_core == thiscpu->physical_core_id) + CPU_SET_S(shift + offset, size, + thiscpu->put_ids); + } + } + } while (!strncmp(&character, ",", 1)); fclose(filep); - return matches+1; + + return CPU_COUNT_S(size, thiscpu->put_ids); } /* @@ -2419,7 +2460,7 @@ void set_max_cpu_num(void) "/sys/devices/system/cpu/cpu0/topology/thread_siblings", "r"); while (fscanf(filep, "%lx,", &dummy) == 1) - topo.max_cpu_num += 32; + topo.max_cpu_num += BITMASK_SIZE; fclose(filep); topo.max_cpu_num--; /* 0 based */ } @@ -4321,10 +4362,6 @@ void topology_probe() int max_core_id = 0; int max_package_id = 0; int max_siblings = 0; - struct cpu_topology { - int core_id; - int physical_package_id; - } *cpus; /* Initialize num_cpus, max_cpu_num */ set_max_cpu_num(); @@ -4381,20 +4418,32 @@ void topology_probe() fprintf(outf, "cpu%d NOT PRESENT\n", i); continue; } - cpus[i].core_id = get_core_id(i); - if (cpus[i].core_id > max_core_id) - max_core_id = cpus[i].core_id; + cpus[i].logical_cpu_id = i; + + /* get package information */ cpus[i].physical_package_id = get_physical_package_id(i); if (cpus[i].physical_package_id > max_package_id) max_package_id = cpus[i].physical_package_id; - siblings = get_num_ht_siblings(i); + /* get numa node information */ + cpus[i].node_id = get_node_id(&cpus[i]); + + /* get core information */ + cpus[i].physical_core_id = get_core_id(i); + if (cpus[i].physical_core_id > max_core_id) + max_core_id = cpus[i].physical_core_id; + + /* get thread information */ + siblings = get_thread_siblings(&cpus[i]); if (siblings > max_siblings) max_siblings = siblings; + if (debug > 1) - fprintf(outf, "cpu %d pkg %d core %d\n", - i, cpus[i].physical_package_id, cpus[i].core_id); + fprintf(outf, "cpu %d pkg %d node %d core %d\n", + i, cpus[i].physical_package_id, + cpus[i].node_id, + cpus[i].physical_core_id); } topo.num_cores_per_pkg = max_core_id + 1; if (debug > 1) @@ -4413,8 +4462,6 @@ void topology_probe() topo.num_threads_per_core = max_siblings; if (debug > 1) fprintf(outf, "max_siblings %d\n", max_siblings); - - free(cpus); } void