slab_def.h 5.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#ifndef _LINUX_SLAB_DEF_H
#define	_LINUX_SLAB_DEF_H

/*
 * Definitions unique to the original Linux SLAB allocator.
 *
 * What we provide here is a way to optimize the frequent kmalloc
 * calls in the kernel by selecting the appropriate general cache
 * if kmalloc was called with a size that can be established at
 * compile time.
 */

#include <linux/init.h>
#include <asm/page.h>		/* kmalloc_sizes.h needs PAGE_SIZE */
#include <asm/cache.h>		/* kmalloc_sizes.h needs L1_CACHE_BYTES */
#include <linux/compiler.h>
17
#include <linux/kmemtrace.h>
18

19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
/*
 * struct kmem_cache
 *
 * manages a cache.
 */

struct kmem_cache {
/* 1) per-cpu data, touched during every alloc/free */
	struct array_cache *array[NR_CPUS];
/* 2) Cache tunables. Protected by cache_chain_mutex */
	unsigned int batchcount;
	unsigned int limit;
	unsigned int shared;

	unsigned int buffer_size;
	u32 reciprocal_buffer_size;
/* 3) touched by every alloc & free from the backend */

	unsigned int flags;		/* constant flags */
	unsigned int num;		/* # of objs per slab */

/* 4) cache_grow/shrink */
	/* order of pgs per slab (2^n) */
	unsigned int gfporder;

	/* force GFP flags, e.g. GFP_DMA */
	gfp_t gfpflags;

	size_t colour;			/* cache colouring range */
	unsigned int colour_off;	/* colour offset */
	struct kmem_cache *slabp_cache;
	unsigned int slab_size;
	unsigned int dflags;		/* dynamic flags */

	/* constructor func */
	void (*ctor)(void *obj);

/* 5) cache creation/removal */
	const char *name;
	struct list_head next;

/* 6) statistics */
#ifdef CONFIG_DEBUG_SLAB
	unsigned long num_active;
	unsigned long num_allocations;
	unsigned long high_mark;
	unsigned long grown;
	unsigned long reaped;
	unsigned long errors;
	unsigned long max_freeable;
	unsigned long node_allocs;
	unsigned long node_frees;
	unsigned long node_overflow;
	atomic_t allochit;
	atomic_t allocmiss;
	atomic_t freehit;
	atomic_t freemiss;

	/*
	 * If debugging is enabled, then the allocator can add additional
	 * fields and/or padding to every object. buffer_size contains the total
	 * object size including these internal fields, the following two
	 * variables contain the offset to the user object and its size.
	 */
	int obj_offset;
	int obj_size;
#endif /* CONFIG_DEBUG_SLAB */

	/*
	 * We put nodelists[] at the end of kmem_cache, because we want to size
	 * this array to nr_node_ids slots instead of MAX_NUMNODES
	 * (see kmem_cache_init())
	 * We still use [MAX_NUMNODES] and not [1] or [0] because cache_cache
	 * is statically defined, so we reserve the max number of nodes.
	 */
	struct kmem_list3 *nodelists[MAX_NUMNODES];
	/*
	 * Do not add fields after nodelists[]
	 */
};

100 101 102 103
/* Size description struct for general caches. */
struct cache_sizes {
	size_t		 	cs_size;
	struct kmem_cache	*cs_cachep;
104
#ifdef CONFIG_ZONE_DMA
105
	struct kmem_cache	*cs_dmacachep;
106
#endif
107 108 109
};
extern struct cache_sizes malloc_sizes[];

P
Paul Mundt 已提交
110 111 112
void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
void *__kmalloc(size_t size, gfp_t flags);

E
Eduard - Gabriel Munteanu 已提交
113 114 115 116 117 118
#ifdef CONFIG_KMEMTRACE
extern void *kmem_cache_alloc_notrace(struct kmem_cache *cachep, gfp_t flags);
extern size_t slab_buffer_size(struct kmem_cache *cachep);
#else
static __always_inline void *
kmem_cache_alloc_notrace(struct kmem_cache *cachep, gfp_t flags)
119
{
E
Eduard - Gabriel Munteanu 已提交
120 121 122 123 124 125 126 127 128 129 130 131 132
	return kmem_cache_alloc(cachep, flags);
}
static inline size_t slab_buffer_size(struct kmem_cache *cachep)
{
	return 0;
}
#endif

static __always_inline void *kmalloc(size_t size, gfp_t flags)
{
	struct kmem_cache *cachep;
	void *ret;

133 134
	if (__builtin_constant_p(size)) {
		int i = 0;
135 136 137 138

		if (!size)
			return ZERO_SIZE_PTR;

139 140 141 142 143
#define CACHE(x) \
		if (size <= x) \
			goto found; \
		else \
			i++;
144
#include <linux/kmalloc_sizes.h>
145
#undef CACHE
146
		return NULL;
147
found:
148 149
#ifdef CONFIG_ZONE_DMA
		if (flags & GFP_DMA)
E
Eduard - Gabriel Munteanu 已提交
150 151
			cachep = malloc_sizes[i].cs_dmacachep;
		else
152
#endif
E
Eduard - Gabriel Munteanu 已提交
153 154 155 156
			cachep = malloc_sizes[i].cs_cachep;

		ret = kmem_cache_alloc_notrace(cachep, flags);

157 158
		trace_kmalloc(_THIS_IP_, ret,
			      size, slab_buffer_size(cachep), flags);
E
Eduard - Gabriel Munteanu 已提交
159 160

		return ret;
161 162 163 164 165 166
	}
	return __kmalloc(size, flags);
}

#ifdef CONFIG_NUMA
extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
P
Paul Mundt 已提交
167
extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
168

E
Eduard - Gabriel Munteanu 已提交
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
#ifdef CONFIG_KMEMTRACE
extern void *kmem_cache_alloc_node_notrace(struct kmem_cache *cachep,
					   gfp_t flags,
					   int nodeid);
#else
static __always_inline void *
kmem_cache_alloc_node_notrace(struct kmem_cache *cachep,
			      gfp_t flags,
			      int nodeid)
{
	return kmem_cache_alloc_node(cachep, flags, nodeid);
}
#endif

static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node)
184
{
E
Eduard - Gabriel Munteanu 已提交
185 186 187
	struct kmem_cache *cachep;
	void *ret;

188 189
	if (__builtin_constant_p(size)) {
		int i = 0;
190 191 192 193

		if (!size)
			return ZERO_SIZE_PTR;

194 195 196 197 198
#define CACHE(x) \
		if (size <= x) \
			goto found; \
		else \
			i++;
199
#include <linux/kmalloc_sizes.h>
200
#undef CACHE
201
		return NULL;
202
found:
203 204
#ifdef CONFIG_ZONE_DMA
		if (flags & GFP_DMA)
E
Eduard - Gabriel Munteanu 已提交
205 206
			cachep = malloc_sizes[i].cs_dmacachep;
		else
207
#endif
E
Eduard - Gabriel Munteanu 已提交
208 209 210 211
			cachep = malloc_sizes[i].cs_cachep;

		ret = kmem_cache_alloc_node_notrace(cachep, flags, node);

212 213 214
		trace_kmalloc_node(_THIS_IP_, ret,
				   size, slab_buffer_size(cachep),
				   flags, node);
E
Eduard - Gabriel Munteanu 已提交
215 216

		return ret;
217 218 219 220 221 222 223
	}
	return __kmalloc_node(size, flags, node);
}

#endif	/* CONFIG_NUMA */

#endif	/* _LINUX_SLAB_DEF_H */