Skip to content

Commit 4164e15

Browse files
RichardWeiYangakpm00
authored andcommitted
lib/rbtree: enable userland test suite for rbtree related data structure
Patch series "lib/interval_tree: add some test cases and cleanup", v2. Since rbtree/augmented tree/interval tree share similar data structure, besides new cases for interval tree, this patch set also does cleanup for others. This patch (of 7): Currently we have some tests for rbtree related data structure, e.g. rbtree, augmented rbtree, interval tree, in lib/ as kernel module. To facilitate the test and debug for those fundamental data structure, this patch enable those tests in userland. Link: https://lkml.kernel.org/r/20250310074938.26756-1-richard.weiyang@gmail.com Link: https://lkml.kernel.org/r/20250310074938.26756-2-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>
1 parent bc2f19d commit 4164e15

File tree

19 files changed

+288
-13
lines changed

19 files changed

+288
-13
lines changed

tools/include/asm/timex.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef __TOOLS_LINUX_ASM_TIMEX_H
3+
#define __TOOLS_LINUX_ASM_TIMEX_H
4+
5+
#include <time.h>
6+
7+
#define cycles_t clock_t
8+
9+
static inline cycles_t get_cycles(void)
10+
{
11+
return clock();
12+
}
13+
#endif // __TOOLS_LINUX_ASM_TIMEX_H

tools/include/linux/container_of.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef _TOOLS_LINUX_CONTAINER_OF_H
3+
#define _TOOLS_LINUX_CONTAINER_OF_H
4+
5+
#ifndef container_of
6+
/**
7+
* container_of - cast a member of a structure out to the containing structure
8+
* @ptr: the pointer to the member.
9+
* @type: the type of the container struct this is embedded in.
10+
* @member: the name of the member within the struct.
11+
*
12+
*/
13+
#define container_of(ptr, type, member) ({ \
14+
const typeof(((type *)0)->member) * __mptr = (ptr); \
15+
(type *)((char *)__mptr - offsetof(type, member)); })
16+
#endif
17+
18+
#endif /* _TOOLS_LINUX_CONTAINER_OF_H */

tools/include/linux/kernel.h

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/panic.h>
1212
#include <endian.h>
1313
#include <byteswap.h>
14+
#include <linux/container_of.h>
1415

1516
#ifndef UINT_MAX
1617
#define UINT_MAX (~0U)
@@ -25,19 +26,6 @@
2526
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
2627
#endif
2728

28-
#ifndef container_of
29-
/**
30-
* container_of - cast a member of a structure out to the containing structure
31-
* @ptr: the pointer to the member.
32-
* @type: the type of the container struct this is embedded in.
33-
* @member: the name of the member within the struct.
34-
*
35-
*/
36-
#define container_of(ptr, type, member) ({ \
37-
const typeof(((type *)0)->member) * __mptr = (ptr); \
38-
(type *)((char *)__mptr - offsetof(type, member)); })
39-
#endif
40-
4129
#ifndef max
4230
#define max(x, y) ({ \
4331
typeof(x) _max1 = (x); \

tools/include/linux/math64.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,9 @@ static inline u64 mul_u64_u64_div64(u64 a, u64 b, u64 c)
7272
}
7373
#endif
7474

75+
static inline u64 div_u64(u64 dividend, u32 divisor)
76+
{
77+
return dividend / divisor;
78+
}
79+
7580
#endif /* _LINUX_MATH64_H */

tools/include/linux/moduleparam.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef _TOOLS_LINUX_MODULE_PARAMS_H
3+
#define _TOOLS_LINUX_MODULE_PARAMS_H
4+
5+
#define MODULE_PARM_DESC(parm, desc)
6+
7+
#endif // _TOOLS_LINUX_MODULE_PARAMS_H

tools/include/linux/prandom.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef __TOOLS_LINUX_PRANDOM_H
3+
#define __TOOLS_LINUX_PRANDOM_H
4+
5+
#include <linux/types.h>
6+
7+
struct rnd_state {
8+
__u32 s1, s2, s3, s4;
9+
};
10+
11+
/*
12+
* Handle minimum values for seeds
13+
*/
14+
static inline u32 __seed(u32 x, u32 m)
15+
{
16+
return (x < m) ? x + m : x;
17+
}
18+
19+
/**
20+
* prandom_seed_state - set seed for prandom_u32_state().
21+
* @state: pointer to state structure to receive the seed.
22+
* @seed: arbitrary 64-bit value to use as a seed.
23+
*/
24+
static inline void prandom_seed_state(struct rnd_state *state, u64 seed)
25+
{
26+
u32 i = ((seed >> 32) ^ (seed << 10) ^ seed) & 0xffffffffUL;
27+
28+
state->s1 = __seed(i, 2U);
29+
state->s2 = __seed(i, 8U);
30+
state->s3 = __seed(i, 16U);
31+
state->s4 = __seed(i, 128U);
32+
}
33+
34+
/**
35+
* prandom_u32_state - seeded pseudo-random number generator.
36+
* @state: pointer to state structure holding seeded state.
37+
*
38+
* This is used for pseudo-randomness with no outside seeding.
39+
* For more random results, use get_random_u32().
40+
*/
41+
static inline u32 prandom_u32_state(struct rnd_state *state)
42+
{
43+
#define TAUSWORTHE(s, a, b, c, d) (((s & c) << d) ^ (((s << a) ^ s) >> b))
44+
state->s1 = TAUSWORTHE(state->s1, 6U, 13U, 4294967294U, 18U);
45+
state->s2 = TAUSWORTHE(state->s2, 2U, 27U, 4294967288U, 2U);
46+
state->s3 = TAUSWORTHE(state->s3, 13U, 21U, 4294967280U, 7U);
47+
state->s4 = TAUSWORTHE(state->s4, 3U, 12U, 4294967168U, 13U);
48+
49+
return (state->s1 ^ state->s2 ^ state->s3 ^ state->s4);
50+
}
51+
#endif // __TOOLS_LINUX_PRANDOM_H

tools/include/linux/slab.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
void *kmalloc(size_t size, gfp_t gfp);
1414
void kfree(void *p);
15+
void *kmalloc_array(size_t n, size_t size, gfp_t gfp);
1516

1617
bool slab_is_available(void);
1718

tools/lib/slab.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,19 @@ void kfree(void *p)
3636
printf("Freeing %p to malloc\n", p);
3737
free(p);
3838
}
39+
40+
void *kmalloc_array(size_t n, size_t size, gfp_t gfp)
41+
{
42+
void *ret;
43+
44+
if (!(gfp & __GFP_DIRECT_RECLAIM))
45+
return NULL;
46+
47+
ret = calloc(n, size);
48+
uatomic_inc(&kmalloc_nr_allocated);
49+
if (kmalloc_verbose)
50+
printf("Allocating %p from calloc\n", ret);
51+
if (gfp & __GFP_ZERO)
52+
memset(ret, 0, n * size);
53+
return ret;
54+
}

tools/testing/rbtree/Makefile

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
3+
.PHONY: clean
4+
5+
TARGETS = rbtree_test interval_tree_test
6+
OFILES = $(LIBS) rbtree-shim.o interval_tree-shim.o
7+
DEPS = ../../../include/linux/rbtree.h \
8+
../../../include/linux/rbtree_types.h \
9+
../../../include/linux/rbtree_augmented.h \
10+
../../../include/linux/interval_tree.h \
11+
../../../include/linux/interval_tree_generic.h \
12+
../../../lib/rbtree.c \
13+
../../../lib/interval_tree.c
14+
15+
targets: $(TARGETS)
16+
17+
include ../shared/shared.mk
18+
19+
ifeq ($(DEBUG), 1)
20+
CFLAGS += -g
21+
endif
22+
23+
$(TARGETS): $(OFILES)
24+
25+
rbtree-shim.o: $(DEPS)
26+
rbtree_test.o: ../../../lib/rbtree_test.c
27+
interval_tree-shim.o: $(DEPS)
28+
interval_tree_test.o: ../../../lib/interval_tree_test.c
29+
30+
clean:
31+
$(RM) $(TARGETS) *.o generated/*
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* interval_tree.c: Userspace Interval Tree test-suite
4+
* Copyright (c) 2025 Wei Yang <richard.weiyang@gmail.com>
5+
*/
6+
#include <linux/math64.h>
7+
#include <linux/kern_levels.h>
8+
#include "shared.h"
9+
10+
#include "../../../lib/interval_tree_test.c"
11+
12+
int usage(void)
13+
{
14+
fprintf(stderr, "Userland interval tree test cases\n");
15+
fprintf(stderr, " -n: Number of nodes in the interval tree\n");
16+
fprintf(stderr, " -p: Number of iterations modifying the tree\n");
17+
fprintf(stderr, " -q: Number of searches to the interval tree\n");
18+
fprintf(stderr, " -s: Number of iterations searching the tree\n");
19+
fprintf(stderr, " -a: Searches will iterate all nodes in the tree\n");
20+
fprintf(stderr, " -m: Largest value for the interval's endpoint\n");
21+
exit(-1);
22+
}
23+
24+
void interval_tree_tests(void)
25+
{
26+
interval_tree_test_init();
27+
interval_tree_test_exit();
28+
}
29+
30+
int main(int argc, char **argv)
31+
{
32+
int opt;
33+
34+
while ((opt = getopt(argc, argv, "n:p:q:s:am:")) != -1) {
35+
if (opt == 'n')
36+
nnodes = strtoul(optarg, NULL, 0);
37+
else if (opt == 'p')
38+
perf_loops = strtoul(optarg, NULL, 0);
39+
else if (opt == 'q')
40+
nsearches = strtoul(optarg, NULL, 0);
41+
else if (opt == 's')
42+
search_loops = strtoul(optarg, NULL, 0);
43+
else if (opt == 'a')
44+
search_all = true;
45+
else if (opt == 'm')
46+
max_endpoint = strtoul(optarg, NULL, 0);
47+
else
48+
usage();
49+
}
50+
51+
interval_tree_tests();
52+
return 0;
53+
}

0 commit comments

Comments
 (0)