diff options
Diffstat (limited to 'mm/slab_common.c')
| -rw-r--r-- | mm/slab_common.c | 120 | 
1 files changed, 120 insertions, 0 deletions
diff --git a/mm/slab_common.c b/mm/slab_common.c new file mode 100644 index 000000000000..aa3ca5bb01b5 --- /dev/null +++ b/mm/slab_common.c @@ -0,0 +1,120 @@ +/* + * Slab allocator functions that are independent of the allocator strategy + * + * (C) 2012 Christoph Lameter <cl@linux.com> + */ +#include <linux/slab.h> + +#include <linux/mm.h> +#include <linux/poison.h> +#include <linux/interrupt.h> +#include <linux/memory.h> +#include <linux/compiler.h> +#include <linux/module.h> +#include <linux/cpu.h> +#include <linux/uaccess.h> +#include <asm/cacheflush.h> +#include <asm/tlbflush.h> +#include <asm/page.h> + +#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; +}  | 
