Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

lib/interval_tree: add test case for interval_tree_iter_xxx() helpers

Verify interval_tree_iter_xxx() helpers could find intersection ranges
as expected.

[sfr@canb.auug.org.au: some of tools/ uses -Wno-unused-parameter]
Link: https://lkml.kernel.org/r/20250312113612.31ac808e@canb.auug.org.au
Link: https://lkml.kernel.org/r/20250310074938.26756-5-richard.weiyang@gmail.com
Signed-off-by: Wei Yang <richard.weiyang@gmail.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Michel Lespinasse <michel@lespinasse.org>
Cc: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Wei Yang and committed by
Andrew Morton
82114e45 16b1936a

+110
+69
lib/interval_tree_test.c
··· 5 5 #include <linux/prandom.h> 6 6 #include <linux/slab.h> 7 7 #include <asm/timex.h> 8 + #include <linux/bitmap.h> 8 9 9 10 #define __param(type, name, init, msg) \ 10 11 static type name = init; \ ··· 126 125 return 0; 127 126 } 128 127 128 + static int intersection_range_check(void) 129 + { 130 + int i, j, k; 131 + unsigned long start, last; 132 + struct interval_tree_node *node; 133 + unsigned long *intxn1; 134 + unsigned long *intxn2; 135 + 136 + printk(KERN_ALERT "interval tree iteration\n"); 137 + 138 + intxn1 = bitmap_alloc(nnodes, GFP_KERNEL); 139 + if (!intxn1) { 140 + WARN_ON_ONCE("Failed to allocate intxn1\n"); 141 + return -ENOMEM; 142 + } 143 + 144 + intxn2 = bitmap_alloc(nnodes, GFP_KERNEL); 145 + if (!intxn2) { 146 + WARN_ON_ONCE("Failed to allocate intxn2\n"); 147 + bitmap_free(intxn1); 148 + return -ENOMEM; 149 + } 150 + 151 + for (i = 0; i < search_loops; i++) { 152 + /* Initialize interval tree for each round */ 153 + init(); 154 + for (j = 0; j < nnodes; j++) 155 + interval_tree_insert(nodes + j, &root); 156 + 157 + /* Let's try nsearches different ranges */ 158 + for (k = 0; k < nsearches; k++) { 159 + /* Try whole range once */ 160 + if (!k) { 161 + start = 0UL; 162 + last = ULONG_MAX; 163 + } else { 164 + last = (prandom_u32_state(&rnd) >> 4) % max_endpoint; 165 + start = (prandom_u32_state(&rnd) >> 4) % last; 166 + } 167 + 168 + /* Walk nodes to mark intersection nodes */ 169 + bitmap_zero(intxn1, nnodes); 170 + for (j = 0; j < nnodes; j++) { 171 + node = nodes + j; 172 + 173 + if (start <= node->last && last >= node->start) 174 + bitmap_set(intxn1, j, 1); 175 + } 176 + 177 + /* Iterate tree to clear intersection nodes */ 178 + bitmap_zero(intxn2, nnodes); 179 + for (node = interval_tree_iter_first(&root, start, last); node; 180 + node = interval_tree_iter_next(node, start, last)) 181 + bitmap_set(intxn2, node - nodes, 1); 182 + 183 + WARN_ON_ONCE(!bitmap_equal(intxn1, intxn2, nnodes)); 184 + } 185 + 186 + for (j = 0; j < nnodes; j++) 187 + interval_tree_remove(nodes + j, &root); 188 + } 189 + 190 + bitmap_free(intxn1); 191 + bitmap_free(intxn2); 192 + return 0; 193 + } 194 + 129 195 static int interval_tree_test_init(void) 130 196 { 131 197 nodes = kmalloc_array(nnodes, sizeof(struct interval_tree_node), ··· 210 142 211 143 basic_check(); 212 144 search_check(); 145 + intersection_range_check(); 213 146 214 147 kfree(queries); 215 148 kfree(nodes);
+21
tools/include/linux/bitmap.h
··· 19 19 const unsigned long *bitmap2, unsigned int bits); 20 20 bool __bitmap_equal(const unsigned long *bitmap1, 21 21 const unsigned long *bitmap2, unsigned int bits); 22 + void __bitmap_set(unsigned long *map, unsigned int start, int len); 22 23 void __bitmap_clear(unsigned long *map, unsigned int start, int len); 23 24 bool __bitmap_intersects(const unsigned long *bitmap1, 24 25 const unsigned long *bitmap2, unsigned int bits); ··· 78 77 *dst = *src1 | *src2; 79 78 else 80 79 __bitmap_or(dst, src1, src2, nbits); 80 + } 81 + 82 + static inline unsigned long *bitmap_alloc(unsigned int nbits, gfp_t flags __maybe_unused) 83 + { 84 + return malloc(bitmap_size(nbits)); 81 85 } 82 86 83 87 /** ··· 154 148 return ((*src1 & *src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0; 155 149 else 156 150 return __bitmap_intersects(src1, src2, nbits); 151 + } 152 + 153 + static inline void bitmap_set(unsigned long *map, unsigned int start, unsigned int nbits) 154 + { 155 + if (__builtin_constant_p(nbits) && nbits == 1) 156 + __set_bit(start, map); 157 + else if (small_const_nbits(start + nbits)) 158 + *map |= GENMASK(start + nbits - 1, start); 159 + else if (__builtin_constant_p(start & BITMAP_MEM_MASK) && 160 + IS_ALIGNED(start, BITMAP_MEM_ALIGNMENT) && 161 + __builtin_constant_p(nbits & BITMAP_MEM_MASK) && 162 + IS_ALIGNED(nbits, BITMAP_MEM_ALIGNMENT)) 163 + memset((char *)map + start / 8, 0xff, nbits / 8); 164 + else 165 + __bitmap_set(map, start, nbits); 157 166 } 158 167 159 168 static inline void bitmap_clear(unsigned long *map, unsigned int start,
+20
tools/lib/bitmap.c
··· 101 101 return false; 102 102 } 103 103 104 + void __bitmap_set(unsigned long *map, unsigned int start, int len) 105 + { 106 + unsigned long *p = map + BIT_WORD(start); 107 + const unsigned int size = start + len; 108 + int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG); 109 + unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start); 110 + 111 + while (len - bits_to_set >= 0) { 112 + *p |= mask_to_set; 113 + len -= bits_to_set; 114 + bits_to_set = BITS_PER_LONG; 115 + mask_to_set = ~0UL; 116 + p++; 117 + } 118 + if (len) { 119 + mask_to_set &= BITMAP_LAST_WORD_MASK(size); 120 + *p |= mask_to_set; 121 + } 122 + } 123 + 104 124 void __bitmap_clear(unsigned long *map, unsigned int start, int len) 105 125 { 106 126 unsigned long *p = map + BIT_WORD(start);