mirror of
https://github.com/torvalds/linux.git
synced 2025-04-12 06:49:52 +00:00
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>
This commit is contained in:
parent
bc2f19d653
commit
4164e1525d
13
tools/include/asm/timex.h
Normal file
13
tools/include/asm/timex.h
Normal file
@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __TOOLS_LINUX_ASM_TIMEX_H
|
||||
#define __TOOLS_LINUX_ASM_TIMEX_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#define cycles_t clock_t
|
||||
|
||||
static inline cycles_t get_cycles(void)
|
||||
{
|
||||
return clock();
|
||||
}
|
||||
#endif // __TOOLS_LINUX_ASM_TIMEX_H
|
18
tools/include/linux/container_of.h
Normal file
18
tools/include/linux/container_of.h
Normal file
@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _TOOLS_LINUX_CONTAINER_OF_H
|
||||
#define _TOOLS_LINUX_CONTAINER_OF_H
|
||||
|
||||
#ifndef container_of
|
||||
/**
|
||||
* container_of - cast a member of a structure out to the containing structure
|
||||
* @ptr: the pointer to the member.
|
||||
* @type: the type of the container struct this is embedded in.
|
||||
* @member: the name of the member within the struct.
|
||||
*
|
||||
*/
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
const typeof(((type *)0)->member) * __mptr = (ptr); \
|
||||
(type *)((char *)__mptr - offsetof(type, member)); })
|
||||
#endif
|
||||
|
||||
#endif /* _TOOLS_LINUX_CONTAINER_OF_H */
|
@ -11,6 +11,7 @@
|
||||
#include <linux/panic.h>
|
||||
#include <endian.h>
|
||||
#include <byteswap.h>
|
||||
#include <linux/container_of.h>
|
||||
|
||||
#ifndef UINT_MAX
|
||||
#define UINT_MAX (~0U)
|
||||
@ -25,19 +26,6 @@
|
||||
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
||||
#endif
|
||||
|
||||
#ifndef container_of
|
||||
/**
|
||||
* container_of - cast a member of a structure out to the containing structure
|
||||
* @ptr: the pointer to the member.
|
||||
* @type: the type of the container struct this is embedded in.
|
||||
* @member: the name of the member within the struct.
|
||||
*
|
||||
*/
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
const typeof(((type *)0)->member) * __mptr = (ptr); \
|
||||
(type *)((char *)__mptr - offsetof(type, member)); })
|
||||
#endif
|
||||
|
||||
#ifndef max
|
||||
#define max(x, y) ({ \
|
||||
typeof(x) _max1 = (x); \
|
||||
|
@ -72,4 +72,9 @@ static inline u64 mul_u64_u64_div64(u64 a, u64 b, u64 c)
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline u64 div_u64(u64 dividend, u32 divisor)
|
||||
{
|
||||
return dividend / divisor;
|
||||
}
|
||||
|
||||
#endif /* _LINUX_MATH64_H */
|
||||
|
7
tools/include/linux/moduleparam.h
Normal file
7
tools/include/linux/moduleparam.h
Normal file
@ -0,0 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _TOOLS_LINUX_MODULE_PARAMS_H
|
||||
#define _TOOLS_LINUX_MODULE_PARAMS_H
|
||||
|
||||
#define MODULE_PARM_DESC(parm, desc)
|
||||
|
||||
#endif // _TOOLS_LINUX_MODULE_PARAMS_H
|
51
tools/include/linux/prandom.h
Normal file
51
tools/include/linux/prandom.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __TOOLS_LINUX_PRANDOM_H
|
||||
#define __TOOLS_LINUX_PRANDOM_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct rnd_state {
|
||||
__u32 s1, s2, s3, s4;
|
||||
};
|
||||
|
||||
/*
|
||||
* Handle minimum values for seeds
|
||||
*/
|
||||
static inline u32 __seed(u32 x, u32 m)
|
||||
{
|
||||
return (x < m) ? x + m : x;
|
||||
}
|
||||
|
||||
/**
|
||||
* prandom_seed_state - set seed for prandom_u32_state().
|
||||
* @state: pointer to state structure to receive the seed.
|
||||
* @seed: arbitrary 64-bit value to use as a seed.
|
||||
*/
|
||||
static inline void prandom_seed_state(struct rnd_state *state, u64 seed)
|
||||
{
|
||||
u32 i = ((seed >> 32) ^ (seed << 10) ^ seed) & 0xffffffffUL;
|
||||
|
||||
state->s1 = __seed(i, 2U);
|
||||
state->s2 = __seed(i, 8U);
|
||||
state->s3 = __seed(i, 16U);
|
||||
state->s4 = __seed(i, 128U);
|
||||
}
|
||||
|
||||
/**
|
||||
* prandom_u32_state - seeded pseudo-random number generator.
|
||||
* @state: pointer to state structure holding seeded state.
|
||||
*
|
||||
* This is used for pseudo-randomness with no outside seeding.
|
||||
* For more random results, use get_random_u32().
|
||||
*/
|
||||
static inline u32 prandom_u32_state(struct rnd_state *state)
|
||||
{
|
||||
#define TAUSWORTHE(s, a, b, c, d) (((s & c) << d) ^ (((s << a) ^ s) >> b))
|
||||
state->s1 = TAUSWORTHE(state->s1, 6U, 13U, 4294967294U, 18U);
|
||||
state->s2 = TAUSWORTHE(state->s2, 2U, 27U, 4294967288U, 2U);
|
||||
state->s3 = TAUSWORTHE(state->s3, 13U, 21U, 4294967280U, 7U);
|
||||
state->s4 = TAUSWORTHE(state->s4, 3U, 12U, 4294967168U, 13U);
|
||||
|
||||
return (state->s1 ^ state->s2 ^ state->s3 ^ state->s4);
|
||||
}
|
||||
#endif // __TOOLS_LINUX_PRANDOM_H
|
@ -12,6 +12,7 @@
|
||||
|
||||
void *kmalloc(size_t size, gfp_t gfp);
|
||||
void kfree(void *p);
|
||||
void *kmalloc_array(size_t n, size_t size, gfp_t gfp);
|
||||
|
||||
bool slab_is_available(void);
|
||||
|
||||
|
@ -36,3 +36,19 @@ void kfree(void *p)
|
||||
printf("Freeing %p to malloc\n", p);
|
||||
free(p);
|
||||
}
|
||||
|
||||
void *kmalloc_array(size_t n, size_t size, gfp_t gfp)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
if (!(gfp & __GFP_DIRECT_RECLAIM))
|
||||
return NULL;
|
||||
|
||||
ret = calloc(n, size);
|
||||
uatomic_inc(&kmalloc_nr_allocated);
|
||||
if (kmalloc_verbose)
|
||||
printf("Allocating %p from calloc\n", ret);
|
||||
if (gfp & __GFP_ZERO)
|
||||
memset(ret, 0, n * size);
|
||||
return ret;
|
||||
}
|
||||
|
31
tools/testing/rbtree/Makefile
Normal file
31
tools/testing/rbtree/Makefile
Normal file
@ -0,0 +1,31 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
TARGETS = rbtree_test interval_tree_test
|
||||
OFILES = $(LIBS) rbtree-shim.o interval_tree-shim.o
|
||||
DEPS = ../../../include/linux/rbtree.h \
|
||||
../../../include/linux/rbtree_types.h \
|
||||
../../../include/linux/rbtree_augmented.h \
|
||||
../../../include/linux/interval_tree.h \
|
||||
../../../include/linux/interval_tree_generic.h \
|
||||
../../../lib/rbtree.c \
|
||||
../../../lib/interval_tree.c
|
||||
|
||||
targets: $(TARGETS)
|
||||
|
||||
include ../shared/shared.mk
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -g
|
||||
endif
|
||||
|
||||
$(TARGETS): $(OFILES)
|
||||
|
||||
rbtree-shim.o: $(DEPS)
|
||||
rbtree_test.o: ../../../lib/rbtree_test.c
|
||||
interval_tree-shim.o: $(DEPS)
|
||||
interval_tree_test.o: ../../../lib/interval_tree_test.c
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGETS) *.o generated/*
|
53
tools/testing/rbtree/interval_tree_test.c
Normal file
53
tools/testing/rbtree/interval_tree_test.c
Normal file
@ -0,0 +1,53 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* interval_tree.c: Userspace Interval Tree test-suite
|
||||
* Copyright (c) 2025 Wei Yang <richard.weiyang@gmail.com>
|
||||
*/
|
||||
#include <linux/math64.h>
|
||||
#include <linux/kern_levels.h>
|
||||
#include "shared.h"
|
||||
|
||||
#include "../../../lib/interval_tree_test.c"
|
||||
|
||||
int usage(void)
|
||||
{
|
||||
fprintf(stderr, "Userland interval tree test cases\n");
|
||||
fprintf(stderr, " -n: Number of nodes in the interval tree\n");
|
||||
fprintf(stderr, " -p: Number of iterations modifying the tree\n");
|
||||
fprintf(stderr, " -q: Number of searches to the interval tree\n");
|
||||
fprintf(stderr, " -s: Number of iterations searching the tree\n");
|
||||
fprintf(stderr, " -a: Searches will iterate all nodes in the tree\n");
|
||||
fprintf(stderr, " -m: Largest value for the interval's endpoint\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void interval_tree_tests(void)
|
||||
{
|
||||
interval_tree_test_init();
|
||||
interval_tree_test_exit();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "n:p:q:s:am:")) != -1) {
|
||||
if (opt == 'n')
|
||||
nnodes = strtoul(optarg, NULL, 0);
|
||||
else if (opt == 'p')
|
||||
perf_loops = strtoul(optarg, NULL, 0);
|
||||
else if (opt == 'q')
|
||||
nsearches = strtoul(optarg, NULL, 0);
|
||||
else if (opt == 's')
|
||||
search_loops = strtoul(optarg, NULL, 0);
|
||||
else if (opt == 'a')
|
||||
search_all = true;
|
||||
else if (opt == 'm')
|
||||
max_endpoint = strtoul(optarg, NULL, 0);
|
||||
else
|
||||
usage();
|
||||
}
|
||||
|
||||
interval_tree_tests();
|
||||
return 0;
|
||||
}
|
45
tools/testing/rbtree/rbtree_test.c
Normal file
45
tools/testing/rbtree/rbtree_test.c
Normal file
@ -0,0 +1,45 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* rbtree_test.c: Userspace Red Black Tree test-suite
|
||||
* Copyright (c) 2025 Wei Yang <richard.weiyang@gmail.com>
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/kern_levels.h>
|
||||
#include "shared.h"
|
||||
|
||||
#include "../../../lib/rbtree_test.c"
|
||||
|
||||
int usage(void)
|
||||
{
|
||||
fprintf(stderr, "Userland rbtree test cases\n");
|
||||
fprintf(stderr, " -n: Number of nodes in the rb-tree\n");
|
||||
fprintf(stderr, " -p: Number of iterations modifying the rb-tree\n");
|
||||
fprintf(stderr, " -c: Number of iterations modifying and verifying the rb-tree\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void rbtree_tests(void)
|
||||
{
|
||||
rbtree_test_init();
|
||||
rbtree_test_exit();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "n:p:c:")) != -1) {
|
||||
if (opt == 'n')
|
||||
nnodes = strtoul(optarg, NULL, 0);
|
||||
else if (opt == 'p')
|
||||
perf_loops = strtoul(optarg, NULL, 0);
|
||||
else if (opt == 'c')
|
||||
check_loops = strtoul(optarg, NULL, 0);
|
||||
else
|
||||
usage();
|
||||
}
|
||||
|
||||
rbtree_tests();
|
||||
return 0;
|
||||
}
|
4
tools/testing/rbtree/test.h
Normal file
4
tools/testing/rbtree/test.h
Normal file
@ -0,0 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
void rbtree_tests(void);
|
||||
void interval_tree_tests(void);
|
5
tools/testing/shared/interval_tree-shim.c
Normal file
5
tools/testing/shared/interval_tree-shim.c
Normal file
@ -0,0 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
/* Very simple shim around the interval tree. */
|
||||
|
||||
#include "../../../lib/interval_tree.c"
|
7
tools/testing/shared/linux/interval_tree.h
Normal file
7
tools/testing/shared/linux/interval_tree.h
Normal file
@ -0,0 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _TEST_INTERVAL_TREE_H
|
||||
#define _TEST_INTERVAL_TREE_H
|
||||
|
||||
#include "../../../../include/linux/interval_tree.h"
|
||||
|
||||
#endif /* _TEST_INTERVAL_TREE_H */
|
2
tools/testing/shared/linux/interval_tree_generic.h
Normal file
2
tools/testing/shared/linux/interval_tree_generic.h
Normal file
@ -0,0 +1,2 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include "../../../../include/linux/interval_tree_generic.h"
|
8
tools/testing/shared/linux/rbtree.h
Normal file
8
tools/testing/shared/linux/rbtree.h
Normal file
@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _TEST_RBTREE_H
|
||||
#define _TEST_RBTREE_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include "../../../../include/linux/rbtree.h"
|
||||
|
||||
#endif /* _TEST_RBTREE_H */
|
7
tools/testing/shared/linux/rbtree_augmented.h
Normal file
7
tools/testing/shared/linux/rbtree_augmented.h
Normal file
@ -0,0 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _TEST_RBTREE_AUGMENTED_H
|
||||
#define _TEST_RBTREE_AUGMENTED_H
|
||||
|
||||
#include "../../../../include/linux/rbtree_augmented.h"
|
||||
|
||||
#endif /* _TEST_RBTREE_AUGMENTED_H */
|
8
tools/testing/shared/linux/rbtree_types.h
Normal file
8
tools/testing/shared/linux/rbtree_types.h
Normal file
@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _TEST_RBTREE_TYPES_H
|
||||
#define _TEST_RBTREE_TYPES_H
|
||||
|
||||
#include "../../../../include/linux/rbtree_types.h"
|
||||
|
||||
#endif /* _TEST_RBTREE_TYPES_H */
|
||||
|
6
tools/testing/shared/rbtree-shim.c
Normal file
6
tools/testing/shared/rbtree-shim.c
Normal file
@ -0,0 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
/* Very simple shim around the rbtree. */
|
||||
|
||||
#include "../../../lib/rbtree.c"
|
||||
|
Loading…
x
Reference in New Issue
Block a user