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