1
2
3
4
5
6
7
8
9
10
11
12#define vm_avl_key vm_end
13#define vm_avl_key_t unsigned long
14
15
16
17
18
19
20
21
22
23
24
25
26#define avl_maxheight 41
27#define heightof(tree) ((tree) == vm_avl_empty ? 0 : (tree)->vm_avl_height)
28
29
30
31
32
33
34
35
36#ifdef DEBUG_AVL
37
38
39static void avl_neighbours (struct vm_area_struct * node, struct vm_area_struct * tree, struct vm_area_struct ** to_the_left, struct vm_area_struct ** to_the_right)
40{
41 vm_avl_key_t key = node->vm_avl_key;
42
43 *to_the_left = *to_the_right = NULL;
44 for (;;) {
45 if (tree == vm_avl_empty) {
46 printk("avl_neighbours: node not found in the tree\n");
47 return;
48 }
49 if (key == tree->vm_avl_key)
50 break;
51 if (key < tree->vm_avl_key) {
52 *to_the_right = tree;
53 tree = tree->vm_avl_left;
54 } else {
55 *to_the_left = tree;
56 tree = tree->vm_avl_right;
57 }
58 }
59 if (tree != node) {
60 printk("avl_neighbours: node not exactly found in the tree\n");
61 return;
62 }
63 if (tree->vm_avl_left != vm_avl_empty) {
64 struct vm_area_struct * node;
65 for (node = tree->vm_avl_left; node->vm_avl_right != vm_avl_empty; node = node->vm_avl_right)
66 continue;
67 *to_the_left = node;
68 }
69 if (tree->vm_avl_right != vm_avl_empty) {
70 struct vm_area_struct * node;
71 for (node = tree->vm_avl_right; node->vm_avl_left != vm_avl_empty; node = node->vm_avl_left)
72 continue;
73 *to_the_right = node;
74 }
75 if ((*to_the_left && ((*to_the_left)->vm_next != node)) || (node->vm_next != *to_the_right))
76 printk("avl_neighbours: tree inconsistent with list\n");
77}
78
79#endif
80
81
82
83
84
85
86
87static void avl_rebalance (struct vm_area_struct *** nodeplaces_ptr, int count)
88{
89 for ( ; count > 0 ; count--) {
90 struct vm_area_struct ** nodeplace = *--nodeplaces_ptr;
91 struct vm_area_struct * node = *nodeplace;
92 struct vm_area_struct * nodeleft = node->vm_avl_left;
93 struct vm_area_struct * noderight = node->vm_avl_right;
94 int heightleft = heightof(nodeleft);
95 int heightright = heightof(noderight);
96 if (heightright + 1 < heightleft) {
97
98
99
100
101
102 struct vm_area_struct * nodeleftleft = nodeleft->vm_avl_left;
103 struct vm_area_struct * nodeleftright = nodeleft->vm_avl_right;
104 int heightleftright = heightof(nodeleftright);
105 if (heightof(nodeleftleft) >= heightleftright) {
106
107
108
109
110
111
112
113 node->vm_avl_left = nodeleftright; nodeleft->vm_avl_right = node;
114 nodeleft->vm_avl_height = 1 + (node->vm_avl_height = 1 + heightleftright);
115 *nodeplace = nodeleft;
116 } else {
117
118
119
120
121
122
123
124
125
126 nodeleft->vm_avl_right = nodeleftright->vm_avl_left;
127 node->vm_avl_left = nodeleftright->vm_avl_right;
128 nodeleftright->vm_avl_left = nodeleft;
129 nodeleftright->vm_avl_right = node;
130 nodeleft->vm_avl_height = node->vm_avl_height = heightleftright;
131 nodeleftright->vm_avl_height = heightleft;
132 *nodeplace = nodeleftright;
133 }
134 }
135 else if (heightleft + 1 < heightright) {
136
137 struct vm_area_struct * noderightright = noderight->vm_avl_right;
138 struct vm_area_struct * noderightleft = noderight->vm_avl_left;
139 int heightrightleft = heightof(noderightleft);
140 if (heightof(noderightright) >= heightrightleft) {
141 node->vm_avl_right = noderightleft; noderight->vm_avl_left = node;
142 noderight->vm_avl_height = 1 + (node->vm_avl_height = 1 + heightrightleft);
143 *nodeplace = noderight;
144 } else {
145 noderight->vm_avl_left = noderightleft->vm_avl_right;
146 node->vm_avl_right = noderightleft->vm_avl_left;
147 noderightleft->vm_avl_right = noderight;
148 noderightleft->vm_avl_left = node;
149 noderight->vm_avl_height = node->vm_avl_height = heightrightleft;
150 noderightleft->vm_avl_height = heightright;
151 *nodeplace = noderightleft;
152 }
153 }
154 else {
155 int height = (heightleft<heightright ? heightright : heightleft) + 1;
156 if (height == node->vm_avl_height)
157 break;
158 node->vm_avl_height = height;
159 }
160 }
161}
162
163
164static inline void avl_insert (struct vm_area_struct * new_node, struct vm_area_struct ** ptree)
165{
166 vm_avl_key_t key = new_node->vm_avl_key;
167 struct vm_area_struct ** nodeplace = ptree;
168 struct vm_area_struct ** stack[avl_maxheight];
169 int stack_count = 0;
170 struct vm_area_struct *** stack_ptr = &stack[0];
171 for (;;) {
172 struct vm_area_struct * node = *nodeplace;
173 if (node == vm_avl_empty)
174 break;
175 *stack_ptr++ = nodeplace; stack_count++;
176 if (key < node->vm_avl_key)
177 nodeplace = &node->vm_avl_left;
178 else
179 nodeplace = &node->vm_avl_right;
180 }
181 new_node->vm_avl_left = vm_avl_empty;
182 new_node->vm_avl_right = vm_avl_empty;
183 new_node->vm_avl_height = 1;
184 *nodeplace = new_node;
185 avl_rebalance(stack_ptr,stack_count);
186}
187
188
189
190
191static inline void avl_insert_neighbours (struct vm_area_struct * new_node, struct vm_area_struct ** ptree,
192 struct vm_area_struct ** to_the_left, struct vm_area_struct ** to_the_right)
193{
194 vm_avl_key_t key = new_node->vm_avl_key;
195 struct vm_area_struct ** nodeplace = ptree;
196 struct vm_area_struct ** stack[avl_maxheight];
197 int stack_count = 0;
198 struct vm_area_struct *** stack_ptr = &stack[0];
199 *to_the_left = *to_the_right = NULL;
200 for (;;) {
201 struct vm_area_struct * node = *nodeplace;
202 if (node == vm_avl_empty)
203 break;
204 *stack_ptr++ = nodeplace; stack_count++;
205 if (key < node->vm_avl_key) {
206 *to_the_right = node;
207 nodeplace = &node->vm_avl_left;
208 } else {
209 *to_the_left = node;
210 nodeplace = &node->vm_avl_right;
211 }
212 }
213 new_node->vm_avl_left = vm_avl_empty;
214 new_node->vm_avl_right = vm_avl_empty;
215 new_node->vm_avl_height = 1;
216 *nodeplace = new_node;
217 avl_rebalance(stack_ptr,stack_count);
218}
219
220
221static void avl_remove (struct vm_area_struct * node_to_delete, struct vm_area_struct ** ptree)
222{
223 vm_avl_key_t key = node_to_delete->vm_avl_key;
224 struct vm_area_struct ** nodeplace = ptree;
225 struct vm_area_struct ** stack[avl_maxheight];
226 int stack_count = 0;
227 struct vm_area_struct *** stack_ptr = &stack[0];
228 struct vm_area_struct ** nodeplace_to_delete;
229 for (;;) {
230 struct vm_area_struct * node = *nodeplace;
231#ifdef DEBUG_AVL
232 if (node == vm_avl_empty) {
233
234 printk("avl_remove: node to delete not found in tree\n");
235 return;
236 }
237#endif
238 *stack_ptr++ = nodeplace; stack_count++;
239 if (key == node->vm_avl_key)
240 break;
241 if (key < node->vm_avl_key)
242 nodeplace = &node->vm_avl_left;
243 else
244 nodeplace = &node->vm_avl_right;
245 }
246 nodeplace_to_delete = nodeplace;
247
248 if (node_to_delete->vm_avl_left == vm_avl_empty) {
249 *nodeplace_to_delete = node_to_delete->vm_avl_right;
250 stack_ptr--; stack_count--;
251 } else {
252 struct vm_area_struct *** stack_ptr_to_delete = stack_ptr;
253 struct vm_area_struct ** nodeplace = &node_to_delete->vm_avl_left;
254 struct vm_area_struct * node;
255 for (;;) {
256 node = *nodeplace;
257 if (node->vm_avl_right == vm_avl_empty)
258 break;
259 *stack_ptr++ = nodeplace; stack_count++;
260 nodeplace = &node->vm_avl_right;
261 }
262 *nodeplace = node->vm_avl_left;
263
264 node->vm_avl_left = node_to_delete->vm_avl_left;
265 node->vm_avl_right = node_to_delete->vm_avl_right;
266 node->vm_avl_height = node_to_delete->vm_avl_height;
267 *nodeplace_to_delete = node;
268 *stack_ptr_to_delete = &node->vm_avl_left;
269 }
270 avl_rebalance(stack_ptr,stack_count);
271}
272
273#ifdef DEBUG_AVL
274
275
276static void printk_list (struct vm_area_struct * vma)
277{
278 printk("[");
279 while (vma) {
280 printk("%08lX-%08lX", vma->vm_start, vma->vm_end);
281 vma = vma->vm_next;
282 if (!vma)
283 break;
284 printk(" ");
285 }
286 printk("]");
287}
288
289
290static void printk_avl (struct vm_area_struct * tree)
291{
292 if (tree != vm_avl_empty) {
293 printk("(");
294 if (tree->vm_avl_left != vm_avl_empty) {
295 printk_avl(tree->vm_avl_left);
296 printk("<");
297 }
298 printk("%08lX-%08lX", tree->vm_start, tree->vm_end);
299 if (tree->vm_avl_right != vm_avl_empty) {
300 printk(">");
301 printk_avl(tree->vm_avl_right);
302 }
303 printk(")");
304 }
305}
306
307static char *avl_check_point = "somewhere";
308
309
310static void avl_checkheights (struct vm_area_struct * tree)
311{
312 int h, hl, hr;
313
314 if (tree == vm_avl_empty)
315 return;
316 avl_checkheights(tree->vm_avl_left);
317 avl_checkheights(tree->vm_avl_right);
318 h = tree->vm_avl_height;
319 hl = heightof(tree->vm_avl_left);
320 hr = heightof(tree->vm_avl_right);
321 if ((h == hl+1) && (hr <= hl) && (hl <= hr+1))
322 return;
323 if ((h == hr+1) && (hl <= hr) && (hr <= hl+1))
324 return;
325 printk("%s: avl_checkheights: heights inconsistent\n",avl_check_point);
326}
327
328
329static void avl_checkleft (struct vm_area_struct * tree, vm_avl_key_t key)
330{
331 if (tree == vm_avl_empty)
332 return;
333 avl_checkleft(tree->vm_avl_left,key);
334 avl_checkleft(tree->vm_avl_right,key);
335 if (tree->vm_avl_key < key)
336 return;
337 printk("%s: avl_checkleft: left key %lu >= top key %lu\n",avl_check_point,tree->vm_avl_key,key);
338}
339
340
341static void avl_checkright (struct vm_area_struct * tree, vm_avl_key_t key)
342{
343 if (tree == vm_avl_empty)
344 return;
345 avl_checkright(tree->vm_avl_left,key);
346 avl_checkright(tree->vm_avl_right,key);
347 if (tree->vm_avl_key > key)
348 return;
349 printk("%s: avl_checkright: right key %lu <= top key %lu\n",avl_check_point,tree->vm_avl_key,key);
350}
351
352
353static void avl_checkorder (struct vm_area_struct * tree)
354{
355 if (tree == vm_avl_empty)
356 return;
357 avl_checkorder(tree->vm_avl_left);
358 avl_checkorder(tree->vm_avl_right);
359 avl_checkleft(tree->vm_avl_left,tree->vm_avl_key);
360 avl_checkright(tree->vm_avl_right,tree->vm_avl_key);
361}
362
363
364static void avl_check (struct task_struct * task, char *caller)
365{
366 avl_check_point = caller;
367
368
369
370 avl_checkheights(task->mm->mmap_avl);
371 avl_checkorder(task->mm->mmap_avl);
372}
373
374#endif
375