0001
0002 #include <stdlib.h>
0003 #include <string.h>
0004 #include <malloc.h>
0005 #include <pthread.h>
0006 #include <unistd.h>
0007 #include <assert.h>
0008
0009 #include <linux/gfp.h>
0010 #include <linux/poison.h>
0011 #include <linux/slab.h>
0012 #include <linux/radix-tree.h>
0013 #include <urcu/uatomic.h>
0014
0015 int nr_allocated;
0016 int preempt_count;
0017 int test_verbose;
0018
0019 struct kmem_cache {
0020 pthread_mutex_t lock;
0021 unsigned int size;
0022 unsigned int align;
0023 int nr_objs;
0024 void *objs;
0025 void (*ctor)(void *);
0026 };
0027
0028 void *kmem_cache_alloc_lru(struct kmem_cache *cachep, struct list_lru *lru,
0029 int gfp)
0030 {
0031 void *p;
0032
0033 if (!(gfp & __GFP_DIRECT_RECLAIM))
0034 return NULL;
0035
0036 pthread_mutex_lock(&cachep->lock);
0037 if (cachep->nr_objs) {
0038 struct radix_tree_node *node = cachep->objs;
0039 cachep->nr_objs--;
0040 cachep->objs = node->parent;
0041 pthread_mutex_unlock(&cachep->lock);
0042 node->parent = NULL;
0043 p = node;
0044 } else {
0045 pthread_mutex_unlock(&cachep->lock);
0046 if (cachep->align)
0047 posix_memalign(&p, cachep->align, cachep->size);
0048 else
0049 p = malloc(cachep->size);
0050 if (cachep->ctor)
0051 cachep->ctor(p);
0052 else if (gfp & __GFP_ZERO)
0053 memset(p, 0, cachep->size);
0054 }
0055
0056 uatomic_inc(&nr_allocated);
0057 if (kmalloc_verbose)
0058 printf("Allocating %p from slab\n", p);
0059 return p;
0060 }
0061
0062 void kmem_cache_free(struct kmem_cache *cachep, void *objp)
0063 {
0064 assert(objp);
0065 uatomic_dec(&nr_allocated);
0066 if (kmalloc_verbose)
0067 printf("Freeing %p to slab\n", objp);
0068 pthread_mutex_lock(&cachep->lock);
0069 if (cachep->nr_objs > 10 || cachep->align) {
0070 memset(objp, POISON_FREE, cachep->size);
0071 free(objp);
0072 } else {
0073 struct radix_tree_node *node = objp;
0074 cachep->nr_objs++;
0075 node->parent = cachep->objs;
0076 cachep->objs = node;
0077 }
0078 pthread_mutex_unlock(&cachep->lock);
0079 }
0080
0081 struct kmem_cache *
0082 kmem_cache_create(const char *name, unsigned int size, unsigned int align,
0083 unsigned int flags, void (*ctor)(void *))
0084 {
0085 struct kmem_cache *ret = malloc(sizeof(*ret));
0086
0087 pthread_mutex_init(&ret->lock, NULL);
0088 ret->size = size;
0089 ret->align = align;
0090 ret->nr_objs = 0;
0091 ret->objs = NULL;
0092 ret->ctor = ctor;
0093 return ret;
0094 }