2012-07-06 15:25:10 -05:00
/*
* 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>
2012-07-06 15:25:13 -05:00
# include <linux/cpu.h>
# include <linux/uaccess.h>
2012-07-06 15:25:10 -05:00
# include <asm/cacheflush.h>
# include <asm/tlbflush.h>
# include <asm/page.h>
2012-07-06 15:25:11 -05:00
# include "slab.h"
enum slab_state slab_state ;
2012-07-06 15:25:12 -05:00
LIST_HEAD ( slab_caches ) ;
DEFINE_MUTEX ( slab_mutex ) ;
2012-07-06 15:25:11 -05:00
2012-07-06 15:25:10 -05:00
/*
* 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
2012-07-06 15:25:13 -05:00
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
2012-07-06 15:25:10 -05:00
s = __kmem_cache_create ( name , size , align , flags , ctor ) ;
2012-07-13 17:12:05 -06:00
# ifdef CONFIG_DEBUG_VM
2012-07-06 15:25:13 -05:00
oops :
2012-07-13 17:12:05 -06:00
# endif
2012-07-06 15:25:13 -05:00
mutex_unlock ( & slab_mutex ) ;
put_online_cpus ( ) ;
2012-07-06 15:25:10 -05:00
# 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 ) ;
2012-07-06 15:25:11 -05:00
int slab_is_available ( void )
{
return slab_state > = UP ;
}