/* * Slab allocator functions that are independent of the allocator strategy * * (C) 2012 Christoph Lameter */ #include #include #include #include #include #include #include #include #include #include #include #include #include "slab.h" enum slab_state slab_state; LIST_HEAD(slab_caches); DEFINE_MUTEX(slab_mutex); /* * 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 interrupt, but can be interrupted. * The @ctor is run when new pages are allocated by the cache. * * 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 *)) { struct kmem_cache *s = NULL; #ifdef CONFIG_DEBUG_VM if (!name || in_interrupt() || size < sizeof(void *) || size > KMALLOC_MAX_SIZE) { printk(KERN_ERR "kmem_cache_create(%s) integrity check" " failed\n", name); goto out; } #endif get_online_cpus(); mutex_lock(&slab_mutex); #ifdef CONFIG_DEBUG_VM list_for_each_entry(s, &slab_caches, list) { char tmp; int res; /* * This happens when the module gets unloaded and doesn't * destroy its slab cache and no-one else reuses the vmalloc * area of the module. Print a warning. */ res = probe_kernel_address(s->name, tmp); if (res) { printk(KERN_ERR "Slab cache with size %d has lost its name\n", s->object_size); continue; } if (!strcmp(s->name, name)) { printk(KERN_ERR "kmem_cache_create(%s): Cache name" " already exists.\n", name); dump_stack(); s = NULL; goto oops; } } WARN_ON(strchr(name, ' ')); /* It confuses parsers */ #endif s = __kmem_cache_create(name, size, align, flags, ctor); #ifdef CONFIG_DEBUG_VM oops: #endif mutex_unlock(&slab_mutex); put_online_cpus(); #ifdef CONFIG_DEBUG_VM out: #endif if (!s && (flags & SLAB_PANIC)) panic("kmem_cache_create: Failed to create slab '%s'\n", name); return s; } EXPORT_SYMBOL(kmem_cache_create); int slab_is_available(void) { return slab_state >= UP; }