tools/perf/util/cpumap.c

Source file repositories/reference/linux-study-clean/tools/perf/util/cpumap.c

File Facts

System
Linux kernel
Corpus path
tools/perf/util/cpumap.c
Extension
.c
Size
17213 bytes
Lines
774
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

if (data->cpus_data.cpu[i] == (u16) -1) {
			RC_CHK_ACCESS(map)->map[i].cpu = -1;
		} else if (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;
		}
	}

	return map;
}

static struct perf_cpu_map *cpu_map__from_mask(const struct perf_record_cpu_map_data *data)
{
	DECLARE_BITMAP(local_copy, 64);
	int weight = 0, mask_nr = data->mask32_data.nr;
	struct perf_cpu_map *map;

	for (int i = 0; i < mask_nr; i++) {
		perf_record_cpu_map_data__read_one_mask(data, i, local_copy);
		weight += bitmap_weight(local_copy, 64);
	}

	map = perf_cpu_map__empty_new(weight);
	if (!map)
		return NULL;

	for (int i = 0, j = 0; i < mask_nr; i++) {
		int cpus_per_i = (i * data->mask32_data.long_size  * BITS_PER_BYTE);
		int cpu;

		perf_record_cpu_map_data__read_one_mask(data, i, local_copy);
		for_each_set_bit(cpu, local_copy, 64) {
			if (cpu + cpus_per_i < INT16_MAX) {
				RC_CHK_ACCESS(map)->map[j++].cpu = cpu + cpus_per_i;
			} else {
				pr_err("Invalid cpumap entry %d\n", cpu + cpus_per_i);
				perf_cpu_map__put(map);
				return NULL;
			}
		}
	}
	return map;

}

static struct perf_cpu_map *cpu_map__from_range(const struct perf_record_cpu_map_data *data)
{
	struct perf_cpu_map *map;
	unsigned int i = 0;

	map = perf_cpu_map__empty_new(data->range_cpu_data.end_cpu -
				data->range_cpu_data.start_cpu + 1 + data->range_cpu_data.any_cpu);
	if (!map)
		return NULL;

	if (data->range_cpu_data.any_cpu)
		RC_CHK_ACCESS(map)->map[i++].cpu = -1;

	for (int cpu = data->range_cpu_data.start_cpu; cpu <= data->range_cpu_data.end_cpu;
	     i++, cpu++) {
		if (cpu < INT16_MAX) {
			RC_CHK_ACCESS(map)->map[i].cpu = cpu;
		} else {
			pr_err("Invalid cpumap entry %d\n", cpu);
			perf_cpu_map__put(map);
			return NULL;
		}
	}

	return map;
}

struct perf_cpu_map *cpu_map__new_data(const struct perf_record_cpu_map_data *data)
{
	switch (data->type) {
	case PERF_CPU_MAP__CPUS:
		return cpu_map__from_entries(data);
	case PERF_CPU_MAP__MASK:
		return cpu_map__from_mask(data);
	case PERF_CPU_MAP__RANGE_CPUS:
		return cpu_map__from_range(data);
	default:
		pr_err("cpu_map__new_data unknown type %d\n", data->type);
		return NULL;
	}
}

Annotation

Implementation Notes