kern_malloc.c revision 1.121 1 /* $NetBSD: kern_malloc.c,v 1.121 2008/10/26 12:23:28 blymn Exp $ */
2
3 /*
4 * Copyright (c) 1987, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * @(#)kern_malloc.c 8.4 (Berkeley) 5/20/95
32 */
33
34 /*
35 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed by the University of
48 * California, Berkeley and its contributors.
49 * 4. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE.
64 *
65 * @(#)kern_malloc.c 8.4 (Berkeley) 5/20/95
66 */
67
68 #include <sys/cdefs.h>
69 __KERNEL_RCSID(0, "$NetBSD: kern_malloc.c,v 1.121 2008/10/26 12:23:28 blymn Exp $");
70
71 #include <sys/param.h>
72 #include <sys/proc.h>
73 #include <sys/kernel.h>
74 #include <sys/malloc.h>
75 #include <sys/systm.h>
76 #include <sys/debug.h>
77 #include <sys/mutex.h>
78 #include <sys/lockdebug.h>
79
80 #include <uvm/uvm_extern.h>
81
82 static struct vm_map_kernel kmem_map_store;
83 struct vm_map *kmem_map = NULL;
84
85 #include "opt_kmempages.h"
86
87 #ifdef NKMEMCLUSTERS
88 #error NKMEMCLUSTERS is obsolete; remove it from your kernel config file and use NKMEMPAGES instead or let the kernel auto-size
89 #endif
90
91 /*
92 * Default number of pages in kmem_map. We attempt to calculate this
93 * at run-time, but allow it to be either patched or set in the kernel
94 * config file.
95 */
96 #ifndef NKMEMPAGES
97 #define NKMEMPAGES 0
98 #endif
99 int nkmempages = NKMEMPAGES;
100
101 /*
102 * Defaults for lower- and upper-bounds for the kmem_map page count.
103 * Can be overridden by kernel config options.
104 */
105 #ifndef NKMEMPAGES_MIN
106 #define NKMEMPAGES_MIN NKMEMPAGES_MIN_DEFAULT
107 #endif
108
109 #ifndef NKMEMPAGES_MAX
110 #define NKMEMPAGES_MAX NKMEMPAGES_MAX_DEFAULT
111 #endif
112
113 #include "opt_kmemstats.h"
114 #include "opt_malloclog.h"
115 #include "opt_malloc_debug.h"
116
117 #define MINALLOCSIZE (1 << MINBUCKET)
118 #define BUCKETINDX(size) \
119 ((size) <= (MINALLOCSIZE * 128) \
120 ? (size) <= (MINALLOCSIZE * 8) \
121 ? (size) <= (MINALLOCSIZE * 2) \
122 ? (size) <= (MINALLOCSIZE * 1) \
123 ? (MINBUCKET + 0) \
124 : (MINBUCKET + 1) \
125 : (size) <= (MINALLOCSIZE * 4) \
126 ? (MINBUCKET + 2) \
127 : (MINBUCKET + 3) \
128 : (size) <= (MINALLOCSIZE* 32) \
129 ? (size) <= (MINALLOCSIZE * 16) \
130 ? (MINBUCKET + 4) \
131 : (MINBUCKET + 5) \
132 : (size) <= (MINALLOCSIZE * 64) \
133 ? (MINBUCKET + 6) \
134 : (MINBUCKET + 7) \
135 : (size) <= (MINALLOCSIZE * 2048) \
136 ? (size) <= (MINALLOCSIZE * 512) \
137 ? (size) <= (MINALLOCSIZE * 256) \
138 ? (MINBUCKET + 8) \
139 : (MINBUCKET + 9) \
140 : (size) <= (MINALLOCSIZE * 1024) \
141 ? (MINBUCKET + 10) \
142 : (MINBUCKET + 11) \
143 : (size) <= (MINALLOCSIZE * 8192) \
144 ? (size) <= (MINALLOCSIZE * 4096) \
145 ? (MINBUCKET + 12) \
146 : (MINBUCKET + 13) \
147 : (size) <= (MINALLOCSIZE * 16384) \
148 ? (MINBUCKET + 14) \
149 : (MINBUCKET + 15))
150
151 /*
152 * Array of descriptors that describe the contents of each page
153 */
154 struct kmemusage {
155 short ku_indx; /* bucket index */
156 union {
157 u_short freecnt;/* for small allocations, free pieces in page */
158 u_short pagecnt;/* for large allocations, pages alloced */
159 } ku_un;
160 };
161 #define ku_freecnt ku_un.freecnt
162 #define ku_pagecnt ku_un.pagecnt
163
164 struct kmembuckets kmembuckets[MINBUCKET + 16];
165 struct kmemusage *kmemusage;
166 char *kmembase, *kmemlimit;
167
168 #ifdef DEBUG
169 static void *malloc_freecheck;
170 #endif
171
172 /*
173 * Turn virtual addresses into kmem map indicies
174 */
175 #define btokup(addr) (&kmemusage[((char *)(addr) - kmembase) >> PGSHIFT])
176
177 struct malloc_type *kmemstatistics;
178
179 #ifdef MALLOCLOG
180 #ifndef MALLOCLOGSIZE
181 #define MALLOCLOGSIZE 100000
182 #endif
183
184 struct malloclog {
185 void *addr;
186 long size;
187 struct malloc_type *type;
188 int action;
189 const char *file;
190 long line;
191 } malloclog[MALLOCLOGSIZE];
192
193 long malloclogptr;
194
195 /*
196 * Fuzz factor for neighbour address match this must be a mask of the lower
197 * bits we wish to ignore when comparing addresses
198 */
199 __uintptr_t malloclog_fuzz = 0x7FL;
200
201
202 static void
203 domlog(void *a, long size, struct malloc_type *type, int action,
204 const char *file, long line)
205 {
206
207 malloclog[malloclogptr].addr = a;
208 malloclog[malloclogptr].size = size;
209 malloclog[malloclogptr].type = type;
210 malloclog[malloclogptr].action = action;
211 malloclog[malloclogptr].file = file;
212 malloclog[malloclogptr].line = line;
213 malloclogptr++;
214 if (malloclogptr >= MALLOCLOGSIZE)
215 malloclogptr = 0;
216 }
217
218 static void
219 hitmlog(void *a)
220 {
221 struct malloclog *lp;
222 long l;
223
224 #define PRT do { \
225 lp = &malloclog[l]; \
226 if (lp->addr == a && lp->action) { \
227 printf("malloc log entry %ld:\n", l); \
228 printf("\taddr = %p\n", lp->addr); \
229 printf("\tsize = %ld\n", lp->size); \
230 printf("\ttype = %s\n", lp->type->ks_shortdesc); \
231 printf("\taction = %s\n", lp->action == 1 ? "alloc" : "free"); \
232 printf("\tfile = %s\n", lp->file); \
233 printf("\tline = %ld\n", lp->line); \
234 } \
235 } while (/* CONSTCOND */0)
236
237 /*
238 * Print fuzzy matched "neighbour" - look for the memory block that has
239 * been allocated below the address we are interested in. We look for a
240 * base address + size that is within malloclog_fuzz of our target
241 * address. If the base address and target address are the same then it is
242 * likely we have found a free (size is 0 in this case) so we won't report
243 * those, they will get reported by PRT anyway.
244 */
245 #define NPRT do { \
246 __uintptr_t fuzz_mask = ~(malloclog_fuzz); \
247 lp = &malloclog[l]; \
248 if ((__uintptr_t)lp->addr != (__uintptr_t)a && \
249 (((__uintptr_t)lp->addr + lp->size + malloclog_fuzz) & fuzz_mask) \
250 == ((__uintptr_t)a & fuzz_mask) && lp->action) { \
251 printf("neighbour malloc log entry %ld:\n", l); \
252 printf("\taddr = %p\n", lp->addr); \
253 printf("\tsize = %ld\n", lp->size); \
254 printf("\ttype = %s\n", lp->type->ks_shortdesc); \
255 printf("\taction = %s\n", lp->action == 1 ? "alloc" : "free"); \
256 printf("\tfile = %s\n", lp->file); \
257 printf("\tline = %ld\n", lp->line); \
258 } \
259 } while (/* CONSTCOND */0)
260
261 for (l = malloclogptr; l < MALLOCLOGSIZE; l++) {
262 PRT;
263 NPRT;
264 }
265
266
267 for (l = 0; l < malloclogptr; l++) {
268 PRT;
269 NPRT;
270 }
271
272 #undef PRT
273 }
274 #endif /* MALLOCLOG */
275
276 #ifdef DIAGNOSTIC
277 /*
278 * This structure provides a set of masks to catch unaligned frees.
279 */
280 const long addrmask[] = { 0,
281 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
282 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
283 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
284 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
285 };
286
287 /*
288 * The WEIRD_ADDR is used as known text to copy into free objects so
289 * that modifications after frees can be detected.
290 */
291 #define WEIRD_ADDR ((uint32_t) 0xdeadbeef)
292 #ifdef DEBUG
293 #define MAX_COPY PAGE_SIZE
294 #else
295 #define MAX_COPY 32
296 #endif
297
298 /*
299 * Normally the freelist structure is used only to hold the list pointer
300 * for free objects. However, when running with diagnostics, the first
301 * 8/16 bytes of the structure is unused except for diagnostic information,
302 * and the free list pointer is at offset 8/16 in the structure. Since the
303 * first 8 bytes is the portion of the structure most often modified, this
304 * helps to detect memory reuse problems and avoid free list corruption.
305 */
306 struct freelist {
307 uint32_t spare0;
308 #ifdef _LP64
309 uint32_t spare1; /* explicit padding */
310 #endif
311 struct malloc_type *type;
312 void * next;
313 };
314 #else /* !DIAGNOSTIC */
315 struct freelist {
316 void * next;
317 };
318 #endif /* DIAGNOSTIC */
319
320 kmutex_t malloc_lock;
321
322 /*
323 * Allocate a block of memory
324 */
325 #ifdef MALLOCLOG
326 void *
327 _malloc(unsigned long size, struct malloc_type *ksp, int flags,
328 const char *file, long line)
329 #else
330 void *
331 malloc(unsigned long size, struct malloc_type *ksp, int flags)
332 #endif /* MALLOCLOG */
333 {
334 struct kmembuckets *kbp;
335 struct kmemusage *kup;
336 struct freelist *freep;
337 long indx, npg, allocsize;
338 char *va, *cp, *savedlist;
339 #ifdef DIAGNOSTIC
340 uint32_t *end, *lp;
341 int copysize;
342 #endif
343
344 #ifdef LOCKDEBUG
345 if ((flags & M_NOWAIT) == 0) {
346 ASSERT_SLEEPABLE();
347 }
348 #endif
349 #ifdef MALLOC_DEBUG
350 if (debug_malloc(size, ksp, flags, (void *) &va)) {
351 if (va != 0)
352 FREECHECK_OUT(&malloc_freecheck, (void *)va);
353 return ((void *) va);
354 }
355 #endif
356 indx = BUCKETINDX(size);
357 kbp = &kmembuckets[indx];
358 mutex_spin_enter(&malloc_lock);
359 #ifdef KMEMSTATS
360 while (ksp->ks_memuse >= ksp->ks_limit) {
361 if (flags & M_NOWAIT) {
362 mutex_spin_exit(&malloc_lock);
363 return ((void *) NULL);
364 }
365 if (ksp->ks_limblocks < 65535)
366 ksp->ks_limblocks++;
367 mtsleep((void *)ksp, PSWP+2, ksp->ks_shortdesc, 0,
368 &malloc_lock);
369 }
370 ksp->ks_size |= 1 << indx;
371 #endif
372 #ifdef DIAGNOSTIC
373 copysize = 1 << indx < MAX_COPY ? 1 << indx : MAX_COPY;
374 #endif
375 if (kbp->kb_next == NULL) {
376 int s;
377 kbp->kb_last = NULL;
378 if (size > MAXALLOCSAVE)
379 allocsize = round_page(size);
380 else
381 allocsize = 1 << indx;
382 npg = btoc(allocsize);
383 mutex_spin_exit(&malloc_lock);
384 s = splvm();
385 va = (void *) uvm_km_alloc(kmem_map,
386 (vsize_t)ctob(npg), 0,
387 ((flags & M_NOWAIT) ? UVM_KMF_NOWAIT : 0) |
388 ((flags & M_CANFAIL) ? UVM_KMF_CANFAIL : 0) |
389 UVM_KMF_WIRED);
390 splx(s);
391 if (__predict_false(va == NULL)) {
392 /*
393 * Kmem_malloc() can return NULL, even if it can
394 * wait, if there is no map space available, because
395 * it can't fix that problem. Neither can we,
396 * right now. (We should release pages which
397 * are completely free and which are in kmembuckets
398 * with too many free elements.)
399 */
400 if ((flags & (M_NOWAIT|M_CANFAIL)) == 0)
401 panic("malloc: out of space in kmem_map");
402 return (NULL);
403 }
404 mutex_spin_enter(&malloc_lock);
405 #ifdef KMEMSTATS
406 kbp->kb_total += kbp->kb_elmpercl;
407 #endif
408 kup = btokup(va);
409 kup->ku_indx = indx;
410 if (allocsize > MAXALLOCSAVE) {
411 if (npg > 65535)
412 panic("malloc: allocation too large");
413 kup->ku_pagecnt = npg;
414 #ifdef KMEMSTATS
415 ksp->ks_memuse += allocsize;
416 #endif
417 goto out;
418 }
419 #ifdef KMEMSTATS
420 kup->ku_freecnt = kbp->kb_elmpercl;
421 kbp->kb_totalfree += kbp->kb_elmpercl;
422 #endif
423 /*
424 * Just in case we blocked while allocating memory,
425 * and someone else also allocated memory for this
426 * kmembucket, don't assume the list is still empty.
427 */
428 savedlist = kbp->kb_next;
429 kbp->kb_next = cp = va + (npg << PAGE_SHIFT) - allocsize;
430 for (;;) {
431 freep = (struct freelist *)cp;
432 #ifdef DIAGNOSTIC
433 /*
434 * Copy in known text to detect modification
435 * after freeing.
436 */
437 end = (uint32_t *)&cp[copysize];
438 for (lp = (uint32_t *)cp; lp < end; lp++)
439 *lp = WEIRD_ADDR;
440 freep->type = M_FREE;
441 #endif /* DIAGNOSTIC */
442 if (cp <= va)
443 break;
444 cp -= allocsize;
445 freep->next = cp;
446 }
447 freep->next = savedlist;
448 if (savedlist == NULL)
449 kbp->kb_last = (void *)freep;
450 }
451 va = kbp->kb_next;
452 kbp->kb_next = ((struct freelist *)va)->next;
453 #ifdef DIAGNOSTIC
454 freep = (struct freelist *)va;
455 /* XXX potential to get garbage pointer here. */
456 if (kbp->kb_next) {
457 int rv;
458 vaddr_t addr = (vaddr_t)kbp->kb_next;
459
460 vm_map_lock(kmem_map);
461 rv = uvm_map_checkprot(kmem_map, addr,
462 addr + sizeof(struct freelist), VM_PROT_WRITE);
463 vm_map_unlock(kmem_map);
464
465 if (__predict_false(rv == 0)) {
466 printf("Data modified on freelist: "
467 "word %ld of object %p size %ld previous type %s "
468 "(invalid addr %p)\n",
469 (long)((int32_t *)&kbp->kb_next - (int32_t *)kbp),
470 va, size, "foo", kbp->kb_next);
471 #ifdef MALLOCLOG
472 hitmlog(va);
473 #endif
474 kbp->kb_next = NULL;
475 }
476 }
477
478 /* Fill the fields that we've used with WEIRD_ADDR */
479 #ifdef _LP64
480 freep->type = (struct malloc_type *)
481 (WEIRD_ADDR | (((u_long) WEIRD_ADDR) << 32));
482 #else
483 freep->type = (struct malloc_type *) WEIRD_ADDR;
484 #endif
485 end = (uint32_t *)&freep->next +
486 (sizeof(freep->next) / sizeof(int32_t));
487 for (lp = (uint32_t *)&freep->next; lp < end; lp++)
488 *lp = WEIRD_ADDR;
489
490 /* and check that the data hasn't been modified. */
491 end = (uint32_t *)&va[copysize];
492 for (lp = (uint32_t *)va; lp < end; lp++) {
493 if (__predict_true(*lp == WEIRD_ADDR))
494 continue;
495 printf("Data modified on freelist: "
496 "word %ld of object %p size %ld previous type %s "
497 "(0x%x != 0x%x)\n",
498 (long)(lp - (uint32_t *)va), va, size,
499 "bar", *lp, WEIRD_ADDR);
500 #ifdef MALLOCLOG
501 hitmlog(va);
502 #endif
503 break;
504 }
505
506 freep->spare0 = 0;
507 #endif /* DIAGNOSTIC */
508 #ifdef KMEMSTATS
509 kup = btokup(va);
510 if (kup->ku_indx != indx)
511 panic("malloc: wrong bucket");
512 if (kup->ku_freecnt == 0)
513 panic("malloc: lost data");
514 kup->ku_freecnt--;
515 kbp->kb_totalfree--;
516 ksp->ks_memuse += 1 << indx;
517 out:
518 kbp->kb_calls++;
519 ksp->ks_inuse++;
520 ksp->ks_calls++;
521 if (ksp->ks_memuse > ksp->ks_maxused)
522 ksp->ks_maxused = ksp->ks_memuse;
523 #else
524 out:
525 #endif
526 #ifdef MALLOCLOG
527 domlog(va, size, ksp, 1, file, line);
528 #endif
529 mutex_spin_exit(&malloc_lock);
530 if ((flags & M_ZERO) != 0)
531 memset(va, 0, size);
532 FREECHECK_OUT(&malloc_freecheck, (void *)va);
533 return ((void *) va);
534 }
535
536 /*
537 * Free a block of memory allocated by malloc.
538 */
539 #ifdef MALLOCLOG
540 void
541 _free(void *addr, struct malloc_type *ksp, const char *file, long line)
542 #else
543 void
544 free(void *addr, struct malloc_type *ksp)
545 #endif /* MALLOCLOG */
546 {
547 struct kmembuckets *kbp;
548 struct kmemusage *kup;
549 struct freelist *freep;
550 long size;
551 #ifdef DIAGNOSTIC
552 void *cp;
553 int32_t *end, *lp;
554 long alloc, copysize;
555 #endif
556
557 FREECHECK_IN(&malloc_freecheck, addr);
558 #ifdef MALLOC_DEBUG
559 if (debug_free(addr, ksp))
560 return;
561 #endif
562
563 #ifdef DIAGNOSTIC
564 /*
565 * Ensure that we're free'ing something that we could
566 * have allocated in the first place. That is, check
567 * to see that the address is within kmem_map.
568 */
569 if (__predict_false((vaddr_t)addr < vm_map_min(kmem_map) ||
570 (vaddr_t)addr >= vm_map_max(kmem_map)))
571 panic("free: addr %p not within kmem_map", addr);
572 #endif
573
574 kup = btokup(addr);
575 size = 1 << kup->ku_indx;
576 kbp = &kmembuckets[kup->ku_indx];
577
578 LOCKDEBUG_MEM_CHECK(addr,
579 size <= MAXALLOCSAVE ? size : ctob(kup->ku_pagecnt));
580
581 mutex_spin_enter(&malloc_lock);
582 #ifdef MALLOCLOG
583 domlog(addr, 0, ksp, 2, file, line);
584 #endif
585 #ifdef DIAGNOSTIC
586 /*
587 * Check for returns of data that do not point to the
588 * beginning of the allocation.
589 */
590 if (size > PAGE_SIZE)
591 alloc = addrmask[BUCKETINDX(PAGE_SIZE)];
592 else
593 alloc = addrmask[kup->ku_indx];
594 if (((u_long)addr & alloc) != 0)
595 panic("free: unaligned addr %p, size %ld, type %s, mask %ld",
596 addr, size, ksp->ks_shortdesc, alloc);
597 #endif /* DIAGNOSTIC */
598 if (size > MAXALLOCSAVE) {
599 uvm_km_free(kmem_map, (vaddr_t)addr, ctob(kup->ku_pagecnt),
600 UVM_KMF_WIRED);
601 #ifdef KMEMSTATS
602 size = kup->ku_pagecnt << PGSHIFT;
603 ksp->ks_memuse -= size;
604 kup->ku_indx = 0;
605 kup->ku_pagecnt = 0;
606 if (ksp->ks_memuse + size >= ksp->ks_limit &&
607 ksp->ks_memuse < ksp->ks_limit)
608 wakeup((void *)ksp);
609 #ifdef DIAGNOSTIC
610 if (ksp->ks_inuse == 0)
611 panic("free 1: inuse 0, probable double free");
612 #endif
613 ksp->ks_inuse--;
614 kbp->kb_total -= 1;
615 #endif
616 mutex_spin_exit(&malloc_lock);
617 return;
618 }
619 freep = (struct freelist *)addr;
620 #ifdef DIAGNOSTIC
621 /*
622 * Check for multiple frees. Use a quick check to see if
623 * it looks free before laboriously searching the freelist.
624 */
625 if (__predict_false(freep->spare0 == WEIRD_ADDR)) {
626 for (cp = kbp->kb_next; cp;
627 cp = ((struct freelist *)cp)->next) {
628 if (addr != cp)
629 continue;
630 printf("multiply freed item %p\n", addr);
631 #ifdef MALLOCLOG
632 hitmlog(addr);
633 #endif
634 panic("free: duplicated free");
635 }
636 }
637
638 /*
639 * Copy in known text to detect modification after freeing
640 * and to make it look free. Also, save the type being freed
641 * so we can list likely culprit if modification is detected
642 * when the object is reallocated.
643 */
644 copysize = size < MAX_COPY ? size : MAX_COPY;
645 end = (int32_t *)&((char *)addr)[copysize];
646 for (lp = (int32_t *)addr; lp < end; lp++)
647 *lp = WEIRD_ADDR;
648 freep->type = ksp;
649 #endif /* DIAGNOSTIC */
650 #ifdef KMEMSTATS
651 kup->ku_freecnt++;
652 if (kup->ku_freecnt >= kbp->kb_elmpercl) {
653 if (kup->ku_freecnt > kbp->kb_elmpercl)
654 panic("free: multiple frees");
655 else if (kbp->kb_totalfree > kbp->kb_highwat)
656 kbp->kb_couldfree++;
657 }
658 kbp->kb_totalfree++;
659 ksp->ks_memuse -= size;
660 if (ksp->ks_memuse + size >= ksp->ks_limit &&
661 ksp->ks_memuse < ksp->ks_limit)
662 wakeup((void *)ksp);
663 #ifdef DIAGNOSTIC
664 if (ksp->ks_inuse == 0)
665 panic("free 2: inuse 0, probable double free");
666 #endif
667 ksp->ks_inuse--;
668 #endif
669 if (kbp->kb_next == NULL)
670 kbp->kb_next = addr;
671 else
672 ((struct freelist *)kbp->kb_last)->next = addr;
673 freep->next = NULL;
674 kbp->kb_last = addr;
675 mutex_spin_exit(&malloc_lock);
676 }
677
678 /*
679 * Change the size of a block of memory.
680 */
681 void *
682 realloc(void *curaddr, unsigned long newsize, struct malloc_type *ksp,
683 int flags)
684 {
685 struct kmemusage *kup;
686 unsigned long cursize;
687 void *newaddr;
688 #ifdef DIAGNOSTIC
689 long alloc;
690 #endif
691
692 /*
693 * realloc() with a NULL pointer is the same as malloc().
694 */
695 if (curaddr == NULL)
696 return (malloc(newsize, ksp, flags));
697
698 /*
699 * realloc() with zero size is the same as free().
700 */
701 if (newsize == 0) {
702 free(curaddr, ksp);
703 return (NULL);
704 }
705
706 #ifdef LOCKDEBUG
707 if ((flags & M_NOWAIT) == 0) {
708 ASSERT_SLEEPABLE();
709 }
710 #endif
711
712 /*
713 * Find out how large the old allocation was (and do some
714 * sanity checking).
715 */
716 kup = btokup(curaddr);
717 cursize = 1 << kup->ku_indx;
718
719 #ifdef DIAGNOSTIC
720 /*
721 * Check for returns of data that do not point to the
722 * beginning of the allocation.
723 */
724 if (cursize > PAGE_SIZE)
725 alloc = addrmask[BUCKETINDX(PAGE_SIZE)];
726 else
727 alloc = addrmask[kup->ku_indx];
728 if (((u_long)curaddr & alloc) != 0)
729 panic("realloc: "
730 "unaligned addr %p, size %ld, type %s, mask %ld\n",
731 curaddr, cursize, ksp->ks_shortdesc, alloc);
732 #endif /* DIAGNOSTIC */
733
734 if (cursize > MAXALLOCSAVE)
735 cursize = ctob(kup->ku_pagecnt);
736
737 /*
738 * If we already actually have as much as they want, we're done.
739 */
740 if (newsize <= cursize)
741 return (curaddr);
742
743 /*
744 * Can't satisfy the allocation with the existing block.
745 * Allocate a new one and copy the data.
746 */
747 newaddr = malloc(newsize, ksp, flags);
748 if (__predict_false(newaddr == NULL)) {
749 /*
750 * malloc() failed, because flags included M_NOWAIT.
751 * Return NULL to indicate that failure. The old
752 * pointer is still valid.
753 */
754 return (NULL);
755 }
756 memcpy(newaddr, curaddr, cursize);
757
758 /*
759 * We were successful: free the old allocation and return
760 * the new one.
761 */
762 free(curaddr, ksp);
763 return (newaddr);
764 }
765
766 /*
767 * Roundup size to the actual allocation size.
768 */
769 unsigned long
770 malloc_roundup(unsigned long size)
771 {
772
773 if (size > MAXALLOCSAVE)
774 return (roundup(size, PAGE_SIZE));
775 else
776 return (1 << BUCKETINDX(size));
777 }
778
779 /*
780 * Add a malloc type to the system.
781 */
782 void
783 malloc_type_attach(struct malloc_type *type)
784 {
785
786 if (nkmempages == 0)
787 panic("malloc_type_attach: nkmempages == 0");
788
789 if (type->ks_magic != M_MAGIC)
790 panic("malloc_type_attach: bad magic");
791
792 #ifdef DIAGNOSTIC
793 {
794 struct malloc_type *ksp;
795 for (ksp = kmemstatistics; ksp != NULL; ksp = ksp->ks_next) {
796 if (ksp == type)
797 panic("malloc_type_attach: already on list");
798 }
799 }
800 #endif
801
802 #ifdef KMEMSTATS
803 if (type->ks_limit == 0)
804 type->ks_limit = ((u_long)nkmempages << PAGE_SHIFT) * 6U / 10U;
805 #else
806 type->ks_limit = 0;
807 #endif
808
809 type->ks_next = kmemstatistics;
810 kmemstatistics = type;
811 }
812
813 /*
814 * Remove a malloc type from the system..
815 */
816 void
817 malloc_type_detach(struct malloc_type *type)
818 {
819 struct malloc_type *ksp;
820
821 #ifdef DIAGNOSTIC
822 if (type->ks_magic != M_MAGIC)
823 panic("malloc_type_detach: bad magic");
824 #endif
825
826 if (type == kmemstatistics)
827 kmemstatistics = type->ks_next;
828 else {
829 for (ksp = kmemstatistics; ksp->ks_next != NULL;
830 ksp = ksp->ks_next) {
831 if (ksp->ks_next == type) {
832 ksp->ks_next = type->ks_next;
833 break;
834 }
835 }
836 #ifdef DIAGNOSTIC
837 if (ksp->ks_next == NULL)
838 panic("malloc_type_detach: not on list");
839 #endif
840 }
841 type->ks_next = NULL;
842 }
843
844 /*
845 * Set the limit on a malloc type.
846 */
847 void
848 malloc_type_setlimit(struct malloc_type *type, u_long limit)
849 {
850 #ifdef KMEMSTATS
851 mutex_spin_enter(&malloc_lock);
852 type->ks_limit = limit;
853 mutex_spin_exit(&malloc_lock);
854 #endif
855 }
856
857 /*
858 * Compute the number of pages that kmem_map will map, that is,
859 * the size of the kernel malloc arena.
860 */
861 void
862 kmeminit_nkmempages(void)
863 {
864 int npages;
865
866 if (nkmempages != 0) {
867 /*
868 * It's already been set (by us being here before, or
869 * by patching or kernel config options), bail out now.
870 */
871 return;
872 }
873
874 npages = physmem;
875
876 if (npages > NKMEMPAGES_MAX)
877 npages = NKMEMPAGES_MAX;
878
879 if (npages < NKMEMPAGES_MIN)
880 npages = NKMEMPAGES_MIN;
881
882 nkmempages = npages;
883 }
884
885 /*
886 * Initialize the kernel memory allocator
887 */
888 void
889 kmeminit(void)
890 {
891 __link_set_decl(malloc_types, struct malloc_type);
892 struct malloc_type * const *ksp;
893 vaddr_t kmb, kml;
894 #ifdef KMEMSTATS
895 long indx;
896 #endif
897
898 #if ((MAXALLOCSAVE & (MAXALLOCSAVE - 1)) != 0)
899 ERROR!_kmeminit:_MAXALLOCSAVE_not_power_of_2
900 #endif
901 #if (MAXALLOCSAVE > MINALLOCSIZE * 32768)
902 ERROR!_kmeminit:_MAXALLOCSAVE_too_big
903 #endif
904 #if (MAXALLOCSAVE < NBPG)
905 ERROR!_kmeminit:_MAXALLOCSAVE_too_small
906 #endif
907
908 if (sizeof(struct freelist) > (1 << MINBUCKET))
909 panic("minbucket too small/struct freelist too big");
910
911 mutex_init(&malloc_lock, MUTEX_DEFAULT, IPL_VM);
912
913 /*
914 * Compute the number of kmem_map pages, if we have not
915 * done so already.
916 */
917 kmeminit_nkmempages();
918
919 kmemusage = (struct kmemusage *) uvm_km_alloc(kernel_map,
920 (vsize_t)(nkmempages * sizeof(struct kmemusage)), 0,
921 UVM_KMF_WIRED|UVM_KMF_ZERO);
922 kmb = 0;
923 kmem_map = uvm_km_suballoc(kernel_map, &kmb,
924 &kml, ((vsize_t)nkmempages << PAGE_SHIFT),
925 VM_MAP_INTRSAFE, false, &kmem_map_store);
926 uvm_km_vacache_init(kmem_map, "kvakmem", 0);
927 kmembase = (char *)kmb;
928 kmemlimit = (char *)kml;
929 #ifdef KMEMSTATS
930 for (indx = 0; indx < MINBUCKET + 16; indx++) {
931 if (1 << indx >= PAGE_SIZE)
932 kmembuckets[indx].kb_elmpercl = 1;
933 else
934 kmembuckets[indx].kb_elmpercl = PAGE_SIZE / (1 << indx);
935 kmembuckets[indx].kb_highwat =
936 5 * kmembuckets[indx].kb_elmpercl;
937 }
938 #endif
939
940 /* Attach all of the statically-linked malloc types. */
941 __link_set_foreach(ksp, malloc_types)
942 malloc_type_attach(*ksp);
943 }
944
945 #ifdef DDB
946 #include <ddb/db_output.h>
947
948 /*
949 * Dump kmem statistics from ddb.
950 *
951 * usage: call dump_kmemstats
952 */
953 void dump_kmemstats(void);
954
955 void
956 dump_kmemstats(void)
957 {
958 #ifdef KMEMSTATS
959 struct malloc_type *ksp;
960
961 for (ksp = kmemstatistics; ksp != NULL; ksp = ksp->ks_next) {
962 if (ksp->ks_memuse == 0)
963 continue;
964 db_printf("%s%.*s %ld\n", ksp->ks_shortdesc,
965 (int)(20 - strlen(ksp->ks_shortdesc)),
966 " ",
967 ksp->ks_memuse);
968 }
969 #else
970 db_printf("Kmem stats are not being collected.\n");
971 #endif /* KMEMSTATS */
972 }
973 #endif /* DDB */
974
975
976 #if 0
977 /*
978 * Diagnostic messages about "Data modified on
979 * freelist" indicate a memory corruption, but
980 * they do not help tracking it down.
981 * This function can be called at various places
982 * to sanity check malloc's freelist and discover
983 * where does the corruption take place.
984 */
985 int
986 freelist_sanitycheck(void) {
987 int i,j;
988 struct kmembuckets *kbp;
989 struct freelist *freep;
990 int rv = 0;
991
992 for (i = MINBUCKET; i <= MINBUCKET + 15; i++) {
993 kbp = &kmembuckets[i];
994 freep = (struct freelist *)kbp->kb_next;
995 j = 0;
996 while(freep) {
997 vm_map_lock(kmem_map);
998 rv = uvm_map_checkprot(kmem_map, (vaddr_t)freep,
999 (vaddr_t)freep + sizeof(struct freelist),
1000 VM_PROT_WRITE);
1001 vm_map_unlock(kmem_map);
1002
1003 if ((rv == 0) || (*(int *)freep != WEIRD_ADDR)) {
1004 printf("bucket %i, chunck %d at %p modified\n",
1005 i, j, freep);
1006 return 1;
1007 }
1008 freep = (struct freelist *)freep->next;
1009 j++;
1010 }
1011 }
1012
1013 return 0;
1014 }
1015 #endif
1016