|
2 | 2 | * Copyright (C) 2001 Momchil Velikov
|
3 | 3 | * Portions Copyright (C) 2001 Christoph Hellwig
|
4 | 4 | * Copyright (C) 2006 Nick Piggin
|
| 5 | + * Copyright (C) 2012 Konstantin Khlebnikov |
5 | 6 | *
|
6 | 7 | * This program is free software; you can redistribute it and/or
|
7 | 8 | * modify it under the terms of the GNU General Public License as
|
@@ -257,4 +258,199 @@ static inline void radix_tree_preload_end(void)
|
257 | 258 | preempt_enable();
|
258 | 259 | }
|
259 | 260 |
|
| 261 | +/** |
| 262 | + * struct radix_tree_iter - radix tree iterator state |
| 263 | + * |
| 264 | + * @index: index of current slot |
| 265 | + * @next_index: next-to-last index for this chunk |
| 266 | + * @tags: bit-mask for tag-iterating |
| 267 | + * |
| 268 | + * This radix tree iterator works in terms of "chunks" of slots. A chunk is a |
| 269 | + * subinterval of slots contained within one radix tree leaf node. It is |
| 270 | + * described by a pointer to its first slot and a struct radix_tree_iter |
| 271 | + * which holds the chunk's position in the tree and its size. For tagged |
| 272 | + * iteration radix_tree_iter also holds the slots' bit-mask for one chosen |
| 273 | + * radix tree tag. |
| 274 | + */ |
| 275 | +struct radix_tree_iter { |
| 276 | + unsigned long index; |
| 277 | + unsigned long next_index; |
| 278 | + unsigned long tags; |
| 279 | +}; |
| 280 | + |
| 281 | +#define RADIX_TREE_ITER_TAG_MASK 0x00FF /* tag index in lower byte */ |
| 282 | +#define RADIX_TREE_ITER_TAGGED 0x0100 /* lookup tagged slots */ |
| 283 | +#define RADIX_TREE_ITER_CONTIG 0x0200 /* stop at first hole */ |
| 284 | + |
| 285 | +/** |
| 286 | + * radix_tree_iter_init - initialize radix tree iterator |
| 287 | + * |
| 288 | + * @iter: pointer to iterator state |
| 289 | + * @start: iteration starting index |
| 290 | + * Returns: NULL |
| 291 | + */ |
| 292 | +static __always_inline void ** |
| 293 | +radix_tree_iter_init(struct radix_tree_iter *iter, unsigned long start) |
| 294 | +{ |
| 295 | + /* |
| 296 | + * Leave iter->tags uninitialized. radix_tree_next_chunk() will fill it |
| 297 | + * in the case of a successful tagged chunk lookup. If the lookup was |
| 298 | + * unsuccessful or non-tagged then nobody cares about ->tags. |
| 299 | + * |
| 300 | + * Set index to zero to bypass next_index overflow protection. |
| 301 | + * See the comment in radix_tree_next_chunk() for details. |
| 302 | + */ |
| 303 | + iter->index = 0; |
| 304 | + iter->next_index = start; |
| 305 | + return NULL; |
| 306 | +} |
| 307 | + |
| 308 | +/** |
| 309 | + * radix_tree_next_chunk - find next chunk of slots for iteration |
| 310 | + * |
| 311 | + * @root: radix tree root |
| 312 | + * @iter: iterator state |
| 313 | + * @flags: RADIX_TREE_ITER_* flags and tag index |
| 314 | + * Returns: pointer to chunk first slot, or NULL if there no more left |
| 315 | + * |
| 316 | + * This function looks up the next chunk in the radix tree starting from |
| 317 | + * @iter->next_index. It returns a pointer to the chunk's first slot. |
| 318 | + * Also it fills @iter with data about chunk: position in the tree (index), |
| 319 | + * its end (next_index), and constructs a bit mask for tagged iterating (tags). |
| 320 | + */ |
| 321 | +void **radix_tree_next_chunk(struct radix_tree_root *root, |
| 322 | + struct radix_tree_iter *iter, unsigned flags); |
| 323 | + |
| 324 | +/** |
| 325 | + * radix_tree_chunk_size - get current chunk size |
| 326 | + * |
| 327 | + * @iter: pointer to radix tree iterator |
| 328 | + * Returns: current chunk size |
| 329 | + */ |
| 330 | +static __always_inline unsigned |
| 331 | +radix_tree_chunk_size(struct radix_tree_iter *iter) |
| 332 | +{ |
| 333 | + return iter->next_index - iter->index; |
| 334 | +} |
| 335 | + |
| 336 | +/** |
| 337 | + * radix_tree_next_slot - find next slot in chunk |
| 338 | + * |
| 339 | + * @slot: pointer to current slot |
| 340 | + * @iter: pointer to interator state |
| 341 | + * @flags: RADIX_TREE_ITER_*, should be constant |
| 342 | + * Returns: pointer to next slot, or NULL if there no more left |
| 343 | + * |
| 344 | + * This function updates @iter->index in the case of a successful lookup. |
| 345 | + * For tagged lookup it also eats @iter->tags. |
| 346 | + */ |
| 347 | +static __always_inline void ** |
| 348 | +radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags) |
| 349 | +{ |
| 350 | + if (flags & RADIX_TREE_ITER_TAGGED) { |
| 351 | + iter->tags >>= 1; |
| 352 | + if (likely(iter->tags & 1ul)) { |
| 353 | + iter->index++; |
| 354 | + return slot + 1; |
| 355 | + } |
| 356 | + if (!(flags & RADIX_TREE_ITER_CONTIG) && likely(iter->tags)) { |
| 357 | + unsigned offset = __ffs(iter->tags); |
| 358 | + |
| 359 | + iter->tags >>= offset; |
| 360 | + iter->index += offset + 1; |
| 361 | + return slot + offset + 1; |
| 362 | + } |
| 363 | + } else { |
| 364 | + unsigned size = radix_tree_chunk_size(iter) - 1; |
| 365 | + |
| 366 | + while (size--) { |
| 367 | + slot++; |
| 368 | + iter->index++; |
| 369 | + if (likely(*slot)) |
| 370 | + return slot; |
| 371 | + if (flags & RADIX_TREE_ITER_CONTIG) |
| 372 | + break; |
| 373 | + } |
| 374 | + } |
| 375 | + return NULL; |
| 376 | +} |
| 377 | + |
| 378 | +/** |
| 379 | + * radix_tree_for_each_chunk - iterate over chunks |
| 380 | + * |
| 381 | + * @slot: the void** variable for pointer to chunk first slot |
| 382 | + * @root: the struct radix_tree_root pointer |
| 383 | + * @iter: the struct radix_tree_iter pointer |
| 384 | + * @start: iteration starting index |
| 385 | + * @flags: RADIX_TREE_ITER_* and tag index |
| 386 | + * |
| 387 | + * Locks can be released and reacquired between iterations. |
| 388 | + */ |
| 389 | +#define radix_tree_for_each_chunk(slot, root, iter, start, flags) \ |
| 390 | + for (slot = radix_tree_iter_init(iter, start) ; \ |
| 391 | + (slot = radix_tree_next_chunk(root, iter, flags)) ;) |
| 392 | + |
| 393 | +/** |
| 394 | + * radix_tree_for_each_chunk_slot - iterate over slots in one chunk |
| 395 | + * |
| 396 | + * @slot: the void** variable, at the beginning points to chunk first slot |
| 397 | + * @iter: the struct radix_tree_iter pointer |
| 398 | + * @flags: RADIX_TREE_ITER_*, should be constant |
| 399 | + * |
| 400 | + * This macro is designed to be nested inside radix_tree_for_each_chunk(). |
| 401 | + * @slot points to the radix tree slot, @iter->index contains its index. |
| 402 | + */ |
| 403 | +#define radix_tree_for_each_chunk_slot(slot, iter, flags) \ |
| 404 | + for (; slot ; slot = radix_tree_next_slot(slot, iter, flags)) |
| 405 | + |
| 406 | +/** |
| 407 | + * radix_tree_for_each_slot - iterate over non-empty slots |
| 408 | + * |
| 409 | + * @slot: the void** variable for pointer to slot |
| 410 | + * @root: the struct radix_tree_root pointer |
| 411 | + * @iter: the struct radix_tree_iter pointer |
| 412 | + * @start: iteration starting index |
| 413 | + * |
| 414 | + * @slot points to radix tree slot, @iter->index contains its index. |
| 415 | + */ |
| 416 | +#define radix_tree_for_each_slot(slot, root, iter, start) \ |
| 417 | + for (slot = radix_tree_iter_init(iter, start) ; \ |
| 418 | + slot || (slot = radix_tree_next_chunk(root, iter, 0)) ; \ |
| 419 | + slot = radix_tree_next_slot(slot, iter, 0)) |
| 420 | + |
| 421 | +/** |
| 422 | + * radix_tree_for_each_contig - iterate over contiguous slots |
| 423 | + * |
| 424 | + * @slot: the void** variable for pointer to slot |
| 425 | + * @root: the struct radix_tree_root pointer |
| 426 | + * @iter: the struct radix_tree_iter pointer |
| 427 | + * @start: iteration starting index |
| 428 | + * |
| 429 | + * @slot points to radix tree slot, @iter->index contains its index. |
| 430 | + */ |
| 431 | +#define radix_tree_for_each_contig(slot, root, iter, start) \ |
| 432 | + for (slot = radix_tree_iter_init(iter, start) ; \ |
| 433 | + slot || (slot = radix_tree_next_chunk(root, iter, \ |
| 434 | + RADIX_TREE_ITER_CONTIG)) ; \ |
| 435 | + slot = radix_tree_next_slot(slot, iter, \ |
| 436 | + RADIX_TREE_ITER_CONTIG)) |
| 437 | + |
| 438 | +/** |
| 439 | + * radix_tree_for_each_tagged - iterate over tagged slots |
| 440 | + * |
| 441 | + * @slot: the void** variable for pointer to slot |
| 442 | + * @root: the struct radix_tree_root pointer |
| 443 | + * @iter: the struct radix_tree_iter pointer |
| 444 | + * @start: iteration starting index |
| 445 | + * @tag: tag index |
| 446 | + * |
| 447 | + * @slot points to radix tree slot, @iter->index contains its index. |
| 448 | + */ |
| 449 | +#define radix_tree_for_each_tagged(slot, root, iter, start, tag) \ |
| 450 | + for (slot = radix_tree_iter_init(iter, start) ; \ |
| 451 | + slot || (slot = radix_tree_next_chunk(root, iter, \ |
| 452 | + RADIX_TREE_ITER_TAGGED | tag)) ; \ |
| 453 | + slot = radix_tree_next_slot(slot, iter, \ |
| 454 | + RADIX_TREE_ITER_TAGGED)) |
| 455 | + |
260 | 456 | #endif /* _LINUX_RADIX_TREE_H */
|
0 commit comments