| 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 | |
| 10 | void 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 | |
| 35 | static int cmp(const void *a, const void *b) { |
| 36 | return (*(uint8_t *) a) - (*(uint8_t *) b); |
| 37 | } |
| 38 | |
| 39 | static 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 | |
| 47 | void 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 | |