diff options
Diffstat (limited to 'tools/perf/util/cpumap.c')
| -rw-r--r-- | tools/perf/util/cpumap.c | 166 | 
1 files changed, 163 insertions, 3 deletions
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index beb8cf9f997..c4e55b71010 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -1,5 +1,5 @@  #include "util.h" -#include "sysfs.h" +#include <api/fs/fs.h>  #include "../perf.h"  #include "cpumap.h"  #include <assert.h> @@ -216,7 +216,7 @@ int cpu_map__get_socket(struct cpu_map *map, int idx)  	cpu = map->map[idx]; -	mnt = sysfs_find_mountpoint(); +	mnt = sysfs__mountpoint();  	if (!mnt)  		return -1; @@ -279,7 +279,7 @@ int cpu_map__get_core(struct cpu_map *map, int idx)  	cpu = map->map[idx]; -	mnt = sysfs_find_mountpoint(); +	mnt = sysfs__mountpoint();  	if (!mnt)  		return -1; @@ -317,3 +317,163 @@ int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep)  {  	return cpu_map__build_map(cpus, corep, cpu_map__get_core);  } + +/* setup simple routines to easily access node numbers given a cpu number */ +static int get_max_num(char *path, int *max) +{ +	size_t num; +	char *buf; +	int err = 0; + +	if (filename__read_str(path, &buf, &num)) +		return -1; + +	buf[num] = '\0'; + +	/* start on the right, to find highest node num */ +	while (--num) { +		if ((buf[num] == ',') || (buf[num] == '-')) { +			num++; +			break; +		} +	} +	if (sscanf(&buf[num], "%d", max) < 1) { +		err = -1; +		goto out; +	} + +	/* convert from 0-based to 1-based */ +	(*max)++; + +out: +	free(buf); +	return err; +} + +/* Determine highest possible cpu in the system for sparse allocation */ +static void set_max_cpu_num(void) +{ +	const char *mnt; +	char path[PATH_MAX]; +	int ret = -1; + +	/* set up default */ +	max_cpu_num = 4096; + +	mnt = sysfs__mountpoint(); +	if (!mnt) +		goto out; + +	/* get the highest possible cpu number for a sparse allocation */ +	ret = snprintf(path, PATH_MAX, "%s/devices/system/cpu/possible", mnt); +	if (ret == PATH_MAX) { +		pr_err("sysfs path crossed PATH_MAX(%d) size\n", PATH_MAX); +		goto out; +	} + +	ret = get_max_num(path, &max_cpu_num); + +out: +	if (ret) +		pr_err("Failed to read max cpus, using default of %d\n", max_cpu_num); +} + +/* Determine highest possible node in the system for sparse allocation */ +static void set_max_node_num(void) +{ +	const char *mnt; +	char path[PATH_MAX]; +	int ret = -1; + +	/* set up default */ +	max_node_num = 8; + +	mnt = sysfs__mountpoint(); +	if (!mnt) +		goto out; + +	/* get the highest possible cpu number for a sparse allocation */ +	ret = snprintf(path, PATH_MAX, "%s/devices/system/node/possible", mnt); +	if (ret == PATH_MAX) { +		pr_err("sysfs path crossed PATH_MAX(%d) size\n", PATH_MAX); +		goto out; +	} + +	ret = get_max_num(path, &max_node_num); + +out: +	if (ret) +		pr_err("Failed to read max nodes, using default of %d\n", max_node_num); +} + +static int init_cpunode_map(void) +{ +	int i; + +	set_max_cpu_num(); +	set_max_node_num(); + +	cpunode_map = calloc(max_cpu_num, sizeof(int)); +	if (!cpunode_map) { +		pr_err("%s: calloc failed\n", __func__); +		return -1; +	} + +	for (i = 0; i < max_cpu_num; i++) +		cpunode_map[i] = -1; + +	return 0; +} + +int cpu__setup_cpunode_map(void) +{ +	struct dirent *dent1, *dent2; +	DIR *dir1, *dir2; +	unsigned int cpu, mem; +	char buf[PATH_MAX]; +	char path[PATH_MAX]; +	const char *mnt; +	int n; + +	/* initialize globals */ +	if (init_cpunode_map()) +		return -1; + +	mnt = sysfs__mountpoint(); +	if (!mnt) +		return 0; + +	n = snprintf(path, PATH_MAX, "%s/devices/system/node", mnt); +	if (n == PATH_MAX) { +		pr_err("sysfs path crossed PATH_MAX(%d) size\n", PATH_MAX); +		return -1; +	} + +	dir1 = opendir(path); +	if (!dir1) +		return 0; + +	/* walk tree and setup map */ +	while ((dent1 = readdir(dir1)) != NULL) { +		if (dent1->d_type != DT_DIR || sscanf(dent1->d_name, "node%u", &mem) < 1) +			continue; + +		n = snprintf(buf, PATH_MAX, "%s/%s", path, dent1->d_name); +		if (n == PATH_MAX) { +			pr_err("sysfs path crossed PATH_MAX(%d) size\n", PATH_MAX); +			continue; +		} + +		dir2 = opendir(buf); +		if (!dir2) +			continue; +		while ((dent2 = readdir(dir2)) != NULL) { +			if (dent2->d_type != DT_LNK || sscanf(dent2->d_name, "cpu%u", &cpu) < 1) +				continue; +			cpunode_map[cpu] = mem; +		} +		closedir(dir2); +	} +	closedir(dir1); +	return 0; +}  | 
