*/
int *cpu2node;
+/* CPU topology */
+struct cpu_topology *st_cpu_topology;
+
struct tm mp_tstamp[3];
/* Activity flag */
perror("malloc");
exit(4);
}
+
+ if ((st_cpu_topology = (struct cpu_topology *) malloc(sizeof(struct cpu_topology) * nr_cpus)) == NULL) {
+ perror("malloc");
+ exit(4);
+ }
}
/*
return hi_node_nr;
}
+/*
+ ***************************************************************************
+ * Read system logical topology: Socket number for each logical core is read
+ * from the /sys/devices/system/cpu/cpu{N}/topology/physical_package_id file,
+ * and the logical core id number is the first number read from the
+ * /sys/devices/system/cpu/cpu{N}/topology/thread_siblings_list file.
+ * Don't use /sys/devices/system/cpu/cpu{N}/topology/core_id as this is the
+ * physical core id (seems to be different from the number displayed by lscpu).
+ *
+ * IN:
+ * @nr_cpus Number of CPU on this machine.
+ * @cpu_topo Structures where socket and core id numbers will be saved.
+ *
+ * OUT:
+ * @cpu_topo Structures where socket and core id numbers have been saved.
+ ***************************************************************************
+ */
+void read_topology(int nr_cpus, struct cpu_topology *cpu_topo)
+{
+ struct cpu_topology *cpu_topo_i;
+ FILE *fp;
+ char filename[MAX_PF_NAME];
+ int cpu;
+
+ /* Init system topology */
+ memset(st_cpu_topology, 0, sizeof(struct cpu_topology) * nr_cpus);
+
+ for (cpu = 0; cpu < nr_cpus; cpu++) {
+
+ cpu_topo_i = cpu_topo + cpu;
+
+ /* Read current CPU's socket number */
+ snprintf(filename, MAX_PF_NAME, "%s/cpu%d/%s", SYSFS_DEVCPU, cpu, PHYS_PACK_ID);
+ filename[MAX_PF_NAME - 1] = '\0';
+
+ if ((fp = fopen(filename, "r")) != NULL) {
+ fscanf(fp, "%d", &cpu_topo_i->phys_package_id);
+ fclose(fp);
+ }
+
+ /* Read current CPU's logical core id number */
+ snprintf(filename, MAX_PF_NAME, "%s/cpu%d/%s", SYSFS_DEVCPU, cpu, THREAD_SBL_LST);
+ filename[MAX_PF_NAME - 1] = '\0';
+
+ if ((fp = fopen(filename, "r")) != NULL) {
+ fscanf(fp, "%d", &cpu_topo_i->logical_core_id);
+ fclose(fp);
+ }
+ }
+}
+
/*
***************************************************************************
* Compute node statistics: Split CPU statistics among nodes.
{
int i;
struct stats_cpu *scc, *scp;
+ struct cpu_topology *cpu_topo_i;
if (dis) {
- printf("\n%-11s CPU %%usr %%nice %%sys %%iowait %%irq "
- "%%soft %%steal %%guest %%gnice %%idle\n",
- prev_string);
+ printf("\n%-11s CPU", prev_string);
+ if (DISPLAY_TOPOLOGY(flags)) {
+ printf(" CORE SOCK NODE");
+ }
+ printf(" %%usr %%nice %%sys %%iowait %%irq "
+ "%%soft %%steal %%guest %%gnice %%idle\n");
}
/*
if (i == 0) {
/* This is CPU "all" */
cprintf_in(IS_STR, " %s", " all", 0);
+
+ if (DISPLAY_TOPOLOGY(flags)) {
+ printf(" ");
+ }
}
else {
cprintf_in(IS_INT, " %4d", "", i - 1);
+ if (DISPLAY_TOPOLOGY(flags)) {
+ cpu_topo_i = st_cpu_topology + i - 1;
+ cprintf_in(IS_INT, " %4d", "", cpu_topo_i->logical_core_id);
+ cprintf_in(IS_INT, " %4d", "", cpu_topo_i->phys_package_id);
+ cprintf_in(IS_INT, " %4d", "", cpu2node[i - 1]);
+ }
+
/* Recalculate itv for current proc */
deltot_jiffies = get_per_cpu_interval(scc, scp);
unsigned char offline_cpu_bitmap[])
{
int i, next = FALSE;
- char cpu_name[16];
+ char cpu_name[16], topology[1024] = "";
struct stats_cpu *scc, *scp;
+ struct cpu_topology *cpu_topo_i;
xprintf(tab++, "\"cpu-load\": [");
/* This is CPU "all" */
strcpy(cpu_name, "all");
+ if (DISPLAY_TOPOLOGY(flags)) {
+ snprintf(topology, 1024,
+ ", \"core\": \"\", \"socket\": \"\", \"node\": \"\"");
+ }
+
}
else {
snprintf(cpu_name, 16, "%d", i - 1);
cpu_name[15] = '\0';
+ if (DISPLAY_TOPOLOGY(flags)) {
+ cpu_topo_i = st_cpu_topology + i - 1;
+ snprintf(topology, 1024,
+ ", \"core\": \"%d\", \"socket\": \"%d\", \"node\": \"%d\"",
+ cpu_topo_i->logical_core_id, cpu_topo_i->phys_package_id, cpu2node[i - 1]);
+ }
+
/* Recalculate itv for current proc */
deltot_jiffies = get_per_cpu_interval(scc, scp);
* If the CPU is tickless then there is no change in CPU values
* but the sum of values is not zero.
*/
- xprintf0(tab, "{\"cpu\": \"%d\", \"usr\": 0.00, \"nice\": 0.00, "
+ xprintf0(tab, "{\"cpu\": \"%d\"%s, \"usr\": 0.00, \"nice\": 0.00, "
"\"sys\": 0.00, \"iowait\": 0.00, \"irq\": 0.00, "
"\"soft\": 0.00, \"steal\": 0.00, \"guest\": 0.00, "
- "\"gnice\": 0.00, \"idle\": 100.00}", i - 1);
+ "\"gnice\": 0.00, \"idle\": 100.00}", i - 1, topology);
printf("\n");
continue;
}
}
- xprintf0(tab, "{\"cpu\": \"%s\", \"usr\": %.2f, \"nice\": %.2f, \"sys\": %.2f, "
+ xprintf0(tab, "{\"cpu\": \"%s\"%s, \"usr\": %.2f, \"nice\": %.2f, \"sys\": %.2f, "
"\"iowait\": %.2f, \"irq\": %.2f, \"soft\": %.2f, \"steal\": %.2f, "
- "\"guest\": %.2f, \"gnice\": %.2f, \"idle\": %.2f}", cpu_name,
+ "\"guest\": %.2f, \"gnice\": %.2f, \"idle\": %.2f}",
+ cpu_name, topology,
(scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
0.0 :
ll_sp_value(scp->cpu_user - scp->cpu_guest,
}
}
+ /* Read system topology */
+ if (DISPLAY_CPU(actflags) && DISPLAY_TOPOLOGY(flags)) {
+ read_topology(cpu_nr, st_cpu_topology);
+ }
+
/*
* Read total number of interrupts received among all CPU.
* (this is the first value on the line "intr:" in the /proc/stat file).
read_uptime(&(uptime_cs[curr]));
read_stat_cpu(st_cpu[curr], cpu_nr + 1);
+ /* Read system topology */
+ if (DISPLAY_CPU(actflags) && DISPLAY_TOPOLOGY(flags)) {
+ read_topology(cpu_nr, st_cpu_topology);
+ }
+
/* Read total number of interrupts received among all CPU */
if (DISPLAY_IRQ_SUM(actflags)) {
read_stat_irq(st_irq[curr], 1);
}
break;
+ case 'T':
+ /* Display logical topology */
+ flags |= F_TOPOLOGY;
+ break;
+
case 'u':
/* Display CPU */
actflags |= M_D_CPU;