1/* 2 * Copyright (c) 1987, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)kern_malloc.c 8.3 (Berkeley) 1/4/94
|
34 * $FreeBSD: head/sys/kern/kern_malloc.c 92194 2002-03-13 01:42:33Z archie $
|
34 * $FreeBSD: head/sys/kern/kern_malloc.c 92654 2002-03-19 09:11:49Z jeff $ |
35 */ 36 37#include "opt_vm.h" 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/kernel.h> 42#include <sys/lock.h> 43#include <sys/malloc.h> 44#include <sys/mbuf.h> 45#include <sys/mutex.h> 46#include <sys/vmmeter.h> 47#include <sys/proc.h> 48 49#include <vm/vm.h> 50#include <vm/vm_param.h> 51#include <vm/vm_kern.h> 52#include <vm/vm_extern.h> 53#include <vm/pmap.h> 54#include <vm/vm_map.h>
|
55#include <vm/uma.h> 56#include <vm/uma_int.h> |
57 58#if defined(INVARIANTS) && defined(__i386__) 59#include <machine/cpu.h> 60#endif 61 62/* 63 * When realloc() is called, if the new size is sufficiently smaller than 64 * the old size, realloc() will allocate a new, smaller block to avoid 65 * wasting memory. 'Sufficiently smaller' is defined as: newsize <= 66 * oldsize / 2^n, where REALLOC_FRACTION defines the value of 'n'. 67 */ 68#ifndef REALLOC_FRACTION 69#define REALLOC_FRACTION 1 /* new block if <= half the size */ 70#endif 71 72MALLOC_DEFINE(M_CACHE, "cache", "Various Dynamically allocated caches"); 73MALLOC_DEFINE(M_DEVBUF, "devbuf", "device driver memory"); 74MALLOC_DEFINE(M_TEMP, "temp", "misc temporary data buffers"); 75 76MALLOC_DEFINE(M_IP6OPT, "ip6opt", "IPv6 options"); 77MALLOC_DEFINE(M_IP6NDP, "ip6ndp", "IPv6 Neighbor Discovery"); 78 79static void kmeminit __P((void *)); 80SYSINIT(kmem, SI_SUB_KMEM, SI_ORDER_FIRST, kmeminit, NULL) 81 82static MALLOC_DEFINE(M_FREE, "free", "should be on free list"); 83 84static struct malloc_type *kmemstatistics;
|
83static struct kmembuckets bucket[MINBUCKET + 16];
84static struct kmemusage *kmemusage;
|
85static char *kmembase; 86static char *kmemlimit; 87
|
88static struct mtx malloc_mtx;
|
88#define KMEM_ZSHIFT 4 89#define KMEM_ZBASE 16 90#define KMEM_ZMASK (KMEM_ZBASE - 1) |
91
|
90u_int vm_kmem_size;
|
92#define KMEM_ZMAX 65536 93#define KMEM_ZSIZE (KMEM_ZMAX >> KMEM_ZSHIFT) 94static uma_zone_t kmemzones[KMEM_ZSIZE + 1]; |
95
|
92#ifdef INVARIANTS
93/*
94 * This structure provides a set of masks to catch unaligned frees.
95 */
96static long addrmask[] = { 0,
97 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
98 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
99 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
100 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
|
96 97/* These won't be powers of two for long */ 98struct { 99 int size; 100 char *name; 101} kmemsizes[] = { 102 {16, "16"}, 103 {32, "32"}, 104 {64, "64"}, 105 {128, "128"}, 106 {256, "256"}, 107 {512, "512"}, 108 {1024, "1024"}, 109 {2048, "2048"}, 110 {4096, "4096"}, 111 {8192, "8192"}, 112 {16384, "16384"}, 113 {32768, "32768"}, 114 {65536, "65536"}, 115 {0, NULL}, |
116}; 117
|
103/*
104 * The WEIRD_ADDR is used as known text to copy into free objects so
105 * that modifications after frees can be detected.
106 */
107#define WEIRD_ADDR 0xdeadc0de
108#define MAX_COPY 64
|
118static struct mtx malloc_mtx; |
119
|
110/*
111 * Normally the first word of the structure is used to hold the list
112 * pointer for free objects. However, when running with diagnostics,
113 * we use the third and fourth fields, so as to catch modifications
114 * in the most commonly trashed first two words.
115 */
116struct freelist {
117 long spare0;
118 struct malloc_type *type;
119 long spare1;
120 caddr_t next;
121};
122#else /* !INVARIANTS */
123struct freelist {
124 caddr_t next;
125};
126#endif /* INVARIANTS */
|
120u_int vm_kmem_size; |
121 122/* 123 * malloc: 124 * 125 * Allocate a block of memory. 126 * 127 * If M_NOWAIT is set, this routine will not block and return NULL if 128 * the allocation fails. 129 */ 130void * 131malloc(size, type, flags) 132 unsigned long size; 133 struct malloc_type *type; 134 int flags; 135{
|
142 register struct kmembuckets *kbp;
143 register struct kmemusage *kup;
144 register struct freelist *freep;
145 long indx, npg, allocsize;
|
136 int s;
|
147 caddr_t va, cp, savedlist;
148#ifdef INVARIANTS
149 long *end, *lp;
150 int copysize;
151 const char *savedtype;
152#endif
|
137 long indx; 138 caddr_t va; 139 uma_zone_t zone; |
140 register struct malloc_type *ksp = type; 141 142#if defined(INVARIANTS) 143 if (flags == M_WAITOK) 144 KASSERT(curthread->td_intr_nesting_level == 0, 145 ("malloc(M_WAITOK) in interrupt context")); 146#endif
|
160 indx = BUCKETINDX(size);
161 kbp = &bucket[indx];
|
147 s = splmem();
|
163 mtx_lock(&malloc_mtx);
|
148 /* mtx_lock(&malloc_mtx); XXX */ |
149 while (ksp->ks_memuse >= ksp->ks_limit) { 150 if (flags & M_NOWAIT) { 151 splx(s);
|
167 mtx_unlock(&malloc_mtx);
|
152 /* mtx_unlock(&malloc_mtx); XXX */ |
153 return ((void *) NULL); 154 } 155 if (ksp->ks_limblocks < 65535) 156 ksp->ks_limblocks++;
|
172 msleep((caddr_t)ksp, &malloc_mtx, PSWP+2, type->ks_shortdesc,
|
157 msleep((caddr_t)ksp, /* &malloc_mtx */ NULL, PSWP+2, type->ks_shortdesc, |
158 0); 159 }
|
175 ksp->ks_size |= 1 << indx;
176#ifdef INVARIANTS
177 copysize = 1 << indx < MAX_COPY ? 1 << indx : MAX_COPY;
178#endif
179 if (kbp->kb_next == NULL) {
180 kbp->kb_last = NULL;
181 if (size > MAXALLOCSAVE)
182 allocsize = roundup(size, PAGE_SIZE);
183 else
184 allocsize = 1 << indx;
185 npg = btoc(allocsize);
|
160 /* mtx_unlock(&malloc_mtx); XXX */ |
161
|
187 mtx_unlock(&malloc_mtx);
188 va = (caddr_t) kmem_malloc(kmem_map, (vm_size_t)ctob(npg), flags);
189
|
162 if (size <= KMEM_ZMAX) { 163 indx = size; 164 if (indx & KMEM_ZMASK) 165 indx = (indx & ~KMEM_ZMASK) + KMEM_ZBASE; 166 zone = kmemzones[indx >> KMEM_ZSHIFT]; 167 indx = zone->uz_size; 168 va = uma_zalloc(zone, flags); |
169 if (va == NULL) {
|
191 splx(s);
192 return ((void *) NULL);
|
170 /* mtx_lock(&malloc_mtx); XXX */ 171 goto out; |
172 }
|
194 /*
195 * Enter malloc_mtx after the error check to avoid having to
196 * immediately exit it again if there is an error.
197 */
198 mtx_lock(&malloc_mtx);
199
200 kbp->kb_total += kbp->kb_elmpercl;
201 kup = btokup(va);
202 kup->ku_indx = indx;
203 if (allocsize > MAXALLOCSAVE) {
204 if (npg > 65535)
205 panic("malloc: allocation too large");
206 kup->ku_pagecnt = npg;
207 ksp->ks_memuse += allocsize;
|
173 ksp->ks_size |= indx; 174 } else { 175 /* XXX This is not the next power of two so this will break ks_size */ 176 indx = roundup(size, PAGE_SIZE); 177 zone = NULL; 178 va = uma_large_malloc(size, flags); 179 if (va == NULL) { 180 /* mtx_lock(&malloc_mtx); XXX */ |
181 goto out; 182 }
|
210 kup->ku_freecnt = kbp->kb_elmpercl;
211 kbp->kb_totalfree += kbp->kb_elmpercl;
212 /*
213 * Just in case we blocked while allocating memory,
214 * and someone else also allocated memory for this
215 * bucket, don't assume the list is still empty.
216 */
217 savedlist = kbp->kb_next;
218 kbp->kb_next = cp = va + (npg * PAGE_SIZE) - allocsize;
219 for (;;) {
220 freep = (struct freelist *)cp;
221#ifdef INVARIANTS
222 /*
223 * Copy in known text to detect modification
224 * after freeing.
225 */
226 end = (long *)&cp[copysize];
227 for (lp = (long *)cp; lp < end; lp++)
228 *lp = WEIRD_ADDR;
229 freep->type = M_FREE;
230#endif /* INVARIANTS */
231 if (cp <= va)
232 break;
233 cp -= allocsize;
234 freep->next = cp;
235 }
236 freep->next = savedlist;
237 if (kbp->kb_last == NULL)
238 kbp->kb_last = (caddr_t)freep;
|
183 }
|
240 va = kbp->kb_next;
241 kbp->kb_next = ((struct freelist *)va)->next;
242#ifdef INVARIANTS
243 freep = (struct freelist *)va;
244 savedtype = (const char *) freep->type->ks_shortdesc;
245 freep->type = (struct malloc_type *)WEIRD_ADDR;
246 if ((intptr_t)(void *)&freep->next & 0x2)
247 freep->next = (caddr_t)((WEIRD_ADDR >> 16)|(WEIRD_ADDR << 16));
248 else
249 freep->next = (caddr_t)WEIRD_ADDR;
250 end = (long *)&va[copysize];
251 for (lp = (long *)va; lp < end; lp++) {
252 if (*lp == WEIRD_ADDR)
253 continue;
254 printf("%s %ld of object %p size %lu %s %s (0x%lx != 0x%lx)\n",
255 "Data modified on freelist: word",
256 (long)(lp - (long *)va), (void *)va, size,
257 "previous type", savedtype, *lp, (u_long)WEIRD_ADDR);
258 break;
259 }
260 freep->spare0 = 0;
261#endif /* INVARIANTS */
262 kup = btokup(va);
263 if (kup->ku_indx != indx)
264 panic("malloc: wrong bucket");
265 if (kup->ku_freecnt == 0)
266 panic("malloc: lost data");
267 kup->ku_freecnt--;
268 kbp->kb_totalfree--;
269 ksp->ks_memuse += 1 << indx;
270out:
271 kbp->kb_calls++;
|
184 /* mtx_lock(&malloc_mtx); XXX */ 185 ksp->ks_memuse += indx; |
186 ksp->ks_inuse++;
|
187out: |
188 ksp->ks_calls++; 189 if (ksp->ks_memuse > ksp->ks_maxused) 190 ksp->ks_maxused = ksp->ks_memuse; 191 splx(s);
|
277 mtx_unlock(&malloc_mtx);
|
192 /* mtx_unlock(&malloc_mtx); XXX */ |
193 /* XXX: Do idle pre-zeroing. */ 194 if (va != NULL && (flags & M_ZERO)) 195 bzero(va, size); 196 return ((void *) va); 197} 198 199/* 200 * free: 201 * 202 * Free a block of memory allocated by malloc. 203 * 204 * This routine may not block. 205 */ 206void 207free(addr, type) 208 void *addr; 209 struct malloc_type *type; 210{
|
296 register struct kmembuckets *kbp;
297 register struct kmemusage *kup;
298 register struct freelist *freep;
299 long size;
|
211 uma_slab_t slab; 212 void *mem; 213 u_long size; |
214 int s;
|
301#ifdef INVARIANTS
302 struct freelist *fp;
303 long *end, *lp, alloc, copysize;
304#endif
|
215 register struct malloc_type *ksp = type; 216 217 /* free(NULL, ...) does nothing */ 218 if (addr == NULL) 219 return; 220
|
311 KASSERT(kmembase <= (char *)addr && (char *)addr < kmemlimit,
312 ("free: address %p out of range", (void *)addr));
313 kup = btokup(addr);
314 size = 1 << kup->ku_indx;
315 kbp = &bucket[kup->ku_indx];
|
221 size = 0; |
222 s = splmem();
|
317 mtx_lock(&malloc_mtx);
318#ifdef INVARIANTS
319 /*
320 * Check for returns of data that do not point to the
321 * beginning of the allocation.
322 */
323 if (size > PAGE_SIZE)
324 alloc = addrmask[BUCKETINDX(PAGE_SIZE)];
325 else
326 alloc = addrmask[kup->ku_indx];
327 if (((uintptr_t)(void *)addr & alloc) != 0)
328 panic("free: unaligned addr %p, size %ld, type %s, mask %ld",
329 (void *)addr, size, type->ks_shortdesc, alloc);
330#endif /* INVARIANTS */
331 if (size > MAXALLOCSAVE) {
332 mtx_unlock(&malloc_mtx);
333 kmem_free(kmem_map, (vm_offset_t)addr, ctob(kup->ku_pagecnt));
334 mtx_lock(&malloc_mtx);
|
223
|
336 size = kup->ku_pagecnt << PAGE_SHIFT;
337 ksp->ks_memuse -= size;
338 kup->ku_indx = 0;
339 kup->ku_pagecnt = 0;
340 if (ksp->ks_memuse + size >= ksp->ks_limit &&
341 ksp->ks_memuse < ksp->ks_limit)
342 wakeup((caddr_t)ksp);
343 ksp->ks_inuse--;
344 kbp->kb_total -= 1;
345 splx(s);
346 mtx_unlock(&malloc_mtx);
347 return;
|
224 mem = (void *)((u_long)addr & (~UMA_SLAB_MASK)); 225 slab = hash_sfind(mallochash, mem); 226 227 if (slab == NULL) 228 panic("free: address %p(%p) has not been allocated.\n", addr, mem); 229 230 if (!(slab->us_flags & UMA_SLAB_MALLOC)) { 231 size = slab->us_zone->uz_size; 232 uma_zfree_arg(slab->us_zone, addr, slab); 233 } else { 234 size = slab->us_size; 235 uma_large_free(slab); |
236 }
|
349 freep = (struct freelist *)addr;
350#ifdef INVARIANTS
351 /*
352 * Check for multiple frees. Use a quick check to see if
353 * it looks free before laboriously searching the freelist.
354 */
355 if (freep->spare0 == WEIRD_ADDR) {
356 fp = (struct freelist *)kbp->kb_next;
357 while (fp) {
358 if (fp->spare0 != WEIRD_ADDR)
359 panic("free: free item %p modified", fp);
360 else if (addr == (caddr_t)fp)
361 panic("free: multiple freed item %p", addr);
362 fp = (struct freelist *)fp->next;
363 }
364 }
365 /*
366 * Copy in known text to detect modification after freeing
367 * and to make it look free. Also, save the type being freed
368 * so we can list likely culprit if modification is detected
369 * when the object is reallocated.
370 */
371 copysize = size < MAX_COPY ? size : MAX_COPY;
372 end = (long *)&((caddr_t)addr)[copysize];
373 for (lp = (long *)addr; lp < end; lp++)
374 *lp = WEIRD_ADDR;
375 freep->type = type;
376#endif /* INVARIANTS */
377 kup->ku_freecnt++;
378 if (kup->ku_freecnt >= kbp->kb_elmpercl) {
379 if (kup->ku_freecnt > kbp->kb_elmpercl)
380 panic("free: multiple frees");
381 else if (kbp->kb_totalfree > kbp->kb_highwat)
382 kbp->kb_couldfree++;
383 }
384 kbp->kb_totalfree++;
|
237 /* mtx_lock(&malloc_mtx); XXX */ 238 |
239 ksp->ks_memuse -= size; 240 if (ksp->ks_memuse + size >= ksp->ks_limit && 241 ksp->ks_memuse < ksp->ks_limit) 242 wakeup((caddr_t)ksp); 243 ksp->ks_inuse--;
|
390#ifdef OLD_MALLOC_MEMORY_POLICY
391 if (kbp->kb_next == NULL)
392 kbp->kb_next = addr;
393 else
394 ((struct freelist *)kbp->kb_last)->next = addr;
395 freep->next = NULL;
396 kbp->kb_last = addr;
397#else
398 /*
399 * Return memory to the head of the queue for quick reuse. This
400 * can improve performance by improving the probability of the
401 * item being in the cache when it is reused.
402 */
403 if (kbp->kb_next == NULL) {
404 kbp->kb_next = addr;
405 kbp->kb_last = addr;
406 freep->next = NULL;
407 } else {
408 freep->next = kbp->kb_next;
409 kbp->kb_next = addr;
410 }
411#endif
|
244 splx(s);
|
413 mtx_unlock(&malloc_mtx);
|
245 /* mtx_unlock(&malloc_mtx); XXX */ |
246} 247 248/* 249 * realloc: change the size of a memory block 250 */ 251void * 252realloc(addr, size, type, flags) 253 void *addr; 254 unsigned long size; 255 struct malloc_type *type; 256 int flags; 257{
|
426 struct kmemusage *kup;
|
258 uma_slab_t slab; |
259 unsigned long alloc; 260 void *newaddr; 261 262 /* realloc(NULL, ...) is equivalent to malloc(...) */ 263 if (addr == NULL) 264 return (malloc(size, type, flags)); 265
|
266 slab = hash_sfind(mallochash, 267 (void *)((u_long)addr & ~(UMA_SLAB_MASK))); 268 |
269 /* Sanity check */
|
435 KASSERT(kmembase <= (char *)addr && (char *)addr < kmemlimit,
|
270 KASSERT(slab != NULL, |
271 ("realloc: address %p out of range", (void *)addr)); 272 273 /* Get the size of the original block */
|
439 kup = btokup(addr);
440 alloc = 1 << kup->ku_indx;
441 if (alloc > MAXALLOCSAVE)
442 alloc = kup->ku_pagecnt << PAGE_SHIFT;
|
274 if (slab->us_zone) 275 alloc = slab->us_zone->uz_size; 276 else 277 alloc = slab->us_size; |
278 279 /* Reuse the original block if appropriate */ 280 if (size <= alloc 281 && (size > (alloc >> REALLOC_FRACTION) || alloc == MINALLOCSIZE)) 282 return (addr); 283 284 /* Allocate a new, bigger (or smaller) block */ 285 if ((newaddr = malloc(size, type, flags)) == NULL) 286 return (NULL); 287 288 /* Copy over original contents */ 289 bcopy(addr, newaddr, min(size, alloc)); 290 free(addr, type); 291 return (newaddr); 292} 293 294/* 295 * reallocf: same as realloc() but free memory on failure. 296 */ 297void * 298reallocf(addr, size, type, flags) 299 void *addr; 300 unsigned long size; 301 struct malloc_type *type; 302 int flags; 303{ 304 void *mem; 305 306 if ((mem = realloc(addr, size, type, flags)) == NULL) 307 free(addr, type); 308 return (mem); 309} 310 311/* 312 * Initialize the kernel memory allocator 313 */ 314/* ARGSUSED*/ 315static void 316kmeminit(dummy) 317 void *dummy; 318{ 319 register long indx; 320 u_long npg; 321 u_long mem_size;
|
322 void *hashmem; 323 u_long hashsize; 324 int highbit; 325 int bits; 326 int i; |
327
|
488#if ((MAXALLOCSAVE & (MAXALLOCSAVE - 1)) != 0)
489#error "kmeminit: MAXALLOCSAVE not power of 2"
490#endif
491#if (MAXALLOCSAVE > MINALLOCSIZE * 32768)
492#error "kmeminit: MAXALLOCSAVE too big"
493#endif
494#if (MAXALLOCSAVE < PAGE_SIZE)
495#error "kmeminit: MAXALLOCSAVE too small"
496#endif
497
|
328 mtx_init(&malloc_mtx, "malloc", MTX_DEF); 329 330 /* 331 * Try to auto-tune the kernel memory size, so that it is 332 * more applicable for a wider range of machine sizes. 333 * On an X86, a VM_KMEM_SIZE_SCALE value of 4 is good, while 334 * a VM_KMEM_SIZE of 12MB is a fair compromise. The 335 * VM_KMEM_SIZE_MAX is dependent on the maximum KVA space 336 * available, and on an X86 with a total KVA space of 256MB, 337 * try to keep VM_KMEM_SIZE_MAX at 80MB or below. 338 * 339 * Note that the kmem_map is also used by the zone allocator, 340 * so make sure that there is enough space. 341 */ 342 vm_kmem_size = VM_KMEM_SIZE; 343 mem_size = cnt.v_page_count * PAGE_SIZE; 344 345#if defined(VM_KMEM_SIZE_SCALE) 346 if ((mem_size / VM_KMEM_SIZE_SCALE) > vm_kmem_size) 347 vm_kmem_size = mem_size / VM_KMEM_SIZE_SCALE; 348#endif 349 350#if defined(VM_KMEM_SIZE_MAX) 351 if (vm_kmem_size >= VM_KMEM_SIZE_MAX) 352 vm_kmem_size = VM_KMEM_SIZE_MAX; 353#endif 354 355 /* Allow final override from the kernel environment */ 356 TUNABLE_INT_FETCH("kern.vm.kmem.size", &vm_kmem_size); 357 358 /* 359 * Limit kmem virtual size to twice the physical memory. 360 * This allows for kmem map sparseness, but limits the size 361 * to something sane. Be careful to not overflow the 32bit 362 * ints while doing the check. 363 */ 364 if ((vm_kmem_size / 2) > (cnt.v_page_count * PAGE_SIZE)) 365 vm_kmem_size = 2 * cnt.v_page_count * PAGE_SIZE; 366 367 /* 368 * In mbuf_init(), we set up submaps for mbufs and clusters, in which 369 * case we rounddown() (nmbufs * MSIZE) and (nmbclusters * MCLBYTES), 370 * respectively. Mathematically, this means that what we do here may 371 * amount to slightly more address space than we need for the submaps, 372 * but it never hurts to have an extra page in kmem_map. 373 */ 374 npg = (nmbufs * MSIZE + nmbclusters * MCLBYTES + nmbcnt * 375 sizeof(u_int) + vm_kmem_size) / PAGE_SIZE; 376
|
547 kmemusage = (struct kmemusage *) kmem_alloc(kernel_map,
548 (vm_size_t)(npg * sizeof(struct kmemusage)));
|
377 kmem_map = kmem_suballoc(kernel_map, (vm_offset_t *)&kmembase, 378 (vm_offset_t *)&kmemlimit, (vm_size_t)(npg * PAGE_SIZE)); 379 kmem_map->system_map = 1;
|
552 for (indx = 0; indx < MINBUCKET + 16; indx++) {
553 if (1 << indx >= PAGE_SIZE)
554 bucket[indx].kb_elmpercl = 1;
555 else
556 bucket[indx].kb_elmpercl = PAGE_SIZE / (1 << indx);
557 bucket[indx].kb_highwat = 5 * bucket[indx].kb_elmpercl;
|
380 381 hashsize = npg * sizeof(void *); 382 383 highbit = 0; 384 bits = 0; 385 /* The hash size must be a power of two */ 386 for (i = 0; i < 8 * sizeof(hashsize); i++) 387 if (hashsize & (1 << i)) { 388 highbit = i; 389 bits++; 390 } 391 if (bits > 1) 392 hashsize = 1 << (highbit); 393 394 hashmem = (void *)kmem_alloc(kernel_map, (vm_size_t)hashsize); 395 uma_startup2(hashmem, hashsize / sizeof(void *)); 396 397 for (i = 0, indx = 0; kmemsizes[indx].size != 0; indx++) { 398 uma_zone_t zone; 399 int size = kmemsizes[indx].size; 400 char *name = kmemsizes[indx].name; 401 402 zone = uma_zcreate(name, size, NULL, NULL, NULL, NULL, 403 UMA_ALIGN_PTR, UMA_ZONE_MALLOC); 404 for (;i <= size; i+= KMEM_ZBASE) 405 kmemzones[i >> KMEM_ZSHIFT] = zone; 406 |
407 } 408} 409 410void 411malloc_init(data) 412 void *data; 413{ 414 struct malloc_type *type = (struct malloc_type *)data; 415 416 if (type->ks_magic != M_MAGIC) 417 panic("malloc type lacks magic"); 418 419 if (type->ks_limit != 0) 420 return; 421 422 if (cnt.v_page_count == 0) 423 panic("malloc_init not allowed before vm init"); 424 425 /* 426 * The default limits for each malloc region is 1/2 of the 427 * malloc portion of the kmem map size. 428 */ 429 type->ks_limit = vm_kmem_size / 2; 430 type->ks_next = kmemstatistics; 431 kmemstatistics = type; 432} 433 434void 435malloc_uninit(data) 436 void *data; 437{ 438 struct malloc_type *type = (struct malloc_type *)data; 439 struct malloc_type *t;
|
591#ifdef INVARIANTS
592 struct kmembuckets *kbp;
593 struct freelist *freep;
594 long indx;
595 int s;
596#endif
|
440 441 if (type->ks_magic != M_MAGIC) 442 panic("malloc type lacks magic"); 443 444 if (cnt.v_page_count == 0) 445 panic("malloc_uninit not allowed before vm init"); 446 447 if (type->ks_limit == 0) 448 panic("malloc_uninit on uninitialized type"); 449
|
607#ifdef INVARIANTS
608 s = splmem();
609 mtx_lock(&malloc_mtx);
610 for (indx = 0; indx < MINBUCKET + 16; indx++) {
611 kbp = bucket + indx;
612 freep = (struct freelist*)kbp->kb_next;
613 while (freep) {
614 if (freep->type == type)
615 freep->type = M_FREE;
616 freep = (struct freelist*)freep->next;
617 }
618 }
619 splx(s);
620 mtx_unlock(&malloc_mtx);
621
622 if (type->ks_memuse != 0)
623 printf("malloc_uninit: %ld bytes of '%s' still allocated\n",
624 type->ks_memuse, type->ks_shortdesc);
625#endif
626
|
450 if (type == kmemstatistics) 451 kmemstatistics = type->ks_next; 452 else { 453 for (t = kmemstatistics; t->ks_next != NULL; t = t->ks_next) { 454 if (t->ks_next == type) { 455 t->ks_next = type->ks_next; 456 break; 457 } 458 } 459 } 460 type->ks_next = NULL; 461 type->ks_limit = 0; 462}
|