162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci#include <linux/interval_tree.h> 362306a36Sopenharmony_ci#include <linux/interval_tree_generic.h> 462306a36Sopenharmony_ci#include <linux/compiler.h> 562306a36Sopenharmony_ci#include <linux/export.h> 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#define START(node) ((node)->start) 862306a36Sopenharmony_ci#define LAST(node) ((node)->last) 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ciINTERVAL_TREE_DEFINE(struct interval_tree_node, rb, 1162306a36Sopenharmony_ci unsigned long, __subtree_last, 1262306a36Sopenharmony_ci START, LAST,, interval_tree) 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(interval_tree_insert); 1562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(interval_tree_remove); 1662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(interval_tree_iter_first); 1762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(interval_tree_iter_next); 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#ifdef CONFIG_INTERVAL_TREE_SPAN_ITER 2062306a36Sopenharmony_ci/* 2162306a36Sopenharmony_ci * Roll nodes[1] into nodes[0] by advancing nodes[1] to the end of a contiguous 2262306a36Sopenharmony_ci * span of nodes. This makes nodes[0]->last the end of that contiguous used span 2362306a36Sopenharmony_ci * indexes that started at the original nodes[1]->start. nodes[1] is now the 2462306a36Sopenharmony_ci * first node starting the next used span. A hole span is between nodes[0]->last 2562306a36Sopenharmony_ci * and nodes[1]->start. nodes[1] must be !NULL. 2662306a36Sopenharmony_ci */ 2762306a36Sopenharmony_cistatic void 2862306a36Sopenharmony_ciinterval_tree_span_iter_next_gap(struct interval_tree_span_iter *state) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci struct interval_tree_node *cur = state->nodes[1]; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci state->nodes[0] = cur; 3362306a36Sopenharmony_ci do { 3462306a36Sopenharmony_ci if (cur->last > state->nodes[0]->last) 3562306a36Sopenharmony_ci state->nodes[0] = cur; 3662306a36Sopenharmony_ci cur = interval_tree_iter_next(cur, state->first_index, 3762306a36Sopenharmony_ci state->last_index); 3862306a36Sopenharmony_ci } while (cur && (state->nodes[0]->last >= cur->start || 3962306a36Sopenharmony_ci state->nodes[0]->last + 1 == cur->start)); 4062306a36Sopenharmony_ci state->nodes[1] = cur; 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_civoid interval_tree_span_iter_first(struct interval_tree_span_iter *iter, 4462306a36Sopenharmony_ci struct rb_root_cached *itree, 4562306a36Sopenharmony_ci unsigned long first_index, 4662306a36Sopenharmony_ci unsigned long last_index) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci iter->first_index = first_index; 4962306a36Sopenharmony_ci iter->last_index = last_index; 5062306a36Sopenharmony_ci iter->nodes[0] = NULL; 5162306a36Sopenharmony_ci iter->nodes[1] = 5262306a36Sopenharmony_ci interval_tree_iter_first(itree, first_index, last_index); 5362306a36Sopenharmony_ci if (!iter->nodes[1]) { 5462306a36Sopenharmony_ci /* No nodes intersect the span, whole span is hole */ 5562306a36Sopenharmony_ci iter->start_hole = first_index; 5662306a36Sopenharmony_ci iter->last_hole = last_index; 5762306a36Sopenharmony_ci iter->is_hole = 1; 5862306a36Sopenharmony_ci return; 5962306a36Sopenharmony_ci } 6062306a36Sopenharmony_ci if (iter->nodes[1]->start > first_index) { 6162306a36Sopenharmony_ci /* Leading hole on first iteration */ 6262306a36Sopenharmony_ci iter->start_hole = first_index; 6362306a36Sopenharmony_ci iter->last_hole = iter->nodes[1]->start - 1; 6462306a36Sopenharmony_ci iter->is_hole = 1; 6562306a36Sopenharmony_ci interval_tree_span_iter_next_gap(iter); 6662306a36Sopenharmony_ci return; 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci /* Starting inside a used */ 7062306a36Sopenharmony_ci iter->start_used = first_index; 7162306a36Sopenharmony_ci iter->is_hole = 0; 7262306a36Sopenharmony_ci interval_tree_span_iter_next_gap(iter); 7362306a36Sopenharmony_ci iter->last_used = iter->nodes[0]->last; 7462306a36Sopenharmony_ci if (iter->last_used >= last_index) { 7562306a36Sopenharmony_ci iter->last_used = last_index; 7662306a36Sopenharmony_ci iter->nodes[0] = NULL; 7762306a36Sopenharmony_ci iter->nodes[1] = NULL; 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(interval_tree_span_iter_first); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_civoid interval_tree_span_iter_next(struct interval_tree_span_iter *iter) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci if (!iter->nodes[0] && !iter->nodes[1]) { 8562306a36Sopenharmony_ci iter->is_hole = -1; 8662306a36Sopenharmony_ci return; 8762306a36Sopenharmony_ci } 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci if (iter->is_hole) { 9062306a36Sopenharmony_ci iter->start_used = iter->last_hole + 1; 9162306a36Sopenharmony_ci iter->last_used = iter->nodes[0]->last; 9262306a36Sopenharmony_ci if (iter->last_used >= iter->last_index) { 9362306a36Sopenharmony_ci iter->last_used = iter->last_index; 9462306a36Sopenharmony_ci iter->nodes[0] = NULL; 9562306a36Sopenharmony_ci iter->nodes[1] = NULL; 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci iter->is_hole = 0; 9862306a36Sopenharmony_ci return; 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci if (!iter->nodes[1]) { 10262306a36Sopenharmony_ci /* Trailing hole */ 10362306a36Sopenharmony_ci iter->start_hole = iter->nodes[0]->last + 1; 10462306a36Sopenharmony_ci iter->last_hole = iter->last_index; 10562306a36Sopenharmony_ci iter->nodes[0] = NULL; 10662306a36Sopenharmony_ci iter->is_hole = 1; 10762306a36Sopenharmony_ci return; 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci /* must have both nodes[0] and [1], interior hole */ 11162306a36Sopenharmony_ci iter->start_hole = iter->nodes[0]->last + 1; 11262306a36Sopenharmony_ci iter->last_hole = iter->nodes[1]->start - 1; 11362306a36Sopenharmony_ci iter->is_hole = 1; 11462306a36Sopenharmony_ci interval_tree_span_iter_next_gap(iter); 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(interval_tree_span_iter_next); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci/* 11962306a36Sopenharmony_ci * Advance the iterator index to a specific position. The returned used/hole is 12062306a36Sopenharmony_ci * updated to start at new_index. This is faster than calling 12162306a36Sopenharmony_ci * interval_tree_span_iter_first() as it can avoid full searches in several 12262306a36Sopenharmony_ci * cases where the iterator is already set. 12362306a36Sopenharmony_ci */ 12462306a36Sopenharmony_civoid interval_tree_span_iter_advance(struct interval_tree_span_iter *iter, 12562306a36Sopenharmony_ci struct rb_root_cached *itree, 12662306a36Sopenharmony_ci unsigned long new_index) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci if (iter->is_hole == -1) 12962306a36Sopenharmony_ci return; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci iter->first_index = new_index; 13262306a36Sopenharmony_ci if (new_index > iter->last_index) { 13362306a36Sopenharmony_ci iter->is_hole = -1; 13462306a36Sopenharmony_ci return; 13562306a36Sopenharmony_ci } 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* Rely on the union aliasing hole/used */ 13862306a36Sopenharmony_ci if (iter->start_hole <= new_index && new_index <= iter->last_hole) { 13962306a36Sopenharmony_ci iter->start_hole = new_index; 14062306a36Sopenharmony_ci return; 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci if (new_index == iter->last_hole + 1) 14362306a36Sopenharmony_ci interval_tree_span_iter_next(iter); 14462306a36Sopenharmony_ci else 14562306a36Sopenharmony_ci interval_tree_span_iter_first(iter, itree, new_index, 14662306a36Sopenharmony_ci iter->last_index); 14762306a36Sopenharmony_ci} 14862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(interval_tree_span_iter_advance); 14962306a36Sopenharmony_ci#endif 150