diff options
Diffstat (limited to 'tools/testing/radix-tree/linux.c')
-rw-r--r-- | tools/testing/radix-tree/linux.c | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/tools/testing/radix-tree/linux.c b/tools/testing/radix-tree/linux.c new file mode 100644 index 000000000..2d9c59df6 --- /dev/null +++ b/tools/testing/radix-tree/linux.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <stdlib.h> +#include <string.h> +#include <malloc.h> +#include <pthread.h> +#include <unistd.h> +#include <assert.h> + +#include <linux/gfp.h> +#include <linux/poison.h> +#include <linux/slab.h> +#include <linux/radix-tree.h> +#include <urcu/uatomic.h> + +int nr_allocated; +int preempt_count; +int kmalloc_verbose; +int test_verbose; + +struct kmem_cache { + pthread_mutex_t lock; + unsigned int size; + unsigned int align; + int nr_objs; + void *objs; + void (*ctor)(void *); +}; + +void *kmem_cache_alloc(struct kmem_cache *cachep, int gfp) +{ + void *p; + + if (!(gfp & __GFP_DIRECT_RECLAIM)) + return NULL; + + pthread_mutex_lock(&cachep->lock); + if (cachep->nr_objs) { + struct radix_tree_node *node = cachep->objs; + cachep->nr_objs--; + cachep->objs = node->parent; + pthread_mutex_unlock(&cachep->lock); + node->parent = NULL; + p = node; + } else { + pthread_mutex_unlock(&cachep->lock); + if (cachep->align) + posix_memalign(&p, cachep->align, cachep->size); + else + p = malloc(cachep->size); + if (cachep->ctor) + cachep->ctor(p); + else if (gfp & __GFP_ZERO) + memset(p, 0, cachep->size); + } + + uatomic_inc(&nr_allocated); + if (kmalloc_verbose) + printf("Allocating %p from slab\n", p); + return p; +} + +void kmem_cache_free(struct kmem_cache *cachep, void *objp) +{ + assert(objp); + uatomic_dec(&nr_allocated); + if (kmalloc_verbose) + printf("Freeing %p to slab\n", objp); + pthread_mutex_lock(&cachep->lock); + if (cachep->nr_objs > 10 || cachep->align) { + memset(objp, POISON_FREE, cachep->size); + free(objp); + } else { + struct radix_tree_node *node = objp; + cachep->nr_objs++; + node->parent = cachep->objs; + cachep->objs = node; + } + pthread_mutex_unlock(&cachep->lock); +} + +void *kmalloc(size_t size, gfp_t gfp) +{ + void *ret; + + if (!(gfp & __GFP_DIRECT_RECLAIM)) + return NULL; + + ret = malloc(size); + uatomic_inc(&nr_allocated); + if (kmalloc_verbose) + printf("Allocating %p from malloc\n", ret); + if (gfp & __GFP_ZERO) + memset(ret, 0, size); + return ret; +} + +void kfree(void *p) +{ + if (!p) + return; + uatomic_dec(&nr_allocated); + if (kmalloc_verbose) + printf("Freeing %p to malloc\n", p); + free(p); +} + +struct kmem_cache * +kmem_cache_create(const char *name, unsigned int size, unsigned int align, + unsigned int flags, void (*ctor)(void *)) +{ + struct kmem_cache *ret = malloc(sizeof(*ret)); + + pthread_mutex_init(&ret->lock, NULL); + ret->size = size; + ret->align = align; + ret->nr_objs = 0; + ret->objs = NULL; + ret->ctor = ctor; + return ret; +} |