diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-09 03:23:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-09 03:23:15 -0400 |
commit | 9e2d8656f5e8aa214e66b462680cf86b210b74a8 (patch) | |
tree | f67d62e896cedf75599ea45f9ecf9999c6ad24cd /include/linux/interval_tree_generic.h | |
parent | 1ea4f4f8405cc1ceec23f2d261bc3775785e6712 (diff) | |
parent | 9e695d2ecc8451cc2c1603d60b5c8e7f5581923a (diff) |
Merge branch 'akpm' (Andrew's patch-bomb)
Merge patches from Andrew Morton:
"A few misc things and very nearly all of the MM tree. A tremendous
amount of stuff (again), including a significant rbtree library
rework."
* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (160 commits)
sparc64: Support transparent huge pages.
mm: thp: Use more portable PMD clearing sequenece in zap_huge_pmd().
mm: Add and use update_mmu_cache_pmd() in transparent huge page code.
sparc64: Document PGD and PMD layout.
sparc64: Eliminate PTE table memory wastage.
sparc64: Halve the size of PTE tables
sparc64: Only support 4MB huge pages and 8KB base pages.
memory-hotplug: suppress "Trying to free nonexistent resource <XXXXXXXXXXXXXXXX-YYYYYYYYYYYYYYYY>" warning
mm: memcg: clean up mm_match_cgroup() signature
mm: document PageHuge somewhat
mm: use %pK for /proc/vmallocinfo
mm, thp: fix mlock statistics
mm, thp: fix mapped pages avoiding unevictable list on mlock
memory-hotplug: update memory block's state and notify userspace
memory-hotplug: preparation to notify memory block's state at memory hot remove
mm: avoid section mismatch warning for memblock_type_name
make GFP_NOTRACK definition unconditional
cma: decrease cc.nr_migratepages after reclaiming pagelist
CMA: migrate mlocked pages
kpageflags: fix wrong KPF_THP on non-huge compound pages
...
Diffstat (limited to 'include/linux/interval_tree_generic.h')
-rw-r--r-- | include/linux/interval_tree_generic.h | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/include/linux/interval_tree_generic.h b/include/linux/interval_tree_generic.h new file mode 100644 index 000000000000..58370e1862ad --- /dev/null +++ b/include/linux/interval_tree_generic.h | |||
@@ -0,0 +1,191 @@ | |||
1 | /* | ||
2 | Interval Trees | ||
3 | (C) 2012 Michel Lespinasse <walken@google.com> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | include/linux/interval_tree_generic.h | ||
20 | */ | ||
21 | |||
22 | #include <linux/rbtree_augmented.h> | ||
23 | |||
24 | /* | ||
25 | * Template for implementing interval trees | ||
26 | * | ||
27 | * ITSTRUCT: struct type of the interval tree nodes | ||
28 | * ITRB: name of struct rb_node field within ITSTRUCT | ||
29 | * ITTYPE: type of the interval endpoints | ||
30 | * ITSUBTREE: name of ITTYPE field within ITSTRUCT holding last-in-subtree | ||
31 | * ITSTART(n): start endpoint of ITSTRUCT node n | ||
32 | * ITLAST(n): last endpoint of ITSTRUCT node n | ||
33 | * ITSTATIC: 'static' or empty | ||
34 | * ITPREFIX: prefix to use for the inline tree definitions | ||
35 | * | ||
36 | * Note - before using this, please consider if non-generic version | ||
37 | * (interval_tree.h) would work for you... | ||
38 | */ | ||
39 | |||
40 | #define INTERVAL_TREE_DEFINE(ITSTRUCT, ITRB, ITTYPE, ITSUBTREE, \ | ||
41 | ITSTART, ITLAST, ITSTATIC, ITPREFIX) \ | ||
42 | \ | ||
43 | /* Callbacks for augmented rbtree insert and remove */ \ | ||
44 | \ | ||
45 | static inline ITTYPE ITPREFIX ## _compute_subtree_last(ITSTRUCT *node) \ | ||
46 | { \ | ||
47 | ITTYPE max = ITLAST(node), subtree_last; \ | ||
48 | if (node->ITRB.rb_left) { \ | ||
49 | subtree_last = rb_entry(node->ITRB.rb_left, \ | ||
50 | ITSTRUCT, ITRB)->ITSUBTREE; \ | ||
51 | if (max < subtree_last) \ | ||
52 | max = subtree_last; \ | ||
53 | } \ | ||
54 | if (node->ITRB.rb_right) { \ | ||
55 | subtree_last = rb_entry(node->ITRB.rb_right, \ | ||
56 | ITSTRUCT, ITRB)->ITSUBTREE; \ | ||
57 | if (max < subtree_last) \ | ||
58 | max = subtree_last; \ | ||
59 | } \ | ||
60 | return max; \ | ||
61 | } \ | ||
62 | \ | ||
63 | RB_DECLARE_CALLBACKS(static, ITPREFIX ## _augment, ITSTRUCT, ITRB, \ | ||
64 | ITTYPE, ITSUBTREE, ITPREFIX ## _compute_subtree_last) \ | ||
65 | \ | ||
66 | /* Insert / remove interval nodes from the tree */ \ | ||
67 | \ | ||
68 | ITSTATIC void ITPREFIX ## _insert(ITSTRUCT *node, struct rb_root *root) \ | ||
69 | { \ | ||
70 | struct rb_node **link = &root->rb_node, *rb_parent = NULL; \ | ||
71 | ITTYPE start = ITSTART(node), last = ITLAST(node); \ | ||
72 | ITSTRUCT *parent; \ | ||
73 | \ | ||
74 | while (*link) { \ | ||
75 | rb_parent = *link; \ | ||
76 | parent = rb_entry(rb_parent, ITSTRUCT, ITRB); \ | ||
77 | if (parent->ITSUBTREE < last) \ | ||
78 | parent->ITSUBTREE = last; \ | ||
79 | if (start < ITSTART(parent)) \ | ||
80 | link = &parent->ITRB.rb_left; \ | ||
81 | else \ | ||
82 | link = &parent->ITRB.rb_right; \ | ||
83 | } \ | ||
84 | \ | ||
85 | node->ITSUBTREE = last; \ | ||
86 | rb_link_node(&node->ITRB, rb_parent, link); \ | ||
87 | rb_insert_augmented(&node->ITRB, root, &ITPREFIX ## _augment); \ | ||
88 | } \ | ||
89 | \ | ||
90 | ITSTATIC void ITPREFIX ## _remove(ITSTRUCT *node, struct rb_root *root) \ | ||
91 | { \ | ||
92 | rb_erase_augmented(&node->ITRB, root, &ITPREFIX ## _augment); \ | ||
93 | } \ | ||
94 | \ | ||
95 | /* \ | ||
96 | * Iterate over intervals intersecting [start;last] \ | ||
97 | * \ | ||
98 | * Note that a node's interval intersects [start;last] iff: \ | ||
99 | * Cond1: ITSTART(node) <= last \ | ||
100 | * and \ | ||
101 | * Cond2: start <= ITLAST(node) \ | ||
102 | */ \ | ||
103 | \ | ||
104 | static ITSTRUCT * \ | ||
105 | ITPREFIX ## _subtree_search(ITSTRUCT *node, ITTYPE start, ITTYPE last) \ | ||
106 | { \ | ||
107 | while (true) { \ | ||
108 | /* \ | ||
109 | * Loop invariant: start <= node->ITSUBTREE \ | ||
110 | * (Cond2 is satisfied by one of the subtree nodes) \ | ||
111 | */ \ | ||
112 | if (node->ITRB.rb_left) { \ | ||
113 | ITSTRUCT *left = rb_entry(node->ITRB.rb_left, \ | ||
114 | ITSTRUCT, ITRB); \ | ||
115 | if (start <= left->ITSUBTREE) { \ | ||
116 | /* \ | ||
117 | * Some nodes in left subtree satisfy Cond2. \ | ||
118 | * Iterate to find the leftmost such node N. \ | ||
119 | * If it also satisfies Cond1, that's the \ | ||
120 | * match we are looking for. Otherwise, there \ | ||
121 | * is no matching interval as nodes to the \ | ||
122 | * right of N can't satisfy Cond1 either. \ | ||
123 | */ \ | ||
124 | node = left; \ | ||
125 | continue; \ | ||
126 | } \ | ||
127 | } \ | ||
128 | if (ITSTART(node) <= last) { /* Cond1 */ \ | ||
129 | if (start <= ITLAST(node)) /* Cond2 */ \ | ||
130 | return node; /* node is leftmost match */ \ | ||
131 | if (node->ITRB.rb_right) { \ | ||
132 | node = rb_entry(node->ITRB.rb_right, \ | ||
133 | ITSTRUCT, ITRB); \ | ||
134 | if (start <= node->ITSUBTREE) \ | ||
135 | continue; \ | ||
136 | } \ | ||
137 | } \ | ||
138 | return NULL; /* No match */ \ | ||
139 | } \ | ||
140 | } \ | ||
141 | \ | ||
142 | ITSTATIC ITSTRUCT * \ | ||
143 | ITPREFIX ## _iter_first(struct rb_root *root, ITTYPE start, ITTYPE last) \ | ||
144 | { \ | ||
145 | ITSTRUCT *node; \ | ||
146 | \ | ||
147 | if (!root->rb_node) \ | ||
148 | return NULL; \ | ||
149 | node = rb_entry(root->rb_node, ITSTRUCT, ITRB); \ | ||
150 | if (node->ITSUBTREE < start) \ | ||
151 | return NULL; \ | ||
152 | return ITPREFIX ## _subtree_search(node, start, last); \ | ||
153 | } \ | ||
154 | \ | ||
155 | ITSTATIC ITSTRUCT * \ | ||
156 | ITPREFIX ## _iter_next(ITSTRUCT *node, ITTYPE start, ITTYPE last) \ | ||
157 | { \ | ||
158 | struct rb_node *rb = node->ITRB.rb_right, *prev; \ | ||
159 | \ | ||
160 | while (true) { \ | ||
161 | /* \ | ||
162 | * Loop invariants: \ | ||
163 | * Cond1: ITSTART(node) <= last \ | ||
164 | * rb == node->ITRB.rb_right \ | ||
165 | * \ | ||
166 | * First, search right subtree if suitable \ | ||
167 | */ \ | ||
168 | if (rb) { \ | ||
169 | ITSTRUCT *right = rb_entry(rb, ITSTRUCT, ITRB); \ | ||
170 | if (start <= right->ITSUBTREE) \ | ||
171 | return ITPREFIX ## _subtree_search(right, \ | ||
172 | start, last); \ | ||
173 | } \ | ||
174 | \ | ||
175 | /* Move up the tree until we come from a node's left child */ \ | ||
176 | do { \ | ||
177 | rb = rb_parent(&node->ITRB); \ | ||
178 | if (!rb) \ | ||
179 | return NULL; \ | ||
180 | prev = &node->ITRB; \ | ||
181 | node = rb_entry(rb, ITSTRUCT, ITRB); \ | ||
182 | rb = node->ITRB.rb_right; \ | ||
183 | } while (prev == rb); \ | ||
184 | \ | ||
185 | /* Check if the node intersects [start;last] */ \ | ||
186 | if (last < ITSTART(node)) /* !Cond1 */ \ | ||
187 | return NULL; \ | ||
188 | else if (start <= ITLAST(node)) /* Cond2 */ \ | ||
189 | return node; \ | ||
190 | } \ | ||
191 | } | ||