Rev 5270 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5270 | Rev 6934 | ||
---|---|---|---|
Line 42... | Line 42... | ||
42 | * We shall indicate color with case, where black nodes are uppercase and red |
42 | * We shall indicate color with case, where black nodes are uppercase and red |
43 | * nodes will be lowercase. Unknown color nodes shall be drawn as red within |
43 | * nodes will be lowercase. Unknown color nodes shall be drawn as red within |
44 | * parentheses and have some accompanying text comment. |
44 | * parentheses and have some accompanying text comment. |
45 | */ |
45 | */ |
Line -... | Line 46... | ||
- | 46 | ||
- | 47 | /* |
|
- | 48 | * Notes on lockless lookups: |
|
- | 49 | * |
|
- | 50 | * All stores to the tree structure (rb_left and rb_right) must be done using |
|
- | 51 | * WRITE_ONCE(). And we must not inadvertently cause (temporary) loops in the |
|
- | 52 | * tree structure as seen in program order. |
|
- | 53 | * |
|
- | 54 | * These two requirements will allow lockless iteration of the tree -- not |
|
- | 55 | * correct iteration mind you, tree rotations are not atomic so a lookup might |
|
- | 56 | * miss entire subtrees. |
|
- | 57 | * |
|
- | 58 | * But they do guarantee that any such traversal will only see valid elements |
|
- | 59 | * and that it will indeed complete -- does not get stuck in a loop. |
|
- | 60 | * |
|
- | 61 | * It also guarantees that if the lookup returns an element it is the 'correct' |
|
- | 62 | * one. But not returning an element does _NOT_ mean it's not present. |
|
- | 63 | * |
|
- | 64 | * NOTE: |
|
- | 65 | * |
|
- | 66 | * Stores to __rb_parent_color are not important for simple lookups so those |
|
- | 67 | * are left undone as of now. Nor did I check for loops involving parent |
|
- | 68 | * pointers. |
|
- | 69 | */ |
|
46 | 70 | ||
47 | static inline void rb_set_black(struct rb_node *rb) |
71 | static inline void rb_set_black(struct rb_node *rb) |
48 | { |
72 | { |
49 | rb->__rb_parent_color |= RB_BLACK; |
73 | rb->__rb_parent_color |= RB_BLACK; |
Line 127... | Line 151... | ||
127 | * n p |
151 | * n p |
128 | * |
152 | * |
129 | * This still leaves us in violation of 4), the |
153 | * This still leaves us in violation of 4), the |
130 | * continuation into Case 3 will fix that. |
154 | * continuation into Case 3 will fix that. |
131 | */ |
155 | */ |
132 | parent->rb_right = tmp = node->rb_left; |
156 | tmp = node->rb_left; |
- | 157 | WRITE_ONCE(parent->rb_right, tmp); |
|
133 | node->rb_left = parent; |
158 | WRITE_ONCE(node->rb_left, parent); |
134 | if (tmp) |
159 | if (tmp) |
135 | rb_set_parent_color(tmp, parent, |
160 | rb_set_parent_color(tmp, parent, |
136 | RB_BLACK); |
161 | RB_BLACK); |
137 | rb_set_parent_color(parent, node, RB_RED); |
162 | rb_set_parent_color(parent, node, RB_RED); |
138 | augment_rotate(parent, node); |
163 | augment_rotate(parent, node); |
Line 147... | Line 172... | ||
147 | * / \ / \ |
172 | * / \ / \ |
148 | * p U --> n g |
173 | * p U --> n g |
149 | * / \ |
174 | * / \ |
150 | * n U |
175 | * n U |
151 | */ |
176 | */ |
152 | gparent->rb_left = tmp; /* == parent->rb_right */ |
177 | WRITE_ONCE(gparent->rb_left, tmp); /* == parent->rb_right */ |
153 | parent->rb_right = gparent; |
178 | WRITE_ONCE(parent->rb_right, gparent); |
154 | if (tmp) |
179 | if (tmp) |
155 | rb_set_parent_color(tmp, gparent, RB_BLACK); |
180 | rb_set_parent_color(tmp, gparent, RB_BLACK); |
156 | __rb_rotate_set_parents(gparent, parent, root, RB_RED); |
181 | __rb_rotate_set_parents(gparent, parent, root, RB_RED); |
157 | augment_rotate(gparent, parent); |
182 | augment_rotate(gparent, parent); |
158 | break; |
183 | break; |
Line 169... | Line 194... | ||
169 | } |
194 | } |
Line 170... | Line 195... | ||
170 | 195 | ||
171 | tmp = parent->rb_left; |
196 | tmp = parent->rb_left; |
172 | if (node == tmp) { |
197 | if (node == tmp) { |
173 | /* Case 2 - right rotate at parent */ |
198 | /* Case 2 - right rotate at parent */ |
- | 199 | tmp = node->rb_right; |
|
174 | parent->rb_left = tmp = node->rb_right; |
200 | WRITE_ONCE(parent->rb_left, tmp); |
175 | node->rb_right = parent; |
201 | WRITE_ONCE(node->rb_right, parent); |
176 | if (tmp) |
202 | if (tmp) |
177 | rb_set_parent_color(tmp, parent, |
203 | rb_set_parent_color(tmp, parent, |
178 | RB_BLACK); |
204 | RB_BLACK); |
179 | rb_set_parent_color(parent, node, RB_RED); |
205 | rb_set_parent_color(parent, node, RB_RED); |
180 | augment_rotate(parent, node); |
206 | augment_rotate(parent, node); |
181 | parent = node; |
207 | parent = node; |
182 | tmp = node->rb_left; |
208 | tmp = node->rb_left; |
Line 183... | Line 209... | ||
183 | } |
209 | } |
184 | 210 | ||
185 | /* Case 3 - left rotate at gparent */ |
211 | /* Case 3 - left rotate at gparent */ |
186 | gparent->rb_right = tmp; /* == parent->rb_left */ |
212 | WRITE_ONCE(gparent->rb_right, tmp); /* == parent->rb_left */ |
187 | parent->rb_left = gparent; |
213 | WRITE_ONCE(parent->rb_left, gparent); |
188 | if (tmp) |
214 | if (tmp) |
189 | rb_set_parent_color(tmp, gparent, RB_BLACK); |
215 | rb_set_parent_color(tmp, gparent, RB_BLACK); |
190 | __rb_rotate_set_parents(gparent, parent, root, RB_RED); |
216 | __rb_rotate_set_parents(gparent, parent, root, RB_RED); |
Line 222... | Line 248... | ||
222 | * / \ / \ |
248 | * / \ / \ |
223 | * N s --> p Sr |
249 | * N s --> p Sr |
224 | * / \ / \ |
250 | * / \ / \ |
225 | * Sl Sr N Sl |
251 | * Sl Sr N Sl |
226 | */ |
252 | */ |
227 | parent->rb_right = tmp1 = sibling->rb_left; |
253 | tmp1 = sibling->rb_left; |
- | 254 | WRITE_ONCE(parent->rb_right, tmp1); |
|
228 | sibling->rb_left = parent; |
255 | WRITE_ONCE(sibling->rb_left, parent); |
229 | rb_set_parent_color(tmp1, parent, RB_BLACK); |
256 | rb_set_parent_color(tmp1, parent, RB_BLACK); |
230 | __rb_rotate_set_parents(parent, sibling, root, |
257 | __rb_rotate_set_parents(parent, sibling, root, |
231 | RB_RED); |
258 | RB_RED); |
232 | augment_rotate(parent, sibling); |
259 | augment_rotate(parent, sibling); |
233 | sibling = tmp1; |
260 | sibling = tmp1; |
Line 273... | Line 300... | ||
273 | * / \ \ |
300 | * / \ \ |
274 | * sl Sr s |
301 | * sl Sr s |
275 | * \ |
302 | * \ |
276 | * Sr |
303 | * Sr |
277 | */ |
304 | */ |
278 | sibling->rb_left = tmp1 = tmp2->rb_right; |
305 | tmp1 = tmp2->rb_right; |
- | 306 | WRITE_ONCE(sibling->rb_left, tmp1); |
|
279 | tmp2->rb_right = sibling; |
307 | WRITE_ONCE(tmp2->rb_right, sibling); |
280 | parent->rb_right = tmp2; |
308 | WRITE_ONCE(parent->rb_right, tmp2); |
281 | if (tmp1) |
309 | if (tmp1) |
282 | rb_set_parent_color(tmp1, sibling, |
310 | rb_set_parent_color(tmp1, sibling, |
283 | RB_BLACK); |
311 | RB_BLACK); |
284 | augment_rotate(sibling, tmp2); |
312 | augment_rotate(sibling, tmp2); |
285 | tmp1 = sibling; |
313 | tmp1 = sibling; |
Line 295... | Line 323... | ||
295 | * / \ / \ |
323 | * / \ / \ |
296 | * N S --> P Sr |
324 | * N S --> P Sr |
297 | * / \ / \ |
325 | * / \ / \ |
298 | * (sl) sr N (sl) |
326 | * (sl) sr N (sl) |
299 | */ |
327 | */ |
300 | parent->rb_right = tmp2 = sibling->rb_left; |
328 | tmp2 = sibling->rb_left; |
- | 329 | WRITE_ONCE(parent->rb_right, tmp2); |
|
301 | sibling->rb_left = parent; |
330 | WRITE_ONCE(sibling->rb_left, parent); |
302 | rb_set_parent_color(tmp1, sibling, RB_BLACK); |
331 | rb_set_parent_color(tmp1, sibling, RB_BLACK); |
303 | if (tmp2) |
332 | if (tmp2) |
304 | rb_set_parent(tmp2, parent); |
333 | rb_set_parent(tmp2, parent); |
305 | __rb_rotate_set_parents(parent, sibling, root, |
334 | __rb_rotate_set_parents(parent, sibling, root, |
306 | RB_BLACK); |
335 | RB_BLACK); |
Line 308... | Line 337... | ||
308 | break; |
337 | break; |
309 | } else { |
338 | } else { |
310 | sibling = parent->rb_left; |
339 | sibling = parent->rb_left; |
311 | if (rb_is_red(sibling)) { |
340 | if (rb_is_red(sibling)) { |
312 | /* Case 1 - right rotate at parent */ |
341 | /* Case 1 - right rotate at parent */ |
313 | parent->rb_left = tmp1 = sibling->rb_right; |
342 | tmp1 = sibling->rb_right; |
- | 343 | WRITE_ONCE(parent->rb_left, tmp1); |
|
314 | sibling->rb_right = parent; |
344 | WRITE_ONCE(sibling->rb_right, parent); |
315 | rb_set_parent_color(tmp1, parent, RB_BLACK); |
345 | rb_set_parent_color(tmp1, parent, RB_BLACK); |
316 | __rb_rotate_set_parents(parent, sibling, root, |
346 | __rb_rotate_set_parents(parent, sibling, root, |
317 | RB_RED); |
347 | RB_RED); |
318 | augment_rotate(parent, sibling); |
348 | augment_rotate(parent, sibling); |
319 | sibling = tmp1; |
349 | sibling = tmp1; |
Line 334... | Line 364... | ||
334 | continue; |
364 | continue; |
335 | } |
365 | } |
336 | break; |
366 | break; |
337 | } |
367 | } |
338 | /* Case 3 - right rotate at sibling */ |
368 | /* Case 3 - right rotate at sibling */ |
339 | sibling->rb_right = tmp1 = tmp2->rb_left; |
369 | tmp1 = tmp2->rb_left; |
- | 370 | WRITE_ONCE(sibling->rb_right, tmp1); |
|
340 | tmp2->rb_left = sibling; |
371 | WRITE_ONCE(tmp2->rb_left, sibling); |
341 | parent->rb_left = tmp2; |
372 | WRITE_ONCE(parent->rb_left, tmp2); |
342 | if (tmp1) |
373 | if (tmp1) |
343 | rb_set_parent_color(tmp1, sibling, |
374 | rb_set_parent_color(tmp1, sibling, |
344 | RB_BLACK); |
375 | RB_BLACK); |
345 | augment_rotate(sibling, tmp2); |
376 | augment_rotate(sibling, tmp2); |
346 | tmp1 = sibling; |
377 | tmp1 = sibling; |
347 | sibling = tmp2; |
378 | sibling = tmp2; |
348 | } |
379 | } |
349 | /* Case 4 - left rotate at parent + color flips */ |
380 | /* Case 4 - left rotate at parent + color flips */ |
350 | parent->rb_left = tmp2 = sibling->rb_right; |
381 | tmp2 = sibling->rb_right; |
- | 382 | WRITE_ONCE(parent->rb_left, tmp2); |
|
351 | sibling->rb_right = parent; |
383 | WRITE_ONCE(sibling->rb_right, parent); |
352 | rb_set_parent_color(tmp1, sibling, RB_BLACK); |
384 | rb_set_parent_color(tmp1, sibling, RB_BLACK); |
353 | if (tmp2) |
385 | if (tmp2) |
354 | rb_set_parent(tmp2, parent); |
386 | rb_set_parent(tmp2, parent); |
355 | __rb_rotate_set_parents(parent, sibling, root, |
387 | __rb_rotate_set_parents(parent, sibling, root, |
356 | RB_BLACK); |
388 | RB_BLACK); |