Skip to content

Commit 82114e4

Browse files
RichardWeiYangakpm00
authored andcommitted
lib/interval_tree: add test case for interval_tree_iter_xxx() helpers
Verify interval_tree_iter_xxx() helpers could find intersection ranges as expected. [[email protected]: some of tools/ uses -Wno-unused-parameter] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Wei Yang <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Michel Lespinasse <[email protected]> Cc: Jason Gunthorpe <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 16b1936 commit 82114e4

File tree

3 files changed

+110
-0
lines changed

3 files changed

+110
-0
lines changed

lib/interval_tree_test.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <linux/prandom.h>
66
#include <linux/slab.h>
77
#include <asm/timex.h>
8+
#include <linux/bitmap.h>
89

910
#define __param(type, name, init, msg) \
1011
static type name = init; \
@@ -125,6 +126,73 @@ static int search_check(void)
125126
return 0;
126127
}
127128

129+
static int intersection_range_check(void)
130+
{
131+
int i, j, k;
132+
unsigned long start, last;
133+
struct interval_tree_node *node;
134+
unsigned long *intxn1;
135+
unsigned long *intxn2;
136+
137+
printk(KERN_ALERT "interval tree iteration\n");
138+
139+
intxn1 = bitmap_alloc(nnodes, GFP_KERNEL);
140+
if (!intxn1) {
141+
WARN_ON_ONCE("Failed to allocate intxn1\n");
142+
return -ENOMEM;
143+
}
144+
145+
intxn2 = bitmap_alloc(nnodes, GFP_KERNEL);
146+
if (!intxn2) {
147+
WARN_ON_ONCE("Failed to allocate intxn2\n");
148+
bitmap_free(intxn1);
149+
return -ENOMEM;
150+
}
151+
152+
for (i = 0; i < search_loops; i++) {
153+
/* Initialize interval tree for each round */
154+
init();
155+
for (j = 0; j < nnodes; j++)
156+
interval_tree_insert(nodes + j, &root);
157+
158+
/* Let's try nsearches different ranges */
159+
for (k = 0; k < nsearches; k++) {
160+
/* Try whole range once */
161+
if (!k) {
162+
start = 0UL;
163+
last = ULONG_MAX;
164+
} else {
165+
last = (prandom_u32_state(&rnd) >> 4) % max_endpoint;
166+
start = (prandom_u32_state(&rnd) >> 4) % last;
167+
}
168+
169+
/* Walk nodes to mark intersection nodes */
170+
bitmap_zero(intxn1, nnodes);
171+
for (j = 0; j < nnodes; j++) {
172+
node = nodes + j;
173+
174+
if (start <= node->last && last >= node->start)
175+
bitmap_set(intxn1, j, 1);
176+
}
177+
178+
/* Iterate tree to clear intersection nodes */
179+
bitmap_zero(intxn2, nnodes);
180+
for (node = interval_tree_iter_first(&root, start, last); node;
181+
node = interval_tree_iter_next(node, start, last))
182+
bitmap_set(intxn2, node - nodes, 1);
183+
184+
WARN_ON_ONCE(!bitmap_equal(intxn1, intxn2, nnodes));
185+
}
186+
187+
for (j = 0; j < nnodes; j++)
188+
interval_tree_remove(nodes + j, &root);
189+
}
190+
191+
bitmap_free(intxn1);
192+
bitmap_free(intxn2);
193+
return 0;
194+
}
195+
128196
static int interval_tree_test_init(void)
129197
{
130198
nodes = kmalloc_array(nnodes, sizeof(struct interval_tree_node),
@@ -142,6 +210,7 @@ static int interval_tree_test_init(void)
142210

143211
basic_check();
144212
search_check();
213+
intersection_range_check();
145214

146215
kfree(queries);
147216
kfree(nodes);

tools/include/linux/bitmap.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ bool __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
1919
const unsigned long *bitmap2, unsigned int bits);
2020
bool __bitmap_equal(const unsigned long *bitmap1,
2121
const unsigned long *bitmap2, unsigned int bits);
22+
void __bitmap_set(unsigned long *map, unsigned int start, int len);
2223
void __bitmap_clear(unsigned long *map, unsigned int start, int len);
2324
bool __bitmap_intersects(const unsigned long *bitmap1,
2425
const unsigned long *bitmap2, unsigned int bits);
@@ -79,6 +80,11 @@ static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
7980
__bitmap_or(dst, src1, src2, nbits);
8081
}
8182

83+
static inline unsigned long *bitmap_alloc(unsigned int nbits, gfp_t flags __maybe_unused)
84+
{
85+
return malloc(bitmap_size(nbits));
86+
}
87+
8288
/**
8389
* bitmap_zalloc - Allocate bitmap
8490
* @nbits: Number of bits
@@ -150,6 +156,21 @@ static inline bool bitmap_intersects(const unsigned long *src1,
150156
return __bitmap_intersects(src1, src2, nbits);
151157
}
152158

159+
static inline void bitmap_set(unsigned long *map, unsigned int start, unsigned int nbits)
160+
{
161+
if (__builtin_constant_p(nbits) && nbits == 1)
162+
__set_bit(start, map);
163+
else if (small_const_nbits(start + nbits))
164+
*map |= GENMASK(start + nbits - 1, start);
165+
else if (__builtin_constant_p(start & BITMAP_MEM_MASK) &&
166+
IS_ALIGNED(start, BITMAP_MEM_ALIGNMENT) &&
167+
__builtin_constant_p(nbits & BITMAP_MEM_MASK) &&
168+
IS_ALIGNED(nbits, BITMAP_MEM_ALIGNMENT))
169+
memset((char *)map + start / 8, 0xff, nbits / 8);
170+
else
171+
__bitmap_set(map, start, nbits);
172+
}
173+
153174
static inline void bitmap_clear(unsigned long *map, unsigned int start,
154175
unsigned int nbits)
155176
{

tools/lib/bitmap.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,26 @@ bool __bitmap_intersects(const unsigned long *bitmap1,
101101
return false;
102102
}
103103

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+
104124
void __bitmap_clear(unsigned long *map, unsigned int start, int len)
105125
{
106126
unsigned long *p = map + BIT_WORD(start);

0 commit comments

Comments
 (0)