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