diff options
Diffstat (limited to 'libdde-linux26/lib/src/arch/l4/kmem_cache.c')
| -rw-r--r-- | libdde-linux26/lib/src/arch/l4/kmem_cache.c | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/libdde-linux26/lib/src/arch/l4/kmem_cache.c b/libdde-linux26/lib/src/arch/l4/kmem_cache.c new file mode 100644 index 00000000..5e44c140 --- /dev/null +++ b/libdde-linux26/lib/src/arch/l4/kmem_cache.c @@ -0,0 +1,211 @@ +/* + * \brief Kmem_cache implementation + * \author Christian Helmuth + * \date 2007-01-22 + * + * In Linux 2.6 this resides in mm/slab.c. + * + * I'll disregard the following function currently... + * + * extern struct kmem_cache *kmem_find_general_cachep(size_t size, gfp_t gfpflags); + * extern void *kmem_cache_zalloc(struct kmem_cache *, gfp_t); + */ + +/* Linux */ +#include <linux/slab.h> + +#include "local.h" + + +/******************* + ** Configuration ** + *******************/ + +#define DEBUG_SLAB 0 + +#if DEBUG_SLAB +# define DEBUG_SLAB_ALLOC 1 +#else +# define DEBUG_SLAB_ALLOC 0 +#endif + +/* + * Kmem cache structure + */ +struct kmem_cache +{ + const char *name; /**< cache name */ + unsigned size; /**< obj size */ + + struct ddekit_slab *ddekit_slab_cache; /**< backing DDEKit cache */ + ddekit_lock_t cache_lock; /**< lock */ + void (*ctor)(void *); /**< object constructor */ +}; + + +/** + * Return size of objects in cache + */ +unsigned int kmem_cache_size(struct kmem_cache *cache) +{ + return cache->size; +} + + +/** + * Return name of cache + */ +const char *kmem_cache_name(struct kmem_cache *cache) +{ + return cache->name; +} + + +/** + * kmem_cache_shrink - Shrink a cache. + * @cachep: The cache to shrink. + * + * Releases as many slabs as possible for a cache. + * To help debugging, a zero exit status indicates all slabs were released. + */ +int kmem_cache_shrink(struct kmem_cache *cache) +{ + /* noop */ + return 1; +} + + +/** + * kmem_cache_free - Deallocate an object + * @cachep: The cache the allocation was from. + * @objp: The previously allocated object. + * + * Free an object which was previously allocated from this + * cache. + */ +void kmem_cache_free(struct kmem_cache *cache, void *objp) +{ + ddekit_log(DEBUG_SLAB_ALLOC, "\"%s\" (%p)", cache->name, objp); + + ddekit_lock_lock(&cache->cache_lock); + ddekit_slab_free(cache->ddekit_slab_cache, objp); + ddekit_lock_unlock(&cache->cache_lock); +} + + +/** + * kmem_cache_alloc - Allocate an object + * @cachep: The cache to allocate from. + * @flags: See kmalloc(). + * + * Allocate an object from this cache. The flags are only relevant + * if the cache has no available objects. + */ +void *kmem_cache_alloc(struct kmem_cache *cache, gfp_t flags) +{ + void *ret; + + ddekit_log(DEBUG_SLAB_ALLOC, "\"%s\" flags=%x", cache->name, flags); + + ddekit_lock_lock(&cache->cache_lock); + ret = ddekit_slab_alloc(cache->ddekit_slab_cache); + ddekit_lock_unlock(&cache->cache_lock); + + // XXX: is it valid to run ctor AND memset to zero? + if (flags & __GFP_ZERO) + memset(ret, 0, cache->size); + else if (cache->ctor) + cache->ctor(ret); + + return ret; +} + + +/** + * kmem_cache_destroy - delete a cache + * @cachep: the cache to destroy + * + * Remove a struct kmem_cache object from the slab cache. + * Returns 0 on success. + * + * It is expected this function will be called by a module when it is + * unloaded. This will remove the cache completely, and avoid a duplicate + * cache being allocated each time a module is loaded and unloaded, if the + * module doesn't have persistent in-kernel storage across loads and unloads. + * + * The cache must be empty before calling this function. + * + * The caller must guarantee that noone will allocate memory from the cache + * during the kmem_cache_destroy(). + */ +void kmem_cache_destroy(struct kmem_cache *cache) +{ + ddekit_log(DEBUG_SLAB, "\"%s\"", cache->name); + + ddekit_slab_destroy(cache->ddekit_slab_cache); + ddekit_simple_free(cache); +} + + +/** + * kmem_cache_create - Create a cache. + * @name: A string which is used in /proc/slabinfo to identify this cache. + * @size: The size of objects to be created in this cache. + * @align: The required alignment for the objects. + * @flags: SLAB flags + * @ctor: A constructor for the objects. + * + * Returns a ptr to the cache on success, NULL on failure. + * Cannot be called within a int, but can be interrupted. + * The @ctor is run when new pages are allocated by the cache + * and the @dtor is run before the pages are handed back. + * + * @name must be valid until the cache is destroyed. This implies that + * the module calling this has to destroy the cache before getting unloaded. + * + * The flags are + * + * %SLAB_POISON - Poison the slab with a known test pattern (a5a5a5a5) + * to catch references to uninitialised memory. + * + * %SLAB_RED_ZONE - Insert `Red' zones around the allocated memory to check + * for buffer overruns. + * + * %SLAB_HWCACHE_ALIGN - Align the objects in this cache to a hardware + * cacheline. This can be beneficial if you're counting cycles as closely + * as davem. + */ +struct kmem_cache * kmem_cache_create(const char *name, size_t size, size_t align, + unsigned long flags, + void (*ctor)(void *)) +{ + ddekit_log(DEBUG_SLAB, "\"%s\" obj_size=%d", name, size); + + struct kmem_cache *cache; + + if (!name) { + printk("kmem_cache name reqeuired\n"); + return 0; + } + + cache = ddekit_simple_malloc(sizeof(*cache)); + if (!cache) { + printk("No memory for slab cache\n"); + return 0; + } + + /* Initialize a physically contiguous cache for kmem */ + if (!(cache->ddekit_slab_cache = ddekit_slab_init(size, 1))) { + printk("DDEKit slab init failed\n"); + ddekit_simple_free(cache); + return 0; + } + + cache->name = name; + cache->size = size; + cache->ctor = ctor; + + ddekit_lock_init_unlocked(&cache->cache_lock); + + return cache; +} |
