slub_def.h 5.0 KB
Newer Older
C
Christoph Lameter 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#ifndef _LINUX_SLUB_DEF_H
#define _LINUX_SLUB_DEF_H

/*
 * SLUB : A Slab allocator without object queues.
 *
 * (C) 2007 SGI, Christoph Lameter <clameter@sgi.com>
 */
#include <linux/types.h>
#include <linux/gfp.h>
#include <linux/workqueue.h>
#include <linux/kobject.h>

struct kmem_cache_node {
	spinlock_t list_lock;	/* Protect partial list and nr_partial */
	unsigned long nr_partial;
	atomic_long_t nr_slabs;
	struct list_head partial;
19
#ifdef CONFIG_SLUB_DEBUG
20
	struct list_head full;
21
#endif
C
Christoph Lameter 已提交
22 23 24 25 26 27 28 29 30 31 32
};

/*
 * Slab cache management.
 */
struct kmem_cache {
	/* Used for retriving partial slabs etc */
	unsigned long flags;
	int size;		/* The size of an object including meta data */
	int objsize;		/* The size of an object without meta data */
	int offset;		/* Free pointer offset. */
33
	int order;
C
Christoph Lameter 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

	/*
	 * Avoid an extra cache line for UP, SMP and for the node local to
	 * struct kmem_cache.
	 */
	struct kmem_cache_node local_node;

	/* Allocation and freeing of slabs */
	int objects;		/* Number of objects in slab */
	int refcount;		/* Refcount for slab cache destroy */
	void (*ctor)(void *, struct kmem_cache *, unsigned long);
	int inuse;		/* Offset to metadata */
	int align;		/* Alignment */
	const char *name;	/* Name (only for display!) */
	struct list_head list;	/* List of slab caches */
49
#ifdef CONFIG_SLUB_DEBUG
C
Christoph Lameter 已提交
50
	struct kobject kobj;	/* For sysfs */
51
#endif
C
Christoph Lameter 已提交
52 53 54 55 56 57 58 59 60 61 62

#ifdef CONFIG_NUMA
	int defrag_ratio;
	struct kmem_cache_node *node[MAX_NUMNODES];
#endif
	struct page *cpu_slab[NR_CPUS];
};

/*
 * Kmalloc subsystem.
 */
63 64 65 66 67 68 69
#if defined(ARCH_KMALLOC_MINALIGN) && ARCH_KMALLOC_MINALIGN > 8
#define KMALLOC_MIN_SIZE ARCH_KMALLOC_MINALIGN
#else
#define KMALLOC_MIN_SIZE 8
#endif

#define KMALLOC_SHIFT_LOW ilog2(KMALLOC_MIN_SIZE)
C
Christoph Lameter 已提交
70 71 72 73 74 75 76 77 78 79 80

/*
 * We keep the general caches in an array of slab caches that are used for
 * 2^x bytes of allocations.
 */
extern struct kmem_cache kmalloc_caches[KMALLOC_SHIFT_HIGH + 1];

/*
 * Sorry that the following has to be that ugly but some versions of GCC
 * have trouble with constant propagation and loops.
 */
81
static inline int kmalloc_index(size_t size)
C
Christoph Lameter 已提交
82
{
83 84
	if (!size)
		return 0;
85

86
	if (size > KMALLOC_MAX_SIZE)
87 88
		return -1;

89 90 91
	if (size <= KMALLOC_MIN_SIZE)
		return KMALLOC_SHIFT_LOW;

C
Christoph Lameter 已提交
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
	if (size > 64 && size <= 96)
		return 1;
	if (size > 128 && size <= 192)
		return 2;
	if (size <=          8) return 3;
	if (size <=         16) return 4;
	if (size <=         32) return 5;
	if (size <=         64) return 6;
	if (size <=        128) return 7;
	if (size <=        256) return 8;
	if (size <=        512) return 9;
	if (size <=       1024) return 10;
	if (size <=   2 * 1024) return 11;
	if (size <=   4 * 1024) return 12;
	if (size <=   8 * 1024) return 13;
	if (size <=  16 * 1024) return 14;
	if (size <=  32 * 1024) return 15;
	if (size <=  64 * 1024) return 16;
	if (size <= 128 * 1024) return 17;
	if (size <= 256 * 1024) return 18;
	if (size <=  512 * 1024) return 19;
	if (size <= 1024 * 1024) return 20;
	if (size <=  2 * 1024 * 1024) return 21;
	if (size <=  4 * 1024 * 1024) return 22;
	if (size <=  8 * 1024 * 1024) return 23;
	if (size <= 16 * 1024 * 1024) return 24;
	if (size <= 32 * 1024 * 1024) return 25;
	return -1;

/*
 * What we really wanted to do and cannot do because of compiler issues is:
 *	int i;
 *	for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++)
 *		if (size <= (1 << i))
 *			return i;
 */
}

/*
 * Find the slab cache for a given combination of allocation flags and size.
 *
 * This ought to end up with a global pointer to the right cache
 * in kmalloc_caches.
 */
static inline struct kmem_cache *kmalloc_slab(size_t size)
{
	int index = kmalloc_index(size);

	if (index == 0)
		return NULL;

143 144 145 146 147 148
	/*
	 * This function only gets expanded if __builtin_constant_p(size), so
	 * testing it here shouldn't be needed.  But some versions of gcc need
	 * help.
	 */
	if (__builtin_constant_p(size) && index < 0) {
C
Christoph Lameter 已提交
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
		/*
		 * Generate a link failure. Would be great if we could
		 * do something to stop the compile here.
		 */
		extern void __kmalloc_size_too_large(void);
		__kmalloc_size_too_large();
	}
	return &kmalloc_caches[index];
}

#ifdef CONFIG_ZONE_DMA
#define SLUB_DMA __GFP_DMA
#else
/* Disable DMA functionality */
#define SLUB_DMA 0
#endif

P
Paul Mundt 已提交
166 167 168
void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
void *__kmalloc(size_t size, gfp_t flags);

C
Christoph Lameter 已提交
169 170 171 172 173 174
static inline void *kmalloc(size_t size, gfp_t flags)
{
	if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) {
		struct kmem_cache *s = kmalloc_slab(size);

		if (!s)
175
			return ZERO_SIZE_PTR;
C
Christoph Lameter 已提交
176 177 178 179 180 181 182

		return kmem_cache_alloc(s, flags);
	} else
		return __kmalloc(size, flags);
}

#ifdef CONFIG_NUMA
P
Paul Mundt 已提交
183 184
void *__kmalloc_node(size_t size, gfp_t flags, int node);
void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
C
Christoph Lameter 已提交
185 186 187 188 189 190 191

static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
{
	if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) {
		struct kmem_cache *s = kmalloc_slab(size);

		if (!s)
192
			return ZERO_SIZE_PTR;
C
Christoph Lameter 已提交
193 194 195 196 197 198 199 200

		return kmem_cache_alloc_node(s, flags, node);
	} else
		return __kmalloc_node(size, flags, node);
}
#endif

#endif /* _LINUX_SLUB_DEF_H */