xref: /openbmc/linux/tools/testing/radix-tree/linux.c (revision bcb84fb4)
1 #include <stdlib.h>
2 #include <string.h>
3 #include <malloc.h>
4 #include <pthread.h>
5 #include <unistd.h>
6 #include <assert.h>
7 
8 #include <linux/gfp.h>
9 #include <linux/poison.h>
10 #include <linux/slab.h>
11 #include <linux/radix-tree.h>
12 #include <urcu/uatomic.h>
13 
14 int nr_allocated;
15 int preempt_count;
16 int kmalloc_verbose;
17 int test_verbose;
18 
19 struct kmem_cache {
20 	pthread_mutex_t lock;
21 	int size;
22 	int nr_objs;
23 	void *objs;
24 	void (*ctor)(void *);
25 };
26 
27 void *kmem_cache_alloc(struct kmem_cache *cachep, int flags)
28 {
29 	struct radix_tree_node *node;
30 
31 	if (flags & __GFP_NOWARN)
32 		return NULL;
33 
34 	pthread_mutex_lock(&cachep->lock);
35 	if (cachep->nr_objs) {
36 		cachep->nr_objs--;
37 		node = cachep->objs;
38 		cachep->objs = node->parent;
39 		pthread_mutex_unlock(&cachep->lock);
40 		node->parent = NULL;
41 	} else {
42 		pthread_mutex_unlock(&cachep->lock);
43 		node = malloc(cachep->size);
44 		if (cachep->ctor)
45 			cachep->ctor(node);
46 	}
47 
48 	uatomic_inc(&nr_allocated);
49 	if (kmalloc_verbose)
50 		printf("Allocating %p from slab\n", node);
51 	return node;
52 }
53 
54 void kmem_cache_free(struct kmem_cache *cachep, void *objp)
55 {
56 	assert(objp);
57 	uatomic_dec(&nr_allocated);
58 	if (kmalloc_verbose)
59 		printf("Freeing %p to slab\n", objp);
60 	pthread_mutex_lock(&cachep->lock);
61 	if (cachep->nr_objs > 10) {
62 		memset(objp, POISON_FREE, cachep->size);
63 		free(objp);
64 	} else {
65 		struct radix_tree_node *node = objp;
66 		cachep->nr_objs++;
67 		node->parent = cachep->objs;
68 		cachep->objs = node;
69 	}
70 	pthread_mutex_unlock(&cachep->lock);
71 }
72 
73 void *kmalloc(size_t size, gfp_t gfp)
74 {
75 	void *ret = malloc(size);
76 	uatomic_inc(&nr_allocated);
77 	if (kmalloc_verbose)
78 		printf("Allocating %p from malloc\n", ret);
79 	return ret;
80 }
81 
82 void kfree(void *p)
83 {
84 	if (!p)
85 		return;
86 	uatomic_dec(&nr_allocated);
87 	if (kmalloc_verbose)
88 		printf("Freeing %p to malloc\n", p);
89 	free(p);
90 }
91 
92 struct kmem_cache *
93 kmem_cache_create(const char *name, size_t size, size_t offset,
94 	unsigned long flags, void (*ctor)(void *))
95 {
96 	struct kmem_cache *ret = malloc(sizeof(*ret));
97 
98 	pthread_mutex_init(&ret->lock, NULL);
99 	ret->size = size;
100 	ret->nr_objs = 0;
101 	ret->objs = NULL;
102 	ret->ctor = ctor;
103 	return ret;
104 }
105