This source file includes following definitions.
- init_bucket_desc
- deb_kmalloc
- deb_kcheck_s
- deb_kfree_s
- get_malloc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 #include <linux/kernel.h>
65 #include <linux/mm.h>
66 #include <linux/string.h>
67
68 #include <asm/system.h>
69
70 struct bucket_desc {
71 void *page;
72 struct bucket_desc *next;
73 void *freeptr;
74 unsigned short refcnt;
75 unsigned short bucket_size;
76 };
77
78 struct _bucket_dir {
79 unsigned int size;
80 struct bucket_desc *chain;
81 };
82
83 #ifdef CONFIG_DEBUG_MALLOC
84
85 struct hdr_start {
86 const char *file;
87 const char *ok_file;
88 unsigned short line;
89 unsigned short ok_line;
90 unsigned short size;
91 int magic;
92 };
93 struct hdr_end {
94 int magic;
95 };
96
97 #define DEB_MAGIC_FREE 0x13579BDF
98 #define DEB_MAGIC_ALLOC 0x2468ACE0
99 #define DEB_MAGIC_USED 0x147AD036
100 #define DEB_MAGIC_FREED 0x258BE169
101
102 #define DEB_MAGIC_END 0x369CF258
103
104 #endif
105
106
107
108
109
110
111
112
113
114
115
116
117 struct _bucket_dir bucket_dir[] = {
118 #ifndef CONFIG_DEBUG_MALLOC
119 { 16, (struct bucket_desc *) 0},
120 #endif
121 { 32, (struct bucket_desc *) 0},
122 { 64, (struct bucket_desc *) 0},
123 { 128, (struct bucket_desc *) 0},
124 { 256, (struct bucket_desc *) 0},
125 { 512, (struct bucket_desc *) 0},
126 { 1024, (struct bucket_desc *) 0},
127 { 2048, (struct bucket_desc *) 0},
128 { 4096, (struct bucket_desc *) 0},
129 { 0, (struct bucket_desc *) 0}};
130
131
132
133
134 static struct bucket_desc *free_bucket_desc = (struct bucket_desc *) 0;
135
136
137
138
139
140
141
142
143 static inline void init_bucket_desc(unsigned long page)
144 {
145 struct bucket_desc *bdesc;
146 int i;
147
148 bdesc = (struct bucket_desc *) page;
149 for (i = PAGE_SIZE/sizeof(struct bucket_desc); i > 1; i--) {
150 bdesc->next = bdesc+1;
151 bdesc++;
152 }
153
154
155
156
157 cli();
158 bdesc->next = free_bucket_desc;
159 free_bucket_desc = (struct bucket_desc *) page;
160 }
161
162
163
164
165
166 #ifdef CONFIG_DEBUG_MALLOC
167 void *
168 deb_kmalloc(const char *deb_file, unsigned short deb_line,
169 unsigned int len, int priority)
170 #else
171 void *
172 kmalloc(unsigned int len, int priority)
173 #endif
174 {
175 int i;
176 unsigned long flags;
177 unsigned long page;
178 struct _bucket_dir *bdir;
179 struct bucket_desc *bdesc;
180 void *retval;
181
182 #ifdef CONFIG_DEBUG_MALLOC
183 len += sizeof(struct hdr_start)+sizeof(struct hdr_end);
184 #endif
185
186
187
188
189
190
191 bdir = bucket_dir;
192 for (bdir = bucket_dir ; bdir->size < len ; bdir++) {
193 if (!bdir->size)
194 goto too_large;
195 }
196
197
198
199
200 save_flags(flags);
201 cli();
202 for (bdesc = bdir->chain; bdesc != NULL; bdesc = bdesc->next)
203 if (bdesc->freeptr)
204 goto found_bdesc;
205
206
207
208
209
210
211
212
213
214
215 if (!free_bucket_desc) {
216 restore_flags(flags);
217 page = get_free_page(priority);
218 if (!page)
219 return NULL;
220 init_bucket_desc(page);
221 }
222
223 bdesc = free_bucket_desc;
224 free_bucket_desc = bdesc->next;
225 restore_flags(flags);
226
227 page = get_free_page(priority);
228
229
230
231
232 if (!page) {
233 cli();
234 bdesc->next = free_bucket_desc;
235 free_bucket_desc = bdesc;
236 restore_flags(flags);
237 return NULL;
238 }
239
240 bdesc->refcnt = 0;
241 bdesc->bucket_size = bdir->size;
242 bdesc->page = bdesc->freeptr = (void *) page;
243
244
245 for (i=PAGE_SIZE/bdir->size; i > 0 ; i--) {
246 #ifdef CONFIG_DEBUG_MALLOC
247 struct hdr_start *hd;
248 struct hdr_end *he;
249 hd = (struct hdr_start *) page;
250 he = (struct hdr_end *)(page+(bdir->size-sizeof(struct hdr_end)));
251 hd->magic = DEB_MAGIC_FREE;
252 hd->file = hd->ok_file = "(expand)";
253 hd->line = hd->ok_line = 0;
254 hd->size = bdir->size-sizeof(struct hdr_start)-sizeof(struct hdr_end);
255 he->magic = DEB_MAGIC_END;
256
257 memset(hd+1,0xF8,hd->size);
258
259 *((void **) (hd+1)) = (i==1) ? NULL : (void *)(page + bdir->size);
260 #else
261 *((void **) page) = (i==1) ? NULL : (void *)(page + bdir->size);
262 #endif
263 page += bdir->size;
264 }
265
266
267
268 cli();
269
270 bdesc->next = bdir->chain;
271 bdir->chain = bdesc;
272
273 found_bdesc:
274 retval = (void *) bdesc->freeptr;
275 #ifdef CONFIG_DEBUG_MALLOC
276 bdesc->freeptr = *((void **) (((char *)retval)+sizeof(struct hdr_start)));
277 #else
278 bdesc->freeptr = *((void **) retval);
279 #endif
280 bdesc->refcnt++;
281 restore_flags(flags);
282 #ifdef CONFIG_DEBUG_MALLOC
283 {
284 struct hdr_start *hd;
285 struct hdr_end *he;
286
287 hd = (struct hdr_start *) retval;
288 retval = hd+1;
289 len -= sizeof(struct hdr_start)+sizeof(struct hdr_end);
290 if(hd->magic != DEB_MAGIC_FREE && hd->magic != DEB_MAGIC_FREED) {
291 printk("DEB_MALLOC allocating %s block 0x%x (head 0x%x) from %s:%d, magic %x\n",
292 (hd->magic == DEB_MAGIC_ALLOC) ? "nonfree" : "trashed",
293 retval,hd,deb_file,deb_line,hd->magic);
294 return NULL;
295 }
296 if(len > hd->size || len > bdir->size-sizeof(struct hdr_start)-sizeof(struct hdr_end)) {
297 printk("DEB_MALLOC got %x:%x-byte block, wanted %x, from %s:%d, last %s:%d\n",
298 hd->size,bdir->size,len,hd->file,hd->line,deb_file,deb_line);
299 return NULL;
300 }
301 {
302 unsigned char *x = (unsigned char *) retval;
303 unsigned short pos = 4;
304 x += pos;
305 while(pos < hd->size) {
306 if(*x++ != 0xF8) {
307 printk("DEB_MALLOC used 0x%x:%x(%x) while free, from %s:%d\n",
308 retval,pos,hd->size,hd->file,hd->line);
309 return NULL;
310 }
311 pos++;
312 }
313 }
314 he = (struct hdr_end *)(((char *)retval)+hd->size);
315 if(he->magic != DEB_MAGIC_END) {
316 printk("DEB_MALLOC overran 0x%x:%d while free, from %s:%d\n",retval,hd->size,hd->file,hd->line);
317 }
318 memset(retval, 0xf0, len);
319 he = (struct hdr_end *)(((char *)retval)+len);
320 hd->file = hd->ok_file = deb_file;
321 hd->line = hd->ok_line = deb_line;
322 hd->size = len;
323 hd->magic = DEB_MAGIC_ALLOC;
324 he->magic = DEB_MAGIC_END;
325 }
326 #endif
327 return retval;
328
329 too_large:
330
331 printk("kmalloc called with impossibly large argument (%d)\n", len);
332 return NULL;
333 }
334
335 #ifdef CONFIG_DEBUG_MALLOC
336 void deb_kcheck_s(const char *deb_file, unsigned short deb_line,
337 void *obj, int size)
338 {
339 struct hdr_start *hd;
340 struct hdr_end *he;
341
342 if (!obj)
343 return;
344 hd = (struct hdr_start *) obj;
345 hd--;
346
347 if(hd->magic != DEB_MAGIC_ALLOC) {
348 if(hd->magic != DEB_MAGIC_USED && hd->magic != DEB_MAGIC_FREED)
349 printk("DEB_MALLOC Using %s block of 0x%x from %s:%d, by %s:%d, last %s:%d\n",
350 (hd->magic == DEB_MAGIC_FREE)?"free":"bad",obj,deb_file,deb_line,hd->file,hd->line,hd->ok_file,hd->ok_line);
351 if(hd->magic == DEB_MAGIC_FREE)
352 hd->magic = DEB_MAGIC_FREED;
353 return;
354 }
355 if(hd->size != size) {
356 if(size != 0) {
357 printk("DEB_MALLOC size for 0x%x given as %d, stored %d, from %s:%d, last %s:%d\n",
358 obj,size,hd->size,deb_file,deb_line,hd->ok_file,hd->ok_line);
359 }
360 size = hd->size;
361 }
362 he = (struct hdr_end *)(((char *)obj)+size);
363 if(he->magic != DEB_MAGIC_END) {
364 printk("DEB_MALLOC overran block 0x%x:%d, free at %s:%d\n",obj,hd->size,deb_file,deb_line);
365 hd->magic = DEB_MAGIC_USED;
366 return;
367 }
368 hd->ok_file = deb_file;
369 hd->ok_line = deb_line;
370 }
371 #endif
372
373
374
375
376
377
378
379
380 #ifdef CONFIG_DEBUG_MALLOC
381 void deb_kfree_s(const char *deb_file, unsigned short deb_line,
382 void *obj, int size)
383 #else
384 void kfree_s(void *obj, int size)
385 #endif
386 {
387 unsigned long flags;
388 void *page;
389 struct _bucket_dir *bdir;
390 struct bucket_desc *bdesc, *prev;
391
392 if (!obj)
393 return;
394 #ifdef CONFIG_DEBUG_MALLOC
395 {
396 struct hdr_start *hd;
397 struct hdr_end *he;
398 hd = (struct hdr_start *) obj;
399 hd--;
400
401 if(hd->magic != DEB_MAGIC_ALLOC && hd->magic != DEB_MAGIC_USED) {
402 if(hd->magic != DEB_MAGIC_FREED)
403 printk("DEB_MALLOC %s free of 0x%x from %s:%d by %s:%d, last %s:%d\n",
404 (hd->magic == DEB_MAGIC_FREE)?"dup":"bad",
405 obj,deb_file,deb_line,hd->file,hd->line,hd->ok_file,hd->ok_line);
406 return;
407 }
408 if(hd->size != size) {
409 if(size != 0) {
410 if(hd->magic != DEB_MAGIC_USED)
411 printk("DEB_MALLOC size for 0x%x given as %d, stored %d, from %s:%d, last %s:%d\n",
412 obj,size,hd->size,deb_file,deb_line,hd->ok_file,hd->ok_line);
413 }
414 size = hd->size;
415 }
416 he = (struct hdr_end *)(((char *)obj)+size);
417 if(he->magic != DEB_MAGIC_END) {
418 if(hd->magic != DEB_MAGIC_USED)
419 printk("DEB_MALLOC overran block 0x%x:%d, free at %s:%d, last %s:%d\n",
420 obj,hd->size,deb_file,deb_line,hd->ok_file,hd->ok_line);
421 return;
422 }
423 size += sizeof(struct hdr_start)+sizeof(struct hdr_end);
424 }
425 #endif
426 save_flags(flags);
427
428 page = (void *) ((unsigned long) obj & 0xfffff000);
429
430
431 for (bdir = bucket_dir; bdir->size; bdir++) {
432 prev = 0;
433
434 if (bdir->size >= size) {
435
436
437
438
439
440
441 cli();
442 for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next) {
443 if (bdesc->page == page)
444 goto found;
445 prev = bdesc;
446 }
447 }
448 }
449
450 restore_flags(flags);
451 printk("Bad address passed to kernel kfree_s(%X, %d)\n",obj, size);
452 #ifdef CONFIG_DEBUG_MALLOC
453 printk("Offending code: %s:%d\n",deb_file,deb_line);
454 #else
455 printk("Offending eip: %08x\n",((unsigned long *) &obj)[-1]);
456 #endif
457 return;
458
459 found:
460
461 #ifdef CONFIG_DEBUG_MALLOC
462
463 {
464 struct hdr_start *hd;
465 struct hdr_end *he;
466 hd = (struct hdr_start *) obj;
467 hd--;
468
469 hd->file = deb_file;
470 hd->line = deb_line;
471 hd->magic = DEB_MAGIC_FREE;
472 hd->size = bdir->size-sizeof(struct hdr_start)-sizeof(struct hdr_end);
473 he = (struct hdr_end *)(((char *)obj)+hd->size);
474 memset(obj, 0xf8, hd->size);
475 he->magic = DEB_MAGIC_END;
476 *((void **)obj) = bdesc->freeptr;
477 obj = hd;
478 }
479 #else
480 *((void **)obj) = bdesc->freeptr;
481 #endif
482
483 bdesc->freeptr = obj;
484 bdesc->refcnt--;
485 if (bdesc->refcnt == 0) {
486
487
488
489
490 if ((prev && (prev->next != bdesc)) ||
491 (!prev && (bdir->chain != bdesc)))
492 for (prev = bdir->chain; prev; prev = prev->next)
493 if (prev->next == bdesc)
494 break;
495 if (prev)
496 prev->next = bdesc->next;
497 else {
498 if (bdir->chain != bdesc)
499 panic("kmalloc bucket chains corrupted");
500 bdir->chain = bdesc->next;
501 }
502 bdesc->next = free_bucket_desc;
503 free_bucket_desc = bdesc;
504 free_page((unsigned long) bdesc->page);
505 }
506 restore_flags(flags);
507 return;
508 }
509
510 #ifdef CONFIG_DEBUG_MALLOC
511 int get_malloc(char *buffer)
512 {
513 int len = 0;
514 int i;
515 unsigned long flags;
516 void *page;
517 struct _bucket_dir *bdir;
518 struct bucket_desc *bdesc;
519
520 save_flags(flags);
521 cli();
522 for (bdir = bucket_dir; bdir->size; bdir++) {
523 for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next) {
524 page = bdesc->page;
525 for (i=PAGE_SIZE/bdir->size; i > 0 ; i--) {
526 struct hdr_start *hd;
527 hd = (struct hdr_start *)page;
528 if(hd->magic == DEB_MAGIC_ALLOC) {
529 if(len > PAGE_SIZE-80) {
530 restore_flags(flags);
531 len += sprintf(buffer+len,"+++\n");
532 return len;
533 }
534 len += sprintf(buffer+len,"%08x:%03x %s:%d %s:%d\n",
535 (long)(page+sizeof(struct hdr_start)),hd->size,hd->file,hd->line,hd->ok_file,hd->ok_line);
536 }
537 page += bdir->size;
538 }
539 }
540 }
541
542 restore_flags(flags);
543 return len;
544 }
545 #endif