blob: 713f841ecaa914e74aead8e4d8ff5d74cb5040d3 [file] [log] [blame]
Christoph Lameter2e892f42006-12-13 00:34:23 -08001#ifndef _LINUX_SLAB_DEF_H
2#define _LINUX_SLAB_DEF_H
3
4/*
5 * Definitions unique to the original Linux SLAB allocator.
6 *
7 * What we provide here is a way to optimize the frequent kmalloc
8 * calls in the kernel by selecting the appropriate general cache
9 * if kmalloc was called with a size that can be established at
10 * compile time.
11 */
12
13#include <linux/init.h>
14#include <asm/page.h> /* kmalloc_sizes.h needs PAGE_SIZE */
15#include <asm/cache.h> /* kmalloc_sizes.h needs L1_CACHE_BYTES */
16#include <linux/compiler.h>
Zhaolei02af61b2009-04-10 14:26:18 +080017#include <linux/kmemtrace.h>
Christoph Lameter2e892f42006-12-13 00:34:23 -080018
19/* Size description struct for general caches. */
20struct cache_sizes {
21 size_t cs_size;
22 struct kmem_cache *cs_cachep;
Christoph Lameter4b51d662007-02-10 01:43:10 -080023#ifdef CONFIG_ZONE_DMA
Christoph Lameter2e892f42006-12-13 00:34:23 -080024 struct kmem_cache *cs_dmacachep;
Christoph Lameter4b51d662007-02-10 01:43:10 -080025#endif
Christoph Lameter2e892f42006-12-13 00:34:23 -080026};
27extern struct cache_sizes malloc_sizes[];
28
Paul Mundt6193a2f2007-07-15 23:38:22 -070029void *kmem_cache_alloc(struct kmem_cache *, gfp_t);
30void *__kmalloc(size_t size, gfp_t flags);
31
Eduard - Gabriel Munteanu36555752008-08-10 20:14:05 +030032#ifdef CONFIG_KMEMTRACE
33extern void *kmem_cache_alloc_notrace(struct kmem_cache *cachep, gfp_t flags);
34extern size_t slab_buffer_size(struct kmem_cache *cachep);
35#else
36static __always_inline void *
37kmem_cache_alloc_notrace(struct kmem_cache *cachep, gfp_t flags)
Christoph Lameter2e892f42006-12-13 00:34:23 -080038{
Eduard - Gabriel Munteanu36555752008-08-10 20:14:05 +030039 return kmem_cache_alloc(cachep, flags);
40}
41static inline size_t slab_buffer_size(struct kmem_cache *cachep)
42{
43 return 0;
44}
45#endif
46
47static __always_inline void *kmalloc(size_t size, gfp_t flags)
48{
49 struct kmem_cache *cachep;
50 void *ret;
51
Christoph Lameter2e892f42006-12-13 00:34:23 -080052 if (__builtin_constant_p(size)) {
53 int i = 0;
Christoph Lameter6cb8f912007-07-17 04:03:22 -070054
55 if (!size)
56 return ZERO_SIZE_PTR;
57
Christoph Lameter2e892f42006-12-13 00:34:23 -080058#define CACHE(x) \
59 if (size <= x) \
60 goto found; \
61 else \
62 i++;
Joe Perches1c61fc42008-03-05 13:58:17 -080063#include <linux/kmalloc_sizes.h>
Christoph Lameter2e892f42006-12-13 00:34:23 -080064#undef CACHE
Jeff Mahoney1cf3eb22009-01-27 23:48:59 +020065 return NULL;
Christoph Lameter2e892f42006-12-13 00:34:23 -080066found:
Christoph Lameter4b51d662007-02-10 01:43:10 -080067#ifdef CONFIG_ZONE_DMA
68 if (flags & GFP_DMA)
Eduard - Gabriel Munteanu36555752008-08-10 20:14:05 +030069 cachep = malloc_sizes[i].cs_dmacachep;
70 else
Christoph Lameter4b51d662007-02-10 01:43:10 -080071#endif
Eduard - Gabriel Munteanu36555752008-08-10 20:14:05 +030072 cachep = malloc_sizes[i].cs_cachep;
73
74 ret = kmem_cache_alloc_notrace(cachep, flags);
75
Eduard - Gabriel Munteanuca2b84cb2009-03-23 15:12:24 +020076 trace_kmalloc(_THIS_IP_, ret,
77 size, slab_buffer_size(cachep), flags);
Eduard - Gabriel Munteanu36555752008-08-10 20:14:05 +030078
79 return ret;
Christoph Lameter2e892f42006-12-13 00:34:23 -080080 }
81 return __kmalloc(size, flags);
82}
83
Christoph Lameter2e892f42006-12-13 00:34:23 -080084#ifdef CONFIG_NUMA
85extern void *__kmalloc_node(size_t size, gfp_t flags, int node);
Paul Mundt6193a2f2007-07-15 23:38:22 -070086extern void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node);
Christoph Lameter2e892f42006-12-13 00:34:23 -080087
Eduard - Gabriel Munteanu36555752008-08-10 20:14:05 +030088#ifdef CONFIG_KMEMTRACE
89extern void *kmem_cache_alloc_node_notrace(struct kmem_cache *cachep,
90 gfp_t flags,
91 int nodeid);
92#else
93static __always_inline void *
94kmem_cache_alloc_node_notrace(struct kmem_cache *cachep,
95 gfp_t flags,
96 int nodeid)
Christoph Lameter2e892f42006-12-13 00:34:23 -080097{
Eduard - Gabriel Munteanu36555752008-08-10 20:14:05 +030098 return kmem_cache_alloc_node(cachep, flags, nodeid);
99}
100#endif
101
102static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node)
103{
104 struct kmem_cache *cachep;
105 void *ret;
106
Christoph Lameter2e892f42006-12-13 00:34:23 -0800107 if (__builtin_constant_p(size)) {
108 int i = 0;
Christoph Lameter6cb8f912007-07-17 04:03:22 -0700109
110 if (!size)
111 return ZERO_SIZE_PTR;
112
Christoph Lameter2e892f42006-12-13 00:34:23 -0800113#define CACHE(x) \
114 if (size <= x) \
115 goto found; \
116 else \
117 i++;
Joe Perches1c61fc42008-03-05 13:58:17 -0800118#include <linux/kmalloc_sizes.h>
Christoph Lameter2e892f42006-12-13 00:34:23 -0800119#undef CACHE
Jeff Mahoney1cf3eb22009-01-27 23:48:59 +0200120 return NULL;
Christoph Lameter2e892f42006-12-13 00:34:23 -0800121found:
Christoph Lameter4b51d662007-02-10 01:43:10 -0800122#ifdef CONFIG_ZONE_DMA
123 if (flags & GFP_DMA)
Eduard - Gabriel Munteanu36555752008-08-10 20:14:05 +0300124 cachep = malloc_sizes[i].cs_dmacachep;
125 else
Christoph Lameter4b51d662007-02-10 01:43:10 -0800126#endif
Eduard - Gabriel Munteanu36555752008-08-10 20:14:05 +0300127 cachep = malloc_sizes[i].cs_cachep;
128
129 ret = kmem_cache_alloc_node_notrace(cachep, flags, node);
130
Eduard - Gabriel Munteanuca2b84cb2009-03-23 15:12:24 +0200131 trace_kmalloc_node(_THIS_IP_, ret,
132 size, slab_buffer_size(cachep),
133 flags, node);
Eduard - Gabriel Munteanu36555752008-08-10 20:14:05 +0300134
135 return ret;
Christoph Lameter2e892f42006-12-13 00:34:23 -0800136 }
137 return __kmalloc_node(size, flags, node);
138}
139
140#endif /* CONFIG_NUMA */
141
Christoph Lameter2e892f42006-12-13 00:34:23 -0800142#endif /* _LINUX_SLAB_DEF_H */