~laumann/drawcpu

7687b3978ab7363d51470e75a47def1164c80905 — Thomas Bracht Laumann Jespersen 6 months ago 96643cf
Identify shared caches

For drawing a picture of caches, we need to know which of them are
shared with which.

Initially, let us just build a deduplicated list of existing caches, and
set up some knowledge structure around caches being shared.
1 files changed, 73 insertions(+), 14 deletions(-)

M main.c
M main.c => main.c +73 -14
@@ 69,9 69,9 @@ isindex(const struct dirent *d)
}

struct cpucache {
	char *type;
	uint level;
	uint shared_cpu_map;
	char *type;
	char *size;
};
typedef struct cpucache cpucache;


@@ 80,16 80,60 @@ struct cpu {
	uint n;
};

int cpucachecmp(const cpucache *a, const cpucache *b) {
	int c;

	c = (int)(a->level) - (int)(b->level);
	if (c)
		return c;

	c = (int)(a->shared_cpu_map) - (int)(b->shared_cpu_map);
	if (c)
		return c;

	c = strcmp(a->type, b->type);
	if (c)
		return c;
	c = strcmp(a->size, b->size);
	return c;
}

/* The shared_cpu_map is a bitmap that shows which CPUs use a given cache... */

struct cpucaches {
	size_t len;
	size_t cap;
	cpucache *caches;
};

struct cpucaches *cpucachesnew() {
	struct cpucaches *c;

	c = malloc(sizeof(struct cpucaches));
	if (!c)
		return c;

	c->caches = calloc(8, sizeof(cpucache));
	if (!c->caches) {
		free(c);
		return NULL;
	}
	c->len = 0;
	c->cap = 8;

	return c;
}

int
listcaches(int cpu)
listcaches(int cpu, struct cpucaches *cs)
{
	char f[512];
	char buf[32];
	struct dirent **dirs;
	int n;
	int i;
	int j;
	int err;

	cpucache c;

	err = 0;


@@ 104,10 148,6 @@ listcaches(int cpu)
	}

	for (i = 0; i < n; i++) {
		/* We need to open "/type", "/level", "/shared_cpu_map", "/size"
		and store the results */

		/* index<n>/type */
		sprintf(f, "/sys/devices/system/cpu/cpu%u/cache/%s/type", cpu, dirs[i]->d_name);

		err = readfileto(f, buf, sizeof(buf));


@@ 120,7 160,6 @@ listcaches(int cpu)
			break;
		}

		/* index<n>/level */
		sprintf(f, "/sys/devices/system/cpu/cpu%u/cache/%s/level", cpu, dirs[i]->d_name);

		err = readfileto(f, buf, sizeof(buf));


@@ 128,7 167,6 @@ listcaches(int cpu)
			break;
		c.level = strtol(buf, NULL, 10); /* XXX Return value "man strtol" */

		/* index<n>/level */
		sprintf(f, "/sys/devices/system/cpu/cpu%u/cache/%s/shared_cpu_map", cpu, dirs[i]->d_name);

		err = readfileto(f, buf, sizeof(buf));


@@ 136,7 174,6 @@ listcaches(int cpu)
			break;
		c.shared_cpu_map = strtol(buf, NULL, 16); /* XXX Return value "man strtol" */

		/* index<n>/size */
		sprintf(f, "/sys/devices/system/cpu/cpu%u/cache/%s/size", cpu, dirs[i]->d_name);
		err = readfileto(f, buf, sizeof(buf));
		if (err)


@@ 147,9 184,26 @@ listcaches(int cpu)
			perror(DRAWCPU);
			break;
		}
		printf("type=%-14s level=%u shared_cpu_map=%2u size=%s\n", c.type, c.level, c.shared_cpu_map, c.size);
		free(c.type);
		free(c.size);
		/* Alright, got all the things - look for an existing one */

		for (j = 0; j < cs->len; j++)
			if (!cpucachecmp(&cs->caches[j], &c))
				break;

		if (j == cs->len) {
			printf("Adding new cache @ %lu!\n", cs->len);
			printf("type=%-14s level=%u shared_cpu_map=%02x size=%s\n", c.type, c.level, c.shared_cpu_map, c.size);
			cs->caches[j].level = c.level;
			cs->caches[j].shared_cpu_map = c.shared_cpu_map;
			cs->caches[j].type = c.type;
			cs->caches[j].size = c.size;
			cs->len++;
		} else {
			printf("Found existing one!\n");
			free(c.type);
			free(c.size);
		}

	}
	/* Free the dir entries */
	for (i = 0; i < n; i++)


@@ 164,6 218,11 @@ main(int argc, char *argv[])
	uint lo, hi;
	int err;
	int cpu;
	struct cpucaches *caches;

	caches = cpucachesnew();
	if (!caches)
		exit(1);

	err = getcpus(&lo, &hi);
	if (err)


@@ 172,6 231,6 @@ main(int argc, char *argv[])
	printf("err=%d lo=%u hi=%u\n", err, lo, hi);
	for (cpu = lo; cpu <= hi; cpu++) {
		printf(">>> CPU%u\n", cpu);
		listcaches(cpu);
		listcaches(cpu, caches);
	}
}