toptree.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. * NUMA support for s390
  3. *
  4. * A tree structure used for machine topology mangling
  5. *
  6. * Copyright IBM Corp. 2015
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/cpumask.h>
  10. #include <linux/list.h>
  11. #include <linux/list_sort.h>
  12. #include <linux/slab.h>
  13. #include <asm/numa.h>
  14. #include "toptree.h"
  15. /**
  16. * toptree_alloc - Allocate and initialize a new tree node.
  17. * @level: The node's vertical level; level 0 contains the leaves.
  18. * @id: ID number, explicitly not unique beyond scope of node's siblings
  19. *
  20. * Allocate a new tree node and initialize it.
  21. *
  22. * RETURNS:
  23. * Pointer to the new tree node or NULL on error
  24. */
  25. struct toptree *toptree_alloc(int level, int id)
  26. {
  27. struct toptree *res = kzalloc(sizeof(struct toptree), GFP_KERNEL);
  28. if (!res)
  29. return res;
  30. INIT_LIST_HEAD(&res->children);
  31. INIT_LIST_HEAD(&res->sibling);
  32. cpumask_clear(&res->mask);
  33. res->level = level;
  34. res->id = id;
  35. return res;
  36. }
  37. /**
  38. * toptree_remove - Remove a tree node from a tree
  39. * @cand: Pointer to the node to remove
  40. *
  41. * The node is detached from its parent node. The parent node's
  42. * masks will be updated to reflect the loss of the child.
  43. */
  44. static void toptree_remove(struct toptree *cand)
  45. {
  46. struct toptree *oldparent;
  47. list_del_init(&cand->sibling);
  48. oldparent = cand->parent;
  49. cand->parent = NULL;
  50. toptree_update_mask(oldparent);
  51. }
  52. /**
  53. * toptree_free - discard a tree node
  54. * @cand: Pointer to the tree node to discard
  55. *
  56. * Checks if @cand is attached to a parent node. Detaches it
  57. * cleanly using toptree_remove. Possible children are freed
  58. * recursively. In the end @cand itself is freed.
  59. */
  60. void toptree_free(struct toptree *cand)
  61. {
  62. struct toptree *child, *tmp;
  63. if (cand->parent)
  64. toptree_remove(cand);
  65. toptree_for_each_child_safe(child, tmp, cand)
  66. toptree_free(child);
  67. kfree(cand);
  68. }
  69. /**
  70. * toptree_update_mask - Update node bitmasks
  71. * @cand: Pointer to a tree node
  72. *
  73. * The node's cpumask will be updated by combining all children's
  74. * masks. Then toptree_update_mask is called recursively for the
  75. * parent if applicable.
  76. *
  77. * NOTE:
  78. * This must not be called on leaves. If called on a leaf, its
  79. * CPU mask is cleared and lost.
  80. */
  81. void toptree_update_mask(struct toptree *cand)
  82. {
  83. struct toptree *child;
  84. cpumask_clear(&cand->mask);
  85. list_for_each_entry(child, &cand->children, sibling)
  86. cpumask_or(&cand->mask, &cand->mask, &child->mask);
  87. if (cand->parent)
  88. toptree_update_mask(cand->parent);
  89. }
  90. /**
  91. * toptree_insert - Insert a tree node into tree
  92. * @cand: Pointer to the node to insert
  93. * @target: Pointer to the node to which @cand will added as a child
  94. *
  95. * Insert a tree node into a tree. Masks will be updated automatically.
  96. *
  97. * RETURNS:
  98. * 0 on success, -1 if NULL is passed as argument or the node levels
  99. * don't fit.
  100. */
  101. static int toptree_insert(struct toptree *cand, struct toptree *target)
  102. {
  103. if (!cand || !target)
  104. return -1;
  105. if (target->level != (cand->level + 1))
  106. return -1;
  107. list_add_tail(&cand->sibling, &target->children);
  108. cand->parent = target;
  109. toptree_update_mask(target);
  110. return 0;
  111. }
  112. /**
  113. * toptree_move_children - Move all child nodes of a node to a new place
  114. * @cand: Pointer to the node whose children are to be moved
  115. * @target: Pointer to the node to which @cand's children will be attached
  116. *
  117. * Take all child nodes of @cand and move them using toptree_move.
  118. */
  119. static void toptree_move_children(struct toptree *cand, struct toptree *target)
  120. {
  121. struct toptree *child, *tmp;
  122. toptree_for_each_child_safe(child, tmp, cand)
  123. toptree_move(child, target);
  124. }
  125. /**
  126. * toptree_unify - Merge children with same ID
  127. * @cand: Pointer to node whose direct children should be made unique
  128. *
  129. * When mangling the tree it is possible that a node has two or more children
  130. * which have the same ID. This routine merges these children into one and
  131. * moves all children of the merged nodes into the unified node.
  132. */
  133. void toptree_unify(struct toptree *cand)
  134. {
  135. struct toptree *child, *tmp, *cand_copy;
  136. /* Threads cannot be split, cores are not split */
  137. if (cand->level < 2)
  138. return;
  139. cand_copy = toptree_alloc(cand->level, 0);
  140. toptree_for_each_child_safe(child, tmp, cand) {
  141. struct toptree *tmpchild;
  142. if (!cpumask_empty(&child->mask)) {
  143. tmpchild = toptree_get_child(cand_copy, child->id);
  144. toptree_move_children(child, tmpchild);
  145. }
  146. toptree_free(child);
  147. }
  148. toptree_move_children(cand_copy, cand);
  149. toptree_free(cand_copy);
  150. toptree_for_each_child(child, cand)
  151. toptree_unify(child);
  152. }
  153. /**
  154. * toptree_move - Move a node to another context
  155. * @cand: Pointer to the node to move
  156. * @target: Pointer to the node where @cand should go
  157. *
  158. * In the easiest case @cand is exactly on the level below @target
  159. * and will be immediately moved to the target.
  160. *
  161. * If @target's level is not the direct parent level of @cand,
  162. * nodes for the missing levels are created and put between
  163. * @cand and @target. The "stacking" nodes' IDs are taken from
  164. * @cand's parents.
  165. *
  166. * After this it is likely to have redundant nodes in the tree
  167. * which are addressed by means of toptree_unify.
  168. */
  169. void toptree_move(struct toptree *cand, struct toptree *target)
  170. {
  171. struct toptree *stack_target, *real_insert_point, *ptr, *tmp;
  172. if (cand->level + 1 == target->level) {
  173. toptree_remove(cand);
  174. toptree_insert(cand, target);
  175. return;
  176. }
  177. real_insert_point = NULL;
  178. ptr = cand;
  179. stack_target = NULL;
  180. do {
  181. tmp = stack_target;
  182. stack_target = toptree_alloc(ptr->level + 1,
  183. ptr->parent->id);
  184. toptree_insert(tmp, stack_target);
  185. if (!real_insert_point)
  186. real_insert_point = stack_target;
  187. ptr = ptr->parent;
  188. } while (stack_target->level < (target->level - 1));
  189. toptree_remove(cand);
  190. toptree_insert(cand, real_insert_point);
  191. toptree_insert(stack_target, target);
  192. }
  193. /**
  194. * toptree_get_child - Access a tree node's child by its ID
  195. * @cand: Pointer to tree node whose child is to access
  196. * @id: The desired child's ID
  197. *
  198. * @cand's children are searched for a child with matching ID.
  199. * If no match can be found, a new child with the desired ID
  200. * is created and returned.
  201. */
  202. struct toptree *toptree_get_child(struct toptree *cand, int id)
  203. {
  204. struct toptree *child;
  205. toptree_for_each_child(child, cand)
  206. if (child->id == id)
  207. return child;
  208. child = toptree_alloc(cand->level-1, id);
  209. toptree_insert(child, cand);
  210. return child;
  211. }
  212. /**
  213. * toptree_first - Find the first descendant on specified level
  214. * @context: Pointer to tree node whose descendants are to be used
  215. * @level: The level of interest
  216. *
  217. * RETURNS:
  218. * @context's first descendant on the specified level, or NULL
  219. * if there is no matching descendant
  220. */
  221. struct toptree *toptree_first(struct toptree *context, int level)
  222. {
  223. struct toptree *child, *tmp;
  224. if (context->level == level)
  225. return context;
  226. if (!list_empty(&context->children)) {
  227. list_for_each_entry(child, &context->children, sibling) {
  228. tmp = toptree_first(child, level);
  229. if (tmp)
  230. return tmp;
  231. }
  232. }
  233. return NULL;
  234. }
  235. /**
  236. * toptree_next_sibling - Return next sibling
  237. * @cur: Pointer to a tree node
  238. *
  239. * RETURNS:
  240. * If @cur has a parent and is not the last in the parent's children list,
  241. * the next sibling is returned. Or NULL when there are no siblings left.
  242. */
  243. static struct toptree *toptree_next_sibling(struct toptree *cur)
  244. {
  245. if (cur->parent == NULL)
  246. return NULL;
  247. if (cur == list_last_entry(&cur->parent->children,
  248. struct toptree, sibling))
  249. return NULL;
  250. return (struct toptree *) list_next_entry(cur, sibling);
  251. }
  252. /**
  253. * toptree_next - Tree traversal function
  254. * @cur: Pointer to current element
  255. * @context: Pointer to the root node of the tree or subtree to
  256. * be traversed.
  257. * @level: The level of interest.
  258. *
  259. * RETURNS:
  260. * Pointer to the next node on level @level
  261. * or NULL when there is no next node.
  262. */
  263. struct toptree *toptree_next(struct toptree *cur, struct toptree *context,
  264. int level)
  265. {
  266. struct toptree *cur_context, *tmp;
  267. if (!cur)
  268. return NULL;
  269. if (context->level == level)
  270. return NULL;
  271. tmp = toptree_next_sibling(cur);
  272. if (tmp != NULL)
  273. return tmp;
  274. cur_context = cur;
  275. while (cur_context->level < context->level - 1) {
  276. /* Step up */
  277. cur_context = cur_context->parent;
  278. /* Step aside */
  279. tmp = toptree_next_sibling(cur_context);
  280. if (tmp != NULL) {
  281. /* Step down */
  282. tmp = toptree_first(tmp, level);
  283. if (tmp != NULL)
  284. return tmp;
  285. }
  286. }
  287. return NULL;
  288. }
  289. /**
  290. * toptree_count - Count descendants on specified level
  291. * @context: Pointer to node whose descendants are to be considered
  292. * @level: Only descendants on the specified level will be counted
  293. *
  294. * RETURNS:
  295. * Number of descendants on the specified level
  296. */
  297. int toptree_count(struct toptree *context, int level)
  298. {
  299. struct toptree *cur;
  300. int cnt = 0;
  301. toptree_for_each(cur, context, level)
  302. cnt++;
  303. return cnt;
  304. }