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