staticstruct perf_cpu max_cpu_num; staticstruct perf_cpu max_present_cpu_num; staticint max_node_num; /** * The numa node X as read from /sys/devices/system/node/nodeX indexed by the * CPU number.
*/ staticint *cpunode_map;
bool perf_record_cpu_map_data__test_bit(int i, conststruct perf_record_cpu_map_data *data)
{ int bit_word32 = i / 32;
__u32 bit_mask32 = 1U << (i & 31); int bit_word64 = i / 64;
__u64 bit_mask64 = ((__u64)1) << (i & 63);
/* Read ith mask value from data into the given 64-bit sized bitmap */ staticvoid perf_record_cpu_map_data__read_one_mask(conststruct perf_record_cpu_map_data *data, int i, unsignedlong *bitmap)
{ #if __SIZEOF_LONG__ == 8 if (data->mask32_data.long_size == 4)
bitmap[0] = data->mask32_data.mask[i]; else
bitmap[0] = data->mask64_data.mask[i]; #else if (data->mask32_data.long_size == 4) {
bitmap[0] = data->mask32_data.mask[i];
bitmap[1] = 0;
} else { #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
bitmap[0] = (unsignedlong)(data->mask64_data.mask[i] >> 32);
bitmap[1] = (unsignedlong)data->mask64_data.mask[i]; #else
bitmap[0] = (unsignedlong)data->mask64_data.mask[i];
bitmap[1] = (unsignedlong)(data->mask64_data.mask[i] >> 32); #endif
} #endif
} staticstruct perf_cpu_map *cpu_map__from_entries(conststruct perf_record_cpu_map_data *data)
{ struct perf_cpu_map *map;
map = perf_cpu_map__empty_new(data->cpus_data.nr); if (!map) return NULL;
for (unsignedint i = 0; i < data->cpus_data.nr; i++) { /* * Special treatment for -1, which is not real cpu number, * and we need to use (int) -1 to initialize map[i], * otherwise it would become 65535.
*/ if (data->cpus_data.cpu[i] == (u16) -1) {
RC_CHK_ACCESS(map)->map[i].cpu = -1;
} elseif (data->cpus_data.cpu[i] < INT16_MAX) {
RC_CHK_ACCESS(map)->map[i].cpu = (int16_t) data->cpus_data.cpu[i];
} else {
pr_err("Invalid cpumap entry %u\n", data->cpus_data.cpu[i]);
perf_cpu_map__put(map); return NULL;
}
}
die = cpu__get_die_id(cpu); /* There is no die_id on legacy system. */ if (die < 0)
die = 0;
/* * die_id is relative to socket, so start * with the socket ID and then add die to * make a unique ID.
*/
id = aggr_cpu_id__socket(cpu, data); if (aggr_cpu_id__is_empty(&id)) return id;
id.die = die; return id;
}
int cpu__get_cluster_id(struct perf_cpu cpu)
{ int value, ret = cpu__get_topology_int(cpu.cpu, "cluster_id", &value);
/* aggr_cpu_id__die returns a struct with socket die, and cluster set. */
id = aggr_cpu_id__cluster(cpu, data); if (aggr_cpu_id__is_empty(&id)) return id;
/* * core_id is relative to socket and die, we need a global id. * So we combine the result from cpu_map__get_die with the core id
*/
id.core = core; return id;
/* it always aggregates to the cpu 0 */
cpu.cpu = 0;
id.cpu = cpu; return id;
}
/* setup simple routines to easily access node numbers given a cpu number */ staticint 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 */ staticvoid set_max_cpu_num(void)
{ constchar *mnt; char path[PATH_MAX]; int max, ret = -1;
/* set up default */
max_cpu_num.cpu = 4096;
max_present_cpu_num.cpu = 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); if (ret) goto out;
max_cpu_num.cpu = max;
/* get the highest present cpu number for a sparse allocation */
ret = snprintf(path, PATH_MAX, "%s/devices/system/cpu/present", 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);
if (!ret && max > INT16_MAX) {
pr_err("Read out of bounds max cpus of %d\n", max);
ret = -1;
} if (!ret)
max_present_cpu_num.cpu = (int16_t)max;
out: if (ret)
pr_err("Failed to read max cpus, using default of %d\n", max_cpu_num.cpu);
}
/* Determine highest possible node in the system for sparse allocation */ staticvoid set_max_node_num(void)
{ constchar *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);
}
int cpu__max_node(void)
{ if (unlikely(!max_node_num))
set_max_node_num();
return max_node_num;
}
struct perf_cpu cpu__max_cpu(void)
{ if (unlikely(!max_cpu_num.cpu))
set_max_cpu_num();
return max_cpu_num;
}
struct perf_cpu cpu__max_present_cpu(void)
{ if (unlikely(!max_present_cpu_num.cpu))
set_max_cpu_num();
return max_present_cpu_num;
}
int cpu__get_node(struct perf_cpu cpu)
{ if (unlikely(cpunode_map == NULL)) {
pr_debug("cpu_map not initialized\n"); return -1;
}
for (i = 0; i < max_cpu_num.cpu; i++)
cpunode_map[i] = -1;
return 0;
}
int cpu__setup_cpunode_map(void)
{ struct dirent *dent1, *dent2;
DIR *dir1, *dir2; unsignedint cpu, mem; char buf[PATH_MAX]; char path[PATH_MAX]; constchar *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;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.