at v4.18 2.3 kB view raw
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 15int nr_allocated; 16int preempt_count; 17int kmalloc_verbose; 18int test_verbose; 19 20struct kmem_cache { 21 pthread_mutex_t lock; 22 int size; 23 int nr_objs; 24 void *objs; 25 void (*ctor)(void *); 26}; 27 28void *kmem_cache_alloc(struct kmem_cache *cachep, int flags) 29{ 30 struct radix_tree_node *node; 31 32 if (!(flags & __GFP_DIRECT_RECLAIM)) 33 return NULL; 34 35 pthread_mutex_lock(&cachep->lock); 36 if (cachep->nr_objs) { 37 cachep->nr_objs--; 38 node = cachep->objs; 39 cachep->objs = node->parent; 40 pthread_mutex_unlock(&cachep->lock); 41 node->parent = NULL; 42 } else { 43 pthread_mutex_unlock(&cachep->lock); 44 node = malloc(cachep->size); 45 if (cachep->ctor) 46 cachep->ctor(node); 47 } 48 49 uatomic_inc(&nr_allocated); 50 if (kmalloc_verbose) 51 printf("Allocating %p from slab\n", node); 52 return node; 53} 54 55void kmem_cache_free(struct kmem_cache *cachep, void *objp) 56{ 57 assert(objp); 58 uatomic_dec(&nr_allocated); 59 if (kmalloc_verbose) 60 printf("Freeing %p to slab\n", objp); 61 pthread_mutex_lock(&cachep->lock); 62 if (cachep->nr_objs > 10) { 63 memset(objp, POISON_FREE, cachep->size); 64 free(objp); 65 } else { 66 struct radix_tree_node *node = objp; 67 cachep->nr_objs++; 68 node->parent = cachep->objs; 69 cachep->objs = node; 70 } 71 pthread_mutex_unlock(&cachep->lock); 72} 73 74void *kmalloc(size_t size, gfp_t gfp) 75{ 76 void *ret; 77 78 if (!(gfp & __GFP_DIRECT_RECLAIM)) 79 return NULL; 80 81 ret = malloc(size); 82 uatomic_inc(&nr_allocated); 83 if (kmalloc_verbose) 84 printf("Allocating %p from malloc\n", ret); 85 if (gfp & __GFP_ZERO) 86 memset(ret, 0, size); 87 return ret; 88} 89 90void kfree(void *p) 91{ 92 if (!p) 93 return; 94 uatomic_dec(&nr_allocated); 95 if (kmalloc_verbose) 96 printf("Freeing %p to malloc\n", p); 97 free(p); 98} 99 100struct kmem_cache * 101kmem_cache_create(const char *name, size_t size, size_t offset, 102 unsigned long flags, void (*ctor)(void *)) 103{ 104 struct kmem_cache *ret = malloc(sizeof(*ret)); 105 106 pthread_mutex_init(&ret->lock, NULL); 107 ret->size = size; 108 ret->nr_objs = 0; 109 ret->objs = NULL; 110 ret->ctor = ctor; 111 return ret; 112}