1
2
3
4
5
6
7
8
9#include <linux/kernel.h>
10#include <linux/cpumask.h>
11#include <linux/list.h>
12#include <linux/list_sort.h>
13#include <linux/slab.h>
14#include <asm/numa.h>
15
16#include "toptree.h"
17
18
19
20
21
22
23
24
25
26
27
28struct toptree *toptree_alloc(int level, int id)
29{
30 struct toptree *res = kzalloc(sizeof(struct toptree), GFP_KERNEL);
31
32 if (!res)
33 return res;
34
35 INIT_LIST_HEAD(&res->children);
36 INIT_LIST_HEAD(&res->sibling);
37 cpumask_clear(&res->mask);
38 res->level = level;
39 res->id = id;
40 return res;
41}
42
43
44
45
46
47
48
49
50static void toptree_remove(struct toptree *cand)
51{
52 struct toptree *oldparent;
53
54 list_del_init(&cand->sibling);
55 oldparent = cand->parent;
56 cand->parent = NULL;
57 toptree_update_mask(oldparent);
58}
59
60
61
62
63
64
65
66
67
68void toptree_free(struct toptree *cand)
69{
70 struct toptree *child, *tmp;
71
72 if (cand->parent)
73 toptree_remove(cand);
74 toptree_for_each_child_safe(child, tmp, cand)
75 toptree_free(child);
76 kfree(cand);
77}
78
79
80
81
82
83
84
85
86
87
88
89
90
91void toptree_update_mask(struct toptree *cand)
92{
93 struct toptree *child;
94
95 cpumask_clear(&cand->mask);
96 list_for_each_entry(child, &cand->children, sibling)
97 cpumask_or(&cand->mask, &cand->mask, &child->mask);
98 if (cand->parent)
99 toptree_update_mask(cand->parent);
100}
101
102
103
104
105
106
107
108
109
110
111
112
113static int toptree_insert(struct toptree *cand, struct toptree *target)
114{
115 if (!cand || !target)
116 return -1;
117 if (target->level != (cand->level + 1))
118 return -1;
119 list_add_tail(&cand->sibling, &target->children);
120 cand->parent = target;
121 toptree_update_mask(target);
122 return 0;
123}
124
125
126
127
128
129
130
131
132static void toptree_move_children(struct toptree *cand, struct toptree *target)
133{
134 struct toptree *child, *tmp;
135
136 toptree_for_each_child_safe(child, tmp, cand)
137 toptree_move(child, target);
138}
139
140
141
142
143
144
145
146
147
148void toptree_unify(struct toptree *cand)
149{
150 struct toptree *child, *tmp, *cand_copy;
151
152
153 if (cand->level < 2)
154 return;
155
156 cand_copy = toptree_alloc(cand->level, 0);
157 toptree_for_each_child_safe(child, tmp, cand) {
158 struct toptree *tmpchild;
159
160 if (!cpumask_empty(&child->mask)) {
161 tmpchild = toptree_get_child(cand_copy, child->id);
162 toptree_move_children(child, tmpchild);
163 }
164 toptree_free(child);
165 }
166 toptree_move_children(cand_copy, cand);
167 toptree_free(cand_copy);
168
169 toptree_for_each_child(child, cand)
170 toptree_unify(child);
171}
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189void toptree_move(struct toptree *cand, struct toptree *target)
190{
191 struct toptree *stack_target, *real_insert_point, *ptr, *tmp;
192
193 if (cand->level + 1 == target->level) {
194 toptree_remove(cand);
195 toptree_insert(cand, target);
196 return;
197 }
198
199 real_insert_point = NULL;
200 ptr = cand;
201 stack_target = NULL;
202
203 do {
204 tmp = stack_target;
205 stack_target = toptree_alloc(ptr->level + 1,
206 ptr->parent->id);
207 toptree_insert(tmp, stack_target);
208 if (!real_insert_point)
209 real_insert_point = stack_target;
210 ptr = ptr->parent;
211 } while (stack_target->level < (target->level - 1));
212
213 toptree_remove(cand);
214 toptree_insert(cand, real_insert_point);
215 toptree_insert(stack_target, target);
216}
217
218
219
220
221
222
223
224
225
226
227struct toptree *toptree_get_child(struct toptree *cand, int id)
228{
229 struct toptree *child;
230
231 toptree_for_each_child(child, cand)
232 if (child->id == id)
233 return child;
234 child = toptree_alloc(cand->level-1, id);
235 toptree_insert(child, cand);
236 return child;
237}
238
239
240
241
242
243
244
245
246
247
248struct toptree *toptree_first(struct toptree *context, int level)
249{
250 struct toptree *child, *tmp;
251
252 if (context->level == level)
253 return context;
254
255 if (!list_empty(&context->children)) {
256 list_for_each_entry(child, &context->children, sibling) {
257 tmp = toptree_first(child, level);
258 if (tmp)
259 return tmp;
260 }
261 }
262 return NULL;
263}
264
265
266
267
268
269
270
271
272
273static struct toptree *toptree_next_sibling(struct toptree *cur)
274{
275 if (cur->parent == NULL)
276 return NULL;
277
278 if (cur == list_last_entry(&cur->parent->children,
279 struct toptree, sibling))
280 return NULL;
281 return (struct toptree *) list_next_entry(cur, sibling);
282}
283
284
285
286
287
288
289
290
291
292
293
294
295struct toptree *toptree_next(struct toptree *cur, struct toptree *context,
296 int level)
297{
298 struct toptree *cur_context, *tmp;
299
300 if (!cur)
301 return NULL;
302
303 if (context->level == level)
304 return NULL;
305
306 tmp = toptree_next_sibling(cur);
307 if (tmp != NULL)
308 return tmp;
309
310 cur_context = cur;
311 while (cur_context->level < context->level - 1) {
312
313 cur_context = cur_context->parent;
314
315 tmp = toptree_next_sibling(cur_context);
316 if (tmp != NULL) {
317
318 tmp = toptree_first(tmp, level);
319 if (tmp != NULL)
320 return tmp;
321 }
322 }
323 return NULL;
324}
325
326
327
328
329
330
331
332
333
334int toptree_count(struct toptree *context, int level)
335{
336 struct toptree *cur;
337 int cnt = 0;
338
339 toptree_for_each(cur, context, level)
340 cnt++;
341 return cnt;
342}
343