1#include <console/panic.h>
2#include <console/printf.h>
3#include <global.h>
4#include <kassert.h>
5#include <math/sort.h>
6#include <mem/alloc.h>
7#include <mem/numa.h>
8#include <string.h>
9
10void numa_dump(void) {
11 size_t n = global.numa_node_count;
12 if (!n) {
13 log_msg(LOG_WARN, "No NUMA nodes detected");
14 return;
15 }
16
17 log_msg(LOG_INFO, "NUMA distance matrix (%zu nodes):", n);
18 log_msg(LOG_INFO, "Displayed as distance (relative distance):", n);
19
20 printf(format: " ");
21 for (size_t j = 0; j < n; j++)
22 printf(format: "%11zu", j);
23 printf(format: "\n");
24
25 for (size_t i = 0; i < n; i++) {
26 printf(format: "%4zu: ", i);
27 for (size_t j = 0; j < n; j++) {
28 printf(format: "%4u (%4u)", global.numa_nodes[i].distance[j],
29 global.numa_nodes[i].rel_dists[j]);
30 }
31 printf(format: "\n");
32 }
33}
34
35static int cmp(const void *a, const void *b) {
36 return (*(uint8_t *) a) - (*(uint8_t *) b);
37}
38
39static uint8_t idx_of_val(uint8_t *buf, size_t len, size_t search_for) {
40 for (size_t i = 0; i < len; i++)
41 if (buf[i] == search_for)
42 return i;
43
44 kassert_unreachable("invalid search_for or buffer");
45}
46
47void numa_construct_relative_distances(struct numa_node *node) {
48 node->rel_dists = kmalloc(node->distances_cnt, ALLOC_FLAGS_ZERO);
49 uint8_t *tmp = kmalloc(node->distances_cnt, ALLOC_FLAGS_ZERO);
50 node->nodes_by_distance = kmalloc(node->distances_cnt, ALLOC_FLAGS_ZERO);
51 if (!node->rel_dists || !tmp || !node->nodes_by_distance)
52 panic("could not allocate numa relative distances");
53
54 /* we copy the distance array into the temporary array and
55 * sort it. then, for each distance in the distance array,
56 * we iterate through the temporary array and find its
57 * position. this position is then set as the distance's rel_dist */
58 memcpy(tmp, node->distance, node->distances_cnt);
59 qsort(a: tmp, n: node->distances_cnt, es: sizeof(uint8_t), cmp);
60
61 for (size_t i = 0; i < node->distances_cnt; i++) {
62 uint8_t idx = idx_of_val(buf: tmp, len: node->distances_cnt, search_for: node->distance[i]);
63 node->rel_dists[i] = idx;
64 node->nodes_by_distance[idx] = i;
65 }
66
67 kfree(tmp);
68}
69