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_lru(struct kmem_cache *cachep, struct list_lru *lru, 29 int gfp) 30 { 31 void *p; 32 33 if (!(gfp & __GFP_DIRECT_RECLAIM)) 34 return NULL; 35 36 pthread_mutex_lock(&cachep->lock); 37 if (cachep->nr_objs) { 38 struct radix_tree_node *node = cachep->objs; 39 cachep->nr_objs--; 40 cachep->objs = node->parent; 41 pthread_mutex_unlock(&cachep->lock); 42 node->parent = NULL; 43 p = node; 44 } else { 45 pthread_mutex_unlock(&cachep->lock); 46 if (cachep->align) 47 posix_memalign(&p, cachep->align, cachep->size); 48 else 49 p = malloc(cachep->size); 50 if (cachep->ctor) 51 cachep->ctor(p); 52 else if (gfp & __GFP_ZERO) 53 memset(p, 0, cachep->size); 54 } 55 56 uatomic_inc(&nr_allocated); 57 if (kmalloc_verbose) 58 printf("Allocating %p from slab\n", p); 59 return p; 60 } 61 62 void kmem_cache_free(struct kmem_cache *cachep, void *objp) 63 { 64 assert(objp); 65 uatomic_dec(&nr_allocated); 66 if (kmalloc_verbose) 67 printf("Freeing %p to slab\n", objp); 68 pthread_mutex_lock(&cachep->lock); 69 if (cachep->nr_objs > 10 || cachep->align) { 70 memset(objp, POISON_FREE, cachep->size); 71 free(objp); 72 } else { 73 struct radix_tree_node *node = objp; 74 cachep->nr_objs++; 75 node->parent = cachep->objs; 76 cachep->objs = node; 77 } 78 pthread_mutex_unlock(&cachep->lock); 79 } 80 81 struct kmem_cache * 82 kmem_cache_create(const char *name, unsigned int size, unsigned int align, 83 unsigned int flags, void (*ctor)(void *)) 84 { 85 struct kmem_cache *ret = malloc(sizeof(*ret)); 86 87 pthread_mutex_init(&ret->lock, NULL); 88 ret->size = size; 89 ret->align = align; 90 ret->nr_objs = 0; 91 ret->objs = NULL; 92 ret->ctor = ctor; 93 return ret; 94 } 95