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

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>

authored by

Wei Yang and committed by
Andrew Morton
4164e152 bc2f19d6

+288 -13
+13
tools/include/asm/timex.h
··· 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
+18
tools/include/linux/container_of.h
··· 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 */
+1 -13
tools/include/linux/kernel.h
··· 11 11 #include <linux/panic.h> 12 12 #include <endian.h> 13 13 #include <byteswap.h> 14 + #include <linux/container_of.h> 14 15 15 16 #ifndef UINT_MAX 16 17 #define UINT_MAX (~0U) ··· 24 23 25 24 #ifndef offsetof 26 25 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 27 - #endif 28 - 29 - #ifndef container_of 30 - /** 31 - * container_of - cast a member of a structure out to the containing structure 32 - * @ptr: the pointer to the member. 33 - * @type: the type of the container struct this is embedded in. 34 - * @member: the name of the member within the struct. 35 - * 36 - */ 37 - #define container_of(ptr, type, member) ({ \ 38 - const typeof(((type *)0)->member) * __mptr = (ptr); \ 39 - (type *)((char *)__mptr - offsetof(type, member)); }) 40 26 #endif 41 27 42 28 #ifndef max
+5
tools/include/linux/math64.h
··· 72 72 } 73 73 #endif 74 74 75 + static inline u64 div_u64(u64 dividend, u32 divisor) 76 + { 77 + return dividend / divisor; 78 + } 79 + 75 80 #endif /* _LINUX_MATH64_H */
+7
tools/include/linux/moduleparam.h
··· 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
+51
tools/include/linux/prandom.h
··· 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
+1
tools/include/linux/slab.h
··· 12 12 13 13 void *kmalloc(size_t size, gfp_t gfp); 14 14 void kfree(void *p); 15 + void *kmalloc_array(size_t n, size_t size, gfp_t gfp); 15 16 16 17 bool slab_is_available(void); 17 18
+16
tools/lib/slab.c
··· 36 36 printf("Freeing %p to malloc\n", p); 37 37 free(p); 38 38 } 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 + }
+31
tools/testing/rbtree/Makefile
··· 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/*
+53
tools/testing/rbtree/interval_tree_test.c
··· 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 + }
+45
tools/testing/rbtree/rbtree_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * rbtree_test.c: Userspace Red Black Tree test-suite 4 + * Copyright (c) 2025 Wei Yang <richard.weiyang@gmail.com> 5 + */ 6 + #include <linux/init.h> 7 + #include <linux/math64.h> 8 + #include <linux/kern_levels.h> 9 + #include "shared.h" 10 + 11 + #include "../../../lib/rbtree_test.c" 12 + 13 + int usage(void) 14 + { 15 + fprintf(stderr, "Userland rbtree test cases\n"); 16 + fprintf(stderr, " -n: Number of nodes in the rb-tree\n"); 17 + fprintf(stderr, " -p: Number of iterations modifying the rb-tree\n"); 18 + fprintf(stderr, " -c: Number of iterations modifying and verifying the rb-tree\n"); 19 + exit(-1); 20 + } 21 + 22 + void rbtree_tests(void) 23 + { 24 + rbtree_test_init(); 25 + rbtree_test_exit(); 26 + } 27 + 28 + int main(int argc, char **argv) 29 + { 30 + int opt; 31 + 32 + while ((opt = getopt(argc, argv, "n:p:c:")) != -1) { 33 + if (opt == 'n') 34 + nnodes = strtoul(optarg, NULL, 0); 35 + else if (opt == 'p') 36 + perf_loops = strtoul(optarg, NULL, 0); 37 + else if (opt == 'c') 38 + check_loops = strtoul(optarg, NULL, 0); 39 + else 40 + usage(); 41 + } 42 + 43 + rbtree_tests(); 44 + return 0; 45 + }
+4
tools/testing/rbtree/test.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + 3 + void rbtree_tests(void); 4 + void interval_tree_tests(void);
+5
tools/testing/shared/interval_tree-shim.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + /* Very simple shim around the interval tree. */ 4 + 5 + #include "../../../lib/interval_tree.c"
+7
tools/testing/shared/linux/interval_tree.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _TEST_INTERVAL_TREE_H 3 + #define _TEST_INTERVAL_TREE_H 4 + 5 + #include "../../../../include/linux/interval_tree.h" 6 + 7 + #endif /* _TEST_INTERVAL_TREE_H */
+2
tools/testing/shared/linux/interval_tree_generic.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #include "../../../../include/linux/interval_tree_generic.h"
+8
tools/testing/shared/linux/rbtree.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _TEST_RBTREE_H 3 + #define _TEST_RBTREE_H 4 + 5 + #include <linux/kernel.h> 6 + #include "../../../../include/linux/rbtree.h" 7 + 8 + #endif /* _TEST_RBTREE_H */
+7
tools/testing/shared/linux/rbtree_augmented.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _TEST_RBTREE_AUGMENTED_H 3 + #define _TEST_RBTREE_AUGMENTED_H 4 + 5 + #include "../../../../include/linux/rbtree_augmented.h" 6 + 7 + #endif /* _TEST_RBTREE_AUGMENTED_H */
+8
tools/testing/shared/linux/rbtree_types.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _TEST_RBTREE_TYPES_H 3 + #define _TEST_RBTREE_TYPES_H 4 + 5 + #include "../../../../include/linux/rbtree_types.h" 6 + 7 + #endif /* _TEST_RBTREE_TYPES_H */ 8 +
+6
tools/testing/shared/rbtree-shim.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + /* Very simple shim around the rbtree. */ 4 + 5 + #include "../../../lib/rbtree.c" 6 +