at v5.12 2.5 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 unsigned int size; 23 unsigned int align; 24 int nr_objs; 25 void *objs; 26 void (*ctor)(void *); 27}; 28 29void *kmem_cache_alloc(struct kmem_cache *cachep, 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 62void 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 81void *kmalloc(size_t size, gfp_t gfp) 82{ 83 void *ret; 84 85 if (!(gfp & __GFP_DIRECT_RECLAIM)) 86 return NULL; 87 88 ret = malloc(size); 89 uatomic_inc(&nr_allocated); 90 if (kmalloc_verbose) 91 printf("Allocating %p from malloc\n", ret); 92 if (gfp & __GFP_ZERO) 93 memset(ret, 0, size); 94 return ret; 95} 96 97void kfree(void *p) 98{ 99 if (!p) 100 return; 101 uatomic_dec(&nr_allocated); 102 if (kmalloc_verbose) 103 printf("Freeing %p to malloc\n", p); 104 free(p); 105} 106 107struct kmem_cache * 108kmem_cache_create(const char *name, unsigned int size, unsigned int align, 109 unsigned int flags, void (*ctor)(void *)) 110{ 111 struct kmem_cache *ret = malloc(sizeof(*ret)); 112 113 pthread_mutex_init(&ret->lock, NULL); 114 ret->size = size; 115 ret->align = align; 116 ret->nr_objs = 0; 117 ret->objs = NULL; 118 ret->ctor = ctor; 119 return ret; 120}