Home | History | Annotate | Line # | Download | only in kern
kern_malloc.c revision 1.133.2.1
      1  1.133.2.1      yamt /*	$NetBSD: kern_malloc.c,v 1.133.2.1 2012/04/17 00:08:24 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.133.2.1      yamt __KERNEL_RCSID(0, "$NetBSD: kern_malloc.c,v 1.133.2.1 2012/04/17 00:08:24 yamt Exp $");
     70        1.1       cgd 
     71        1.7   mycroft #include <sys/param.h>
     72        1.7   mycroft #include <sys/proc.h>
     73        1.7   mycroft #include <sys/kernel.h>
     74        1.7   mycroft #include <sys/malloc.h>
     75  1.133.2.1      yamt #include <sys/kmem.h>
     76       1.12  christos #include <sys/systm.h>
     77      1.106        ad #include <sys/debug.h>
     78      1.109        ad #include <sys/mutex.h>
     79      1.113        ad #include <sys/lockdebug.h>
     80       1.24   thorpej 
     81       1.28       mrg #include <uvm/uvm_extern.h>
     82       1.28       mrg 
     83       1.24   thorpej #include "opt_kmemstats.h"
     84       1.27   thorpej #include "opt_malloclog.h"
     85       1.71      fvdl #include "opt_malloc_debug.h"
     86       1.12  christos 
     87       1.99       chs struct kmembuckets kmembuckets[MINBUCKET + 16];
     88        1.1       cgd struct kmemusage *kmemusage;
     89       1.77   thorpej struct malloc_type *kmemstatistics;
     90        1.1       cgd 
     91      1.109        ad kmutex_t malloc_lock;
     92       1.78        pk 
     93  1.133.2.1      yamt struct malloc_header {
     94  1.133.2.1      yamt 	/* Total size, include the header. */
     95  1.133.2.1      yamt 	size_t		mh_size;
     96  1.133.2.1      yamt } __aligned(ALIGNBYTES+1);
     97  1.133.2.1      yamt 
     98       1.77   thorpej /*
     99        1.1       cgd  * Allocate a block of memory
    100        1.1       cgd  */
    101       1.27   thorpej #ifdef MALLOCLOG
    102       1.27   thorpej void *
    103      1.125     pooka _kern_malloc(unsigned long size, struct malloc_type *ksp, int flags,
    104       1.77   thorpej     const char *file, long line)
    105       1.27   thorpej #else
    106        1.1       cgd void *
    107      1.125     pooka kern_malloc(unsigned long size, struct malloc_type *ksp, int flags)
    108       1.27   thorpej #endif /* MALLOCLOG */
    109        1.1       cgd {
    110  1.133.2.1      yamt 	const int kmflags = (flags & M_NOWAIT) ? KM_NOSLEEP : KM_SLEEP;
    111  1.133.2.1      yamt 	size_t allocsize, hdroffset;
    112  1.133.2.1      yamt 	struct malloc_header *mh;
    113  1.133.2.1      yamt 	void *p;
    114  1.133.2.1      yamt 
    115  1.133.2.1      yamt 	if (size >= PAGE_SIZE) {
    116  1.133.2.1      yamt 		allocsize = PAGE_SIZE + size; /* for page alignment */
    117  1.133.2.1      yamt 		hdroffset = PAGE_SIZE - sizeof(struct malloc_header);
    118  1.133.2.1      yamt 	} else {
    119  1.133.2.1      yamt 		allocsize = sizeof(struct malloc_header) + size;
    120  1.133.2.1      yamt 		hdroffset = 0;
    121  1.133.2.1      yamt 	}
    122  1.133.2.1      yamt 
    123  1.133.2.1      yamt 	p = kmem_intr_alloc(allocsize, kmflags);
    124  1.133.2.1      yamt 	if (p == NULL)
    125  1.133.2.1      yamt 		return NULL;
    126       1.11       cgd 
    127  1.133.2.1      yamt 	if ((flags & M_ZERO) != 0) {
    128  1.133.2.1      yamt 		memset(p, 0, allocsize);
    129        1.8       cgd 	}
    130  1.133.2.1      yamt 	mh = (void *)((char *)p + hdroffset);
    131  1.133.2.1      yamt 	mh->mh_size = allocsize - hdroffset;
    132       1.11       cgd 
    133  1.133.2.1      yamt 	return mh + 1;
    134        1.1       cgd }
    135        1.1       cgd 
    136        1.1       cgd /*
    137        1.1       cgd  * Free a block of memory allocated by malloc.
    138        1.1       cgd  */
    139       1.27   thorpej #ifdef MALLOCLOG
    140       1.27   thorpej void
    141      1.125     pooka _kern_free(void *addr, struct malloc_type *ksp, const char *file, long line)
    142       1.27   thorpej #else
    143        1.1       cgd void
    144      1.125     pooka kern_free(void *addr, struct malloc_type *ksp)
    145       1.27   thorpej #endif /* MALLOCLOG */
    146        1.1       cgd {
    147  1.133.2.1      yamt 	struct malloc_header *mh;
    148       1.62   thorpej 
    149  1.133.2.1      yamt 	mh = addr;
    150  1.133.2.1      yamt 	mh--;
    151      1.112        ad 
    152  1.133.2.1      yamt 	if (mh->mh_size >= PAGE_SIZE + sizeof(struct malloc_header))
    153  1.133.2.1      yamt 		kmem_intr_free((char *)addr - PAGE_SIZE,
    154  1.133.2.1      yamt 		    mh->mh_size + PAGE_SIZE - sizeof(struct malloc_header));
    155        1.8       cgd 	else
    156  1.133.2.1      yamt 		kmem_intr_free(mh, mh->mh_size);
    157       1.20       cgd }
    158       1.20       cgd 
    159       1.20       cgd /*
    160       1.20       cgd  * Change the size of a block of memory.
    161       1.20       cgd  */
    162       1.20       cgd void *
    163      1.126     pooka kern_realloc(void *curaddr, unsigned long newsize, struct malloc_type *ksp,
    164       1.77   thorpej     int flags)
    165       1.20       cgd {
    166  1.133.2.1      yamt 	struct malloc_header *mh;
    167       1.72   thorpej 	unsigned long cursize;
    168       1.20       cgd 	void *newaddr;
    169       1.20       cgd 
    170       1.20       cgd 	/*
    171       1.69     enami 	 * realloc() with a NULL pointer is the same as malloc().
    172       1.20       cgd 	 */
    173       1.20       cgd 	if (curaddr == NULL)
    174       1.77   thorpej 		return (malloc(newsize, ksp, flags));
    175       1.20       cgd 
    176       1.20       cgd 	/*
    177       1.69     enami 	 * realloc() with zero size is the same as free().
    178       1.20       cgd 	 */
    179       1.20       cgd 	if (newsize == 0) {
    180       1.77   thorpej 		free(curaddr, ksp);
    181       1.20       cgd 		return (NULL);
    182       1.20       cgd 	}
    183       1.59   thorpej 
    184       1.59   thorpej #ifdef LOCKDEBUG
    185      1.119        ad 	if ((flags & M_NOWAIT) == 0) {
    186      1.118      yamt 		ASSERT_SLEEPABLE();
    187      1.119        ad 	}
    188       1.59   thorpej #endif
    189       1.20       cgd 
    190  1.133.2.1      yamt 	mh = curaddr;
    191  1.133.2.1      yamt 	mh--;
    192       1.20       cgd 
    193  1.133.2.1      yamt 	cursize = mh->mh_size - sizeof(struct malloc_header);
    194       1.20       cgd 
    195       1.20       cgd 	/*
    196       1.20       cgd 	 * If we already actually have as much as they want, we're done.
    197       1.20       cgd 	 */
    198       1.20       cgd 	if (newsize <= cursize)
    199       1.20       cgd 		return (curaddr);
    200       1.20       cgd 
    201       1.20       cgd 	/*
    202       1.20       cgd 	 * Can't satisfy the allocation with the existing block.
    203       1.20       cgd 	 * Allocate a new one and copy the data.
    204       1.20       cgd 	 */
    205       1.77   thorpej 	newaddr = malloc(newsize, ksp, flags);
    206       1.51   thorpej 	if (__predict_false(newaddr == NULL)) {
    207       1.20       cgd 		/*
    208       1.69     enami 		 * malloc() failed, because flags included M_NOWAIT.
    209       1.20       cgd 		 * Return NULL to indicate that failure.  The old
    210       1.20       cgd 		 * pointer is still valid.
    211       1.20       cgd 		 */
    212       1.69     enami 		return (NULL);
    213       1.20       cgd 	}
    214       1.34     perry 	memcpy(newaddr, curaddr, cursize);
    215       1.20       cgd 
    216       1.20       cgd 	/*
    217       1.20       cgd 	 * We were successful: free the old allocation and return
    218       1.20       cgd 	 * the new one.
    219       1.20       cgd 	 */
    220       1.77   thorpej 	free(curaddr, ksp);
    221       1.20       cgd 	return (newaddr);
    222       1.70     enami }
    223       1.70     enami 
    224       1.70     enami /*
    225       1.77   thorpej  * Add a malloc type to the system.
    226       1.77   thorpej  */
    227       1.77   thorpej void
    228       1.77   thorpej malloc_type_attach(struct malloc_type *type)
    229       1.77   thorpej {
    230       1.77   thorpej 
    231       1.77   thorpej 	if (type->ks_magic != M_MAGIC)
    232       1.77   thorpej 		panic("malloc_type_attach: bad magic");
    233       1.77   thorpej 
    234       1.77   thorpej #ifdef DIAGNOSTIC
    235       1.77   thorpej 	{
    236       1.77   thorpej 		struct malloc_type *ksp;
    237       1.77   thorpej 		for (ksp = kmemstatistics; ksp != NULL; ksp = ksp->ks_next) {
    238       1.77   thorpej 			if (ksp == type)
    239      1.131  christos 				panic("%s: `%s' already on list", __func__,
    240      1.131  christos 				    type->ks_shortdesc);
    241       1.77   thorpej 		}
    242       1.77   thorpej 	}
    243       1.77   thorpej #endif
    244       1.77   thorpej 
    245       1.77   thorpej #ifdef KMEMSTATS
    246       1.77   thorpej #else
    247       1.77   thorpej 	type->ks_limit = 0;
    248       1.77   thorpej #endif
    249       1.77   thorpej 
    250       1.77   thorpej 	type->ks_next = kmemstatistics;
    251       1.77   thorpej 	kmemstatistics = type;
    252       1.77   thorpej }
    253       1.77   thorpej 
    254       1.77   thorpej /*
    255       1.77   thorpej  * Remove a malloc type from the system..
    256       1.77   thorpej  */
    257       1.77   thorpej void
    258       1.77   thorpej malloc_type_detach(struct malloc_type *type)
    259       1.77   thorpej {
    260       1.77   thorpej 	struct malloc_type *ksp;
    261       1.77   thorpej 
    262       1.77   thorpej #ifdef DIAGNOSTIC
    263       1.77   thorpej 	if (type->ks_magic != M_MAGIC)
    264       1.77   thorpej 		panic("malloc_type_detach: bad magic");
    265       1.77   thorpej #endif
    266       1.77   thorpej 
    267       1.77   thorpej 	if (type == kmemstatistics)
    268       1.77   thorpej 		kmemstatistics = type->ks_next;
    269       1.77   thorpej 	else {
    270       1.77   thorpej 		for (ksp = kmemstatistics; ksp->ks_next != NULL;
    271       1.77   thorpej 		     ksp = ksp->ks_next) {
    272       1.77   thorpej 			if (ksp->ks_next == type) {
    273       1.77   thorpej 				ksp->ks_next = type->ks_next;
    274       1.77   thorpej 				break;
    275       1.77   thorpej 			}
    276       1.77   thorpej 		}
    277       1.77   thorpej #ifdef DIAGNOSTIC
    278       1.77   thorpej 		if (ksp->ks_next == NULL)
    279       1.77   thorpej 			panic("malloc_type_detach: not on list");
    280       1.77   thorpej #endif
    281       1.77   thorpej 	}
    282       1.77   thorpej 	type->ks_next = NULL;
    283       1.77   thorpej }
    284       1.77   thorpej 
    285       1.77   thorpej /*
    286       1.77   thorpej  * Set the limit on a malloc type.
    287       1.77   thorpej  */
    288       1.77   thorpej void
    289      1.105      yamt malloc_type_setlimit(struct malloc_type *type, u_long limit)
    290       1.77   thorpej {
    291       1.77   thorpej #ifdef KMEMSTATS
    292      1.113        ad 	mutex_spin_enter(&malloc_lock);
    293       1.77   thorpej 	type->ks_limit = limit;
    294      1.113        ad 	mutex_spin_exit(&malloc_lock);
    295       1.77   thorpej #endif
    296       1.77   thorpej }
    297       1.77   thorpej 
    298       1.77   thorpej /*
    299        1.1       cgd  * Initialize the kernel memory allocator
    300        1.1       cgd  */
    301       1.12  christos void
    302       1.69     enami kmeminit(void)
    303        1.1       cgd {
    304       1.77   thorpej 	__link_set_decl(malloc_types, struct malloc_type);
    305       1.77   thorpej 	struct malloc_type * const *ksp;
    306       1.23       tls #ifdef KMEMSTATS
    307       1.50  augustss 	long indx;
    308       1.23       tls #endif
    309        1.1       cgd 
    310      1.116        ad 	mutex_init(&malloc_lock, MUTEX_DEFAULT, IPL_VM);
    311      1.109        ad 
    312        1.1       cgd #ifdef KMEMSTATS
    313        1.1       cgd 	for (indx = 0; indx < MINBUCKET + 16; indx++) {
    314       1.49   thorpej 		if (1 << indx >= PAGE_SIZE)
    315       1.99       chs 			kmembuckets[indx].kb_elmpercl = 1;
    316        1.1       cgd 		else
    317       1.99       chs 			kmembuckets[indx].kb_elmpercl = PAGE_SIZE / (1 << indx);
    318       1.99       chs 		kmembuckets[indx].kb_highwat =
    319       1.99       chs 			5 * kmembuckets[indx].kb_elmpercl;
    320        1.1       cgd 	}
    321       1.62   thorpej #endif
    322       1.77   thorpej 
    323       1.77   thorpej 	/* Attach all of the statically-linked malloc types. */
    324       1.77   thorpej 	__link_set_foreach(ksp, malloc_types)
    325       1.77   thorpej 		malloc_type_attach(*ksp);
    326      1.127     pooka 
    327      1.127     pooka #ifdef MALLOC_DEBUG
    328      1.127     pooka 	debug_malloc_init();
    329      1.127     pooka #endif
    330        1.1       cgd }
    331       1.39   thorpej 
    332       1.39   thorpej #ifdef DDB
    333       1.39   thorpej #include <ddb/db_output.h>
    334       1.39   thorpej 
    335       1.39   thorpej /*
    336       1.39   thorpej  * Dump kmem statistics from ddb.
    337       1.39   thorpej  *
    338       1.39   thorpej  * usage: call dump_kmemstats
    339       1.39   thorpej  */
    340       1.69     enami void	dump_kmemstats(void);
    341       1.39   thorpej 
    342       1.39   thorpej void
    343       1.69     enami dump_kmemstats(void)
    344       1.39   thorpej {
    345       1.39   thorpej #ifdef KMEMSTATS
    346       1.77   thorpej 	struct malloc_type *ksp;
    347       1.39   thorpej 
    348       1.77   thorpej 	for (ksp = kmemstatistics; ksp != NULL; ksp = ksp->ks_next) {
    349       1.77   thorpej 		if (ksp->ks_memuse == 0)
    350       1.77   thorpej 			continue;
    351       1.77   thorpej 		db_printf("%s%.*s %ld\n", ksp->ks_shortdesc,
    352       1.77   thorpej 		    (int)(20 - strlen(ksp->ks_shortdesc)),
    353       1.77   thorpej 		    "                    ",
    354       1.77   thorpej 		    ksp->ks_memuse);
    355       1.39   thorpej 	}
    356       1.39   thorpej #else
    357       1.39   thorpej 	db_printf("Kmem stats are not being collected.\n");
    358       1.39   thorpej #endif /* KMEMSTATS */
    359       1.39   thorpej }
    360       1.39   thorpej #endif /* DDB */
    361       1.82      manu 
    362       1.82      manu 
    363       1.82      manu #if 0
    364       1.96     perry /*
    365       1.82      manu  * Diagnostic messages about "Data modified on
    366       1.82      manu  * freelist" indicate a memory corruption, but
    367       1.82      manu  * they do not help tracking it down.
    368       1.96     perry  * This function can be called at various places
    369       1.82      manu  * to sanity check malloc's freelist and discover
    370       1.82      manu  * where does the corruption take place.
    371       1.82      manu  */
    372       1.82      manu int
    373       1.82      manu freelist_sanitycheck(void) {
    374       1.82      manu 	int i,j;
    375       1.82      manu 	struct kmembuckets *kbp;
    376       1.82      manu 	struct freelist *freep;
    377       1.82      manu 	int rv = 0;
    378       1.96     perry 
    379       1.82      manu 	for (i = MINBUCKET; i <= MINBUCKET + 15; i++) {
    380       1.99       chs 		kbp = &kmembuckets[i];
    381       1.82      manu 		freep = (struct freelist *)kbp->kb_next;
    382       1.82      manu 		j = 0;
    383       1.82      manu 		while(freep) {
    384       1.82      manu 			vm_map_lock(kmem_map);
    385       1.82      manu 			rv = uvm_map_checkprot(kmem_map, (vaddr_t)freep,
    386       1.96     perry 			    (vaddr_t)freep + sizeof(struct freelist),
    387       1.82      manu 			    VM_PROT_WRITE);
    388       1.82      manu 			vm_map_unlock(kmem_map);
    389       1.82      manu 
    390       1.82      manu 			if ((rv == 0) || (*(int *)freep != WEIRD_ADDR)) {
    391       1.82      manu 				printf("bucket %i, chunck %d at %p modified\n",
    392       1.82      manu 				    i, j, freep);
    393       1.82      manu 				return 1;
    394       1.82      manu 			}
    395       1.82      manu 			freep = (struct freelist *)freep->next;
    396       1.82      manu 			j++;
    397       1.82      manu 		}
    398       1.82      manu 	}
    399       1.82      manu 
    400       1.82      manu 	return 0;
    401       1.82      manu }
    402       1.82      manu #endif
    403