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