]>
Commit | Line | Data |
---|---|---|
09b414e8 | 1 | #ifndef _SPL_KMEM_H |
2 | #define _SPL_KMEM_H | |
f1ca4da6 | 3 | |
4 | #ifdef __cplusplus | |
5 | extern "C" { | |
6 | #endif | |
7 | ||
79b31f36 | 8 | #define DEBUG_KMEM |
f1ca4da6 | 9 | #undef DEBUG_KMEM_UNIMPLEMENTED |
10 | ||
f1b59d26 | 11 | #include <linux/module.h> |
f1ca4da6 | 12 | #include <linux/slab.h> |
79b31f36 | 13 | #include <linux/vmalloc.h> |
f1ca4da6 | 14 | #include <linux/mm.h> |
15 | #include <linux/spinlock.h> | |
16 | /* | |
17 | * Memory allocation interfaces | |
18 | */ | |
19 | #define KM_SLEEP GFP_KERNEL | |
20 | #define KM_NOSLEEP GFP_ATOMIC | |
21 | #undef KM_PANIC /* No linux analog */ | |
22 | #define KM_PUSHPAGE (GFP_KERNEL | GFP_HIGH) | |
23 | #define KM_VMFLAGS GFP_LEVEL_MASK | |
24 | #define KM_FLAGS __GFP_BITS_MASK | |
25 | ||
26 | #ifdef DEBUG_KMEM | |
c19c06f3 | 27 | extern atomic64_t kmem_alloc_used; |
28 | extern unsigned long kmem_alloc_max; | |
29 | extern atomic64_t vmem_alloc_used; | |
30 | extern unsigned long vmem_alloc_max; | |
31 | extern int kmem_warning_flag; | |
f1ca4da6 | 32 | |
f1ca4da6 | 33 | #define __kmem_alloc(size, flags, allocator) \ |
34 | ({ void *_ptr_; \ | |
35 | \ | |
36 | /* Marked unlikely because we should never be doing this */ \ | |
c19c06f3 | 37 | if (unlikely((size) > (PAGE_SIZE * 2)) && kmem_warning_flag) \ |
f1ca4da6 | 38 | printk("Warning: kmem_alloc(%d, 0x%x) large alloc at %s:%d " \ |
c19c06f3 | 39 | "(%ld/%ld)\n", (int)(size), (int)(flags), \ |
f1ca4da6 | 40 | __FILE__, __LINE__, \ |
c19c06f3 | 41 | atomic64_read(&kmem_alloc_used), kmem_alloc_max); \ |
f1ca4da6 | 42 | \ |
43 | _ptr_ = (void *)allocator((size), (flags)); \ | |
44 | if (_ptr_ == NULL) { \ | |
45 | printk("Warning: kmem_alloc(%d, 0x%x) failed at %s:%d " \ | |
c19c06f3 | 46 | "(%ld/%ld)\n", (int)(size), (int)(flags), \ |
f1ca4da6 | 47 | __FILE__, __LINE__, \ |
c19c06f3 | 48 | atomic64_read(&kmem_alloc_used), kmem_alloc_max); \ |
49 | } else { \ | |
50 | atomic64_add((size), &kmem_alloc_used); \ | |
51 | if (unlikely(atomic64_read(&kmem_alloc_used)>kmem_alloc_max)) \ | |
52 | kmem_alloc_max = atomic64_read(&kmem_alloc_used); \ | |
f1ca4da6 | 53 | } \ |
54 | \ | |
55 | _ptr_; \ | |
56 | }) | |
57 | ||
58 | #define kmem_alloc(size, flags) __kmem_alloc(size, flags, kmalloc) | |
59 | #define kmem_zalloc(size, flags) __kmem_alloc(size, flags, kzalloc) | |
60 | ||
61 | #define kmem_free(ptr, size) \ | |
62 | ({ \ | |
79b31f36 | 63 | BUG_ON(!(ptr) || (size) < 0); \ |
c19c06f3 | 64 | atomic64_sub((size), &kmem_alloc_used); \ |
f1ca4da6 | 65 | memset(ptr, 0x5a, (size)); /* Poison */ \ |
66 | kfree(ptr); \ | |
f1ca4da6 | 67 | }) |
68 | ||
79b31f36 | 69 | #define __vmem_alloc(size, flags) \ |
70 | ({ void *_ptr_; \ | |
71 | \ | |
72 | BUG_ON(flags != KM_SLEEP); \ | |
73 | \ | |
74 | _ptr_ = (void *)vmalloc((size)); \ | |
75 | if (_ptr_ == NULL) { \ | |
76 | printk("Warning: vmem_alloc(%d, 0x%x) failed at %s:%d " \ | |
c19c06f3 | 77 | "(%ld/%ld)\n", (int)(size), (int)(flags), \ |
79b31f36 | 78 | __FILE__, __LINE__, \ |
c19c06f3 | 79 | atomic64_read(&vmem_alloc_used), vmem_alloc_max); \ |
80 | } else { \ | |
81 | atomic64_add((size), &vmem_alloc_used); \ | |
82 | if (unlikely(atomic64_read(&vmem_alloc_used)>vmem_alloc_max)) \ | |
83 | vmem_alloc_max = atomic64_read(&vmem_alloc_used); \ | |
79b31f36 | 84 | } \ |
85 | \ | |
86 | _ptr_; \ | |
87 | }) | |
88 | ||
89 | #define vmem_alloc(size, flags) __vmem_alloc(size, flags) | |
90 | ||
91 | #define vmem_free(ptr, size) \ | |
92 | ({ \ | |
93 | BUG_ON(!(ptr) || (size) < 0); \ | |
c19c06f3 | 94 | atomic64_sub((size), &vmem_alloc_used); \ |
79b31f36 | 95 | memset(ptr, 0x5a, (size)); /* Poison */ \ |
96 | vfree(ptr); \ | |
97 | }) | |
f1ca4da6 | 98 | |
99 | #else | |
100 | ||
101 | #define kmem_alloc(size, flags) kmalloc(size, flags) | |
102 | #define kmem_zalloc(size, flags) kzalloc(size, flags) | |
3b3ba48f | 103 | #define kmem_free(ptr, size) \ |
104 | ({ \ | |
79b31f36 | 105 | BUG_ON(!(ptr) || (size) < 0); \ |
3b3ba48f | 106 | kfree(ptr); \ |
107 | }) | |
f1ca4da6 | 108 | |
79b31f36 | 109 | #define vmem_alloc(size, flags) vmalloc(size) |
110 | #define vmem_free(ptr, size) \ | |
111 | ({ \ | |
112 | BUG_ON(!(ptr) || (size) < 0); \ | |
113 | vfree(ptr); \ | |
114 | }) | |
115 | ||
f1ca4da6 | 116 | #endif /* DEBUG_KMEM */ |
117 | ||
118 | ||
119 | #ifdef DEBUG_KMEM_UNIMPLEMENTED | |
120 | static __inline__ void * | |
121 | kmem_alloc_tryhard(size_t size, size_t *alloc_size, int kmflags) | |
122 | { | |
123 | #error "kmem_alloc_tryhard() not implemented" | |
124 | } | |
125 | #endif /* DEBUG_KMEM_UNIMPLEMENTED */ | |
126 | ||
127 | /* | |
128 | * Slab allocation interfaces | |
129 | */ | |
130 | #undef KMC_NOTOUCH /* No linux analog */ | |
48f940b9 | 131 | #define KMC_NODEBUG 0x00000000 /* Default behavior */ |
f1ca4da6 | 132 | #define KMC_NOMAGAZINE /* No linux analog */ |
133 | #define KMC_NOHASH /* No linux analog */ | |
134 | #define KMC_QCACHE /* No linux analog */ | |
135 | ||
136 | #define KMC_REAP_CHUNK 256 | |
137 | #define KMC_DEFAULT_SEEKS DEFAULT_SEEKS | |
138 | ||
139 | /* Defined by linux slab.h | |
140 | * typedef struct kmem_cache_s kmem_cache_t; | |
141 | */ | |
142 | ||
143 | /* No linux analog | |
144 | * extern int kmem_ready; | |
145 | * extern pgcnt_t kmem_reapahead; | |
146 | */ | |
147 | ||
148 | #ifdef DEBUG_KMEM_UNIMPLEMENTED | |
149 | static __inline__ void kmem_init(void) { | |
150 | #error "kmem_init() not implemented" | |
151 | } | |
152 | ||
153 | static __inline__ void kmem_thread_init(void) { | |
154 | #error "kmem_thread_init() not implemented" | |
155 | } | |
156 | ||
157 | static __inline__ void kmem_mp_init(void) { | |
158 | #error "kmem_mp_init() not implemented" | |
159 | } | |
160 | ||
161 | static __inline__ void kmem_reap_idspace(void) { | |
162 | #error "kmem_reap_idspace() not implemented" | |
163 | } | |
164 | ||
165 | static __inline__ size_t kmem_avail(void) { | |
166 | #error "kmem_avail() not implemented" | |
167 | } | |
168 | ||
169 | static __inline__ size_t kmem_maxavail(void) { | |
170 | #error "kmem_maxavail() not implemented" | |
171 | } | |
172 | ||
173 | static __inline__ uint64_t kmem_cache_stat(kmem_cache_t *cache) { | |
174 | #error "kmem_cache_stat() not implemented" | |
175 | } | |
176 | #endif /* DEBUG_KMEM_UNIMPLEMENTED */ | |
177 | ||
178 | /* XXX - Used by arc.c to adjust its memory footprint. We may want | |
179 | * to use this hook in the future to adjust behavior based on | |
180 | * debug levels. For now it's safe to always return 0. | |
181 | */ | |
182 | static __inline__ int | |
183 | kmem_debugging(void) | |
184 | { | |
185 | return 0; | |
186 | } | |
187 | ||
188 | typedef int (*kmem_constructor_t)(void *, void *, int); | |
189 | typedef void (*kmem_destructor_t)(void *, void *); | |
190 | typedef void (*kmem_reclaim_t)(void *); | |
191 | ||
c19c06f3 | 192 | extern int kmem_set_warning(int flag); |
193 | ||
f1b59d26 | 194 | extern kmem_cache_t * |
f1ca4da6 | 195 | __kmem_cache_create(char *name, size_t size, size_t align, |
f1b59d26 | 196 | kmem_constructor_t constructor, |
197 | kmem_destructor_t destructor, | |
198 | kmem_reclaim_t reclaim, | |
f1ca4da6 | 199 | void *priv, void *vmp, int flags); |
200 | ||
e4f1d29f | 201 | int |
f1b59d26 | 202 | extern __kmem_cache_destroy(kmem_cache_t *cache); |
203 | ||
204 | void | |
205 | extern __kmem_reap(void); | |
f1ca4da6 | 206 | |
5d86345d | 207 | int kmem_init(void); |
208 | void kmem_fini(void); | |
209 | ||
f1ca4da6 | 210 | #define kmem_cache_create(name,size,align,ctor,dtor,rclm,priv,vmp,flags) \ |
211 | __kmem_cache_create(name,size,align,ctor,dtor,rclm,priv,vmp,flags) | |
212 | #define kmem_cache_destroy(cache) __kmem_cache_destroy(cache) | |
213 | #define kmem_cache_alloc(cache, flags) kmem_cache_alloc(cache, flags) | |
214 | #define kmem_cache_free(cache, ptr) kmem_cache_free(cache, ptr) | |
215 | #define kmem_cache_reap_now(cache) kmem_cache_shrink(cache) | |
f1b59d26 | 216 | #define kmem_reap() __kmem_reap() |
f1ca4da6 | 217 | |
218 | #ifdef __cplusplus | |
219 | } | |
220 | #endif | |
221 | ||
09b414e8 | 222 | #endif /* _SPL_KMEM_H */ |