[DTrace-devel] [PATCH 08/15 v2] Update cpu handling to also retrieve num_possible_cpus and chip id

Kris Van Hees kris.van.hees at oracle.com
Fri May 29 10:59:38 PDT 2020


The code used to populate the list of online CPUs was only recording
the CPU ids.  In order to support the cpuinfo_t information needed
for the curcpu D variable we need additional information.  This patch
adds code to obtain the chip id for each CPU and also the number of
possible CPUs on the system..

The cpuinfo_t structure definition is added to include/dtrace/conf.h,
and members in dtrace_conf_t have been updated (better naming, type
updates, and adding num_possible_cpus).  The renaming of numcpus to
num_online_cpus required updates to various source code files that use
it.

The list of online CPU ids has been converted into a list of cpuinfo_t
structures.

The dt_conf_init() function has been moved from dt_subr.c to its own
file.

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 include/dtrace/conf.h  |  27 ++++++---
 libdtrace/Build        |  10 ++--
 libdtrace/dt_bpf.c     |   2 +-
 libdtrace/dt_conf.c    | 122 +++++++++++++++++++++++++++++++++++++++++
 libdtrace/dt_consume.c |   4 +-
 libdtrace/dt_open.c    |  14 +++--
 libdtrace/dt_peb.c     |   9 +--
 libdtrace/dt_subr.c    |  85 ----------------------------
 8 files changed, 161 insertions(+), 112 deletions(-)
 create mode 100644 libdtrace/dt_conf.c

diff --git a/include/dtrace/conf.h b/include/dtrace/conf.h
index d40a781b..90195835 100644
--- a/include/dtrace/conf.h
+++ b/include/dtrace/conf.h
@@ -16,18 +16,27 @@
 #include <dtrace/universal.h>
 #include <dtrace/conf_defines.h>
 
+typedef struct cpuinfo {
+	processorid_t	cpu_id;
+	psetid_t	cpu_pset;
+	chipid_t	cpu_chip;
+	lgrp_id_t	cpu_lgrp;
+	void		*cpu_info;
+} cpuinfo_t;
+
 typedef struct dtrace_conf {
-	uint_t		numcpus;	/* number of online CPUs */
-	processorid_t	maxcpuid;	/* highest CPU id */
-	processorid_t	*cpuids;	/* list of CPU ids */
+	uint32_t	num_possible_cpus;	/* number of possible CPUs */
+	uint32_t	num_online_cpus;	/* number of online CPUs */
+	processorid_t	max_cpuid;		/* highest CPU id */
+	cpuinfo_t	*cpus;			/* CPU info structs */
 
 	/* FIXME: Are these actually still necessary for our purposes? */
-	uint_t		dtc_difversion;	/* supported DIF version */
-	uint_t		dtc_difintregs;	/* # of DIF integer registers */
-	uint_t		dtc_diftupregs;	/* # of DIF tuple registers */
-	uint_t		dtc_ctfmodel;	/* CTF data model */
-	uint_t		dtc_maxbufs;	/* max # of buffers */
-	uint_t		dtc_pad[7];	/* reserved for future use */
+	uint32_t	dtc_difversion;	/* supported DIF version */
+	uint32_t	dtc_difintregs;	/* # of DIF integer registers */
+	uint32_t	dtc_diftupregs;	/* # of DIF tuple registers */
+	uint32_t	dtc_ctfmodel;	/* CTF data model */
+	uint32_t	dtc_maxbufs;	/* max # of buffers */
+	uint32_t	dtc_pad[7];	/* reserved for future use */
 } dtrace_conf_t;
 
 #endif /* _DTRACE_CONF_H */
diff --git a/libdtrace/Build b/libdtrace/Build
index 684d8ebc..1fe41d53 100644
--- a/libdtrace/Build
+++ b/libdtrace/Build
@@ -11,11 +11,11 @@ libdtrace-build_CPPFLAGS = -Ilibdtrace -Ilibproc -Iuts/intel -Ilibdtrace/$(ARCHI
 libdtrace-build_TARGET = libdtrace
 libdtrace-build_DIR := $(current-dir)
 libdtrace-build_SOURCES = dt_lex.c dt_aggregate.c dt_as.c dt_bpf.c \
-			  dt_buf.c dt_cc.c dt_cg.c dt_consume.c dt_debug.c \
-			  dt_decl.c dt_dis.c dt_dlibs.c dt_dof.c dt_error.c \
-			  dt_errtags.c dt_grammar.c dt_handle.c dt_htab.c \
-			  dt_ident.c dt_link.c dt_kernel_module.c dt_list.c \
-			  dt_map.c dt_module.c dt_names.c dt_open.c \
+			  dt_buf.c dt_cc.c dt_cg.c dt_conf.c dt_consume.c \
+			  dt_debug.c dt_decl.c dt_dis.c dt_dlibs.c dt_dof.c \
+			  dt_error.c dt_errtags.c dt_grammar.c dt_handle.c \
+			  dt_htab.c dt_ident.c dt_link.c dt_kernel_module.c \
+			  dt_list.c dt_map.c dt_module.c dt_names.c dt_open.c \
 			  dt_options.c dt_parser.c dt_pcap.c dt_pcb.c \
 			  dt_pid.c dt_pragma.c dt_printf.c dt_probe.c \
 			  dt_proc.c dt_program.c dt_provider.c dt_regset.c \
diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
index 97d33ae2..a0dd0ef0 100644
--- a/libdtrace/dt_bpf.c
+++ b/libdtrace/dt_bpf.c
@@ -146,7 +146,7 @@ dt_bpf_gmap_create(dtrace_hdl_t *dtp, uint_t probec)
 	/* Create global maps as long as there are no errors. */
 	if (create_gmap(dtp, "buffers", BPF_MAP_TYPE_PERF_EVENT_ARRAY,
 			sizeof(uint32_t), sizeof(uint32_t),
-			dtp->dt_conf.numcpus) == -1)
+			dtp->dt_conf.num_online_cpus) == -1)
 		return -1;	/* dt_errno is set for us */
 
 	if (create_gmap(dtp, "mem", BPF_MAP_TYPE_PERCPU_ARRAY,
diff --git a/libdtrace/dt_conf.c b/libdtrace/dt_conf.c
new file mode 100644
index 00000000..890198a8
--- /dev/null
+++ b/libdtrace/dt_conf.c
@@ -0,0 +1,122 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <dt_impl.h>
+
+#define SYSFS_CPU	"/sys/devices/system/cpu/"
+#define	ONLINE_CPUS	SYSFS_CPU "online"
+#define	POSSIBLE_CPUS	SYSFS_CPU "possible"
+#define	CPU_CHIP_ID	SYSFS_CPU "cpu%d/topology/physical_package_id"
+
+static uint32_t
+dt_cpuinfo_read(dtrace_hdl_t *dtp, const char *fn, cpuinfo_t **cip)
+{
+	FILE		*fp;
+	int		cnt = 0;
+	cpuinfo_t	*ci = NULL;
+
+	uint32_t	num, start;
+	int		range = 0;
+	char		c[2];
+
+	fp = fopen(fn, "r");
+	if (fp == NULL)
+		goto out;
+
+again:
+	cnt = 0;
+	for (;;) {
+		c[0] = 0;
+		switch (fscanf(fp, "%u%1[,-]", &num, c)) {
+		case 2:
+			if (c[0] == '-') {
+				range = 1;
+				start = num;
+				continue;
+			}
+			/* fall-through */
+		case 1:
+			if (range) {
+				range = 0;
+				cnt += num - start + 1;
+			} else {
+				start = num;
+				cnt++;
+			}
+
+			if (ci) {
+				uint32_t	i;
+
+				for (i = start; i <= num; i++)
+					(ci++)->cpu_id = i;
+			}
+
+			if (c[0] == ',')
+				continue;
+		default:
+			break;
+		}
+
+		break;
+	}
+
+	if (ci == NULL && cip != NULL && cnt > 0) {
+		ci = dt_calloc(dtp, cnt, sizeof(cpuinfo_t));
+		*cip = ci;
+		rewind(fp);
+		goto again;
+	}
+
+	fclose(fp);
+out:
+	return cnt;
+}
+
+void
+dt_conf_init(dtrace_hdl_t *dtp)
+{
+	size_t		len;
+	char		*fn;
+	int		i;
+	dtrace_conf_t	*conf = &dtp->dt_conf;
+	cpuinfo_t	*ci;
+
+	/*
+	 * Determine number of possible and online CPUs, and obtain the list of
+	 * cpuinfo_t structures for the online CPUs.
+	 */
+	conf->num_possible_cpus = dt_cpuinfo_read(dtp, POSSIBLE_CPUS, NULL);
+	conf->num_online_cpus = dt_cpuinfo_read(dtp, ONLINE_CPUS, &conf->cpus);
+
+	if (conf->num_online_cpus == 0 || conf->cpus == NULL)
+		return;
+
+	conf->max_cpuid = conf->cpus[conf->num_online_cpus - 1].cpu_id;
+
+	/* Retrieve the chip ID (physical_package_id) for each CPU. */
+	len = snprintf(NULL, 0, CPU_CHIP_ID, dtp->dt_conf.max_cpuid) + 1;
+	fn = dt_alloc(dtp, len);
+	if (fn == NULL)
+		return;
+
+	for (i = 0, ci = &dtp->dt_conf.cpus[0]; i < conf->num_online_cpus;
+	     i++, ci++) {
+		FILE	*fp;
+
+		snprintf(fn, len, CPU_CHIP_ID, ci->cpu_id);
+		fp = fopen(fn, "r");
+		if (fp != NULL) {
+			fscanf(fp, "%u", &ci->cpu_chip);
+			fclose(fp);
+		}
+	}
+
+	dt_free(dtp, fn);
+}
diff --git a/libdtrace/dt_consume.c b/libdtrace/dt_consume.c
index 5a5eb3bb..bd54ddee 100644
--- a/libdtrace/dt_consume.c
+++ b/libdtrace/dt_consume.c
@@ -2854,7 +2854,7 @@ dtrace_consume(dtrace_hdl_t *dtp, FILE *fp,
 	return (dt_consume_cpu(dtp, fp, dtp->dt_endedon, buf, pf, rf, arg));
 #else
 	dtrace_optval_t		timeout = dtp->dt_options[DTRACEOPT_SWITCHRATE];
-	struct epoll_event	events[dtp->dt_conf.numcpus];
+	struct epoll_event	events[dtp->dt_conf.num_online_cpus];
 	int			i, cnt;
 
 	/*
@@ -2863,7 +2863,7 @@ dtrace_consume(dtrace_hdl_t *dtp, FILE *fp,
 	 * We therefore need to convert the value.
 	 */
 	timeout /= NANOSEC / MILLISEC;
-	cnt = epoll_wait(dtp->dt_poll_fd, events, dtp->dt_conf.numcpus,
+	cnt = epoll_wait(dtp->dt_poll_fd, events, dtp->dt_conf.num_online_cpus,
 			 timeout);
 	if (cnt < 0) {
 		dt_set_errno(dtp, errno);
diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
index 2c57a8a3..7f680419 100644
--- a/libdtrace/dt_open.c
+++ b/libdtrace/dt_open.c
@@ -547,9 +547,10 @@ inline long NULL = 0; \n\
  * Default DTrace configuration.
  */
 static const dtrace_conf_t _dtrace_conf = {
-	0,			/* numcpus */
-	0,			/* maxcpuid */
-	NULL,			/* cpuids */
+	0,			/* num_possible_cpus */
+	0,			/* num_online_cpus */
+	0,			/* max_cpuid */
+	NULL,			/* CPU info structs */
 	DIF_VERSION,		/* dtc_difversion */
 	DIF_DIR_NREGS,		/* dtc_difintregs */
 	DIF_DTR_NREGS,		/* dtc_diftupregs */
@@ -779,8 +780,9 @@ dt_vopen(int version, int flags, int *errp,
 
 	memcpy(&dtp->dt_conf, &_dtrace_conf, sizeof (_dtrace_conf));
 	dt_conf_init(dtp);
-	dt_dprintf("detected %d CPUs online (highest cpuid %d)\n",
-		  dtp->dt_conf.numcpus, dtp->dt_conf.maxcpuid);
+	dt_dprintf("detected %u CPUs online (%u possible, highest cpuid %u)\n",
+		  dtp->dt_conf.num_online_cpus, dtp->dt_conf.num_possible_cpus,
+		  dtp->dt_conf.max_cpuid);
 
 	if (flags & DTRACE_O_LP64)
 		dtp->dt_conf.dtc_ctfmodel = CTF_MODEL_LP64;
@@ -1144,7 +1146,7 @@ dtrace_close(dtrace_hdl_t *dtp)
 	if (dtp == NULL)
 		return;
 
-	dt_free(dtp, dtp->dt_conf.cpuids);
+	dt_free(dtp, dtp->dt_conf.cpus);
 
 	if (dtp->dt_procs != NULL)
 		dt_proc_hash_destroy(dtp);
diff --git a/libdtrace/dt_peb.c b/libdtrace/dt_peb.c
index 033d183a..0ef1c419 100644
--- a/libdtrace/dt_peb.c
+++ b/libdtrace/dt_peb.c
@@ -125,7 +125,7 @@ dt_pebs_exit(dtrace_hdl_t *dtp)
 	if (dtp->dt_pebset == NULL)
 		return;
 
-	for (i = 0; i < dtp->dt_conf.numcpus; i++)
+	for (i = 0; i < dtp->dt_conf.num_online_cpus; i++)
 		dt_peb_close(&dtp->dt_pebset->pebs[i]);
 
 	dt_free(dtp, dtp->dt_pebset->pebs);
@@ -184,7 +184,8 @@ int dt_pebs_init(dtrace_hdl_t *dtp, size_t bufsize)
 	/*
 	 * Allocate the per-CPU perf event buffers.
 	 */
-	pebs = dt_calloc(dtp, dtp->dt_conf.numcpus, sizeof(struct dt_peb));
+	pebs = dt_calloc(dtp, dtp->dt_conf.num_online_cpus,
+			 sizeof(struct dt_peb));
 	if (pebs == NULL) {
 		dt_free(dtp, dtp->dt_pebset);
 		return -ENOMEM;
@@ -198,8 +199,8 @@ int dt_pebs_init(dtrace_hdl_t *dtp, size_t bufsize)
 	/*
 	 * Initialize a perf event buffer for each online CPU.
 	 */
-	for (i = 0; i < dtp->dt_conf.numcpus; i++) {
-		int			cpu = dtp->dt_conf.cpuids[i];
+	for (i = 0; i < dtp->dt_conf.num_online_cpus; i++) {
+		int			cpu = dtp->dt_conf.cpus[i].cpu_id;
 		struct epoll_event	ev;
 		dt_peb_t		*peb = &dtp->dt_pebset->pebs[i];
 
diff --git a/libdtrace/dt_subr.c b/libdtrace/dt_subr.c
index 3dcb92d8..39a2eefd 100644
--- a/libdtrace/dt_subr.c
+++ b/libdtrace/dt_subr.c
@@ -988,88 +988,3 @@ dt_str2kver(const char *kverstr, dt_version_t *vp)
 
 	return 0;
 }
-
-void
-dt_conf_init(dtrace_hdl_t *dtp)
-{
-	char		buf[BUFSIZ];
-	int		fd, cnt, start, end, i;
-	processorid_t	*cpu = NULL;
-	char		*p, *q;
-
-	fd = open("/sys/devices/system/cpu/online", O_RDONLY);
-	if (fd < 0)
-		goto fail;
-
-	cnt = read(fd, buf, sizeof(buf));
-	close(fd);
-	if (cnt <= 0)
-		goto fail;
-
-	/* If the string ends with a newline as it should), get rid of it. */
-	if (buf[cnt - 1] == '\n')
-		buf[--cnt] = 0;
-
-	/* Count how many CPUs are online.  */
-	cnt = 0;
-again:
-	p = buf;
-	do {
-		start = (int)strtol(p, &q, 10);
-		switch (*q) {
-		case '-':		/* range */
-			p = q + 1;
-			end = (int)strtol(p, &q, 10);
-
-			if (cpu) {
-				for (i = start; i <= end; i++)
-					*cpu++ = i;
-			} else
-				cnt += end - start + 1;
-
-			if (*q == 0) {	/* end of string */
-				p = q;
-				break;
-			}
-			if (*q != ',')
-				goto fail;
-
-			p = q + 1;
-			break;
-		case 0:			/* end of string */
-			if (cpu)
-				*cpu++ = start;
-			else
-				cnt++;
-
-			p = q;
-			break;
-		case ',':		/* gap  */
-			if (cpu)
-				*cpu++ = start;
-			else
-				cnt++;
-
-			p = q + 1;
-			break;
-		}
-	} while (*p != 0);
-
-	if (cpu == NULL) {
-		dtp->dt_conf.numcpus = cnt;
-		dtp->dt_conf.cpuids = dt_zalloc(dtp,
-						cnt * sizeof(processorid_t));
-		cpu = dtp->dt_conf.cpuids;
-		goto again;
-	}
-
-	/* Record the highest CPU id (i.e. the last one seen). */
-	dtp->dt_conf.maxcpuid = *(cpu - 1);
-
-	return;
-
-fail:
-	dtp->dt_conf.numcpus = 0;
-	dtp->dt_conf.maxcpuid = 0;
-	dtp->dt_conf.cpuids = NULL;
-}
-- 
2.26.0




More information about the DTrace-devel mailing list