1bad3ecd0Sotto/* $NetBSD: kern_malloc.c,v 1.11 1995/05/01 22:39:11 cgd Exp $ */ 2bad3ecd0Sotto 3bad3ecd0Sotto/* 4bad3ecd0Sotto * Copyright (c) 1987, 1991, 1993 5bad3ecd0Sotto * The Regents of the University of California. All rights reserved. 6bad3ecd0Sotto * 7bad3ecd0Sotto * Redistribution and use in source and binary forms, with or without 8bad3ecd0Sotto * modification, are permitted provided that the following conditions 9bad3ecd0Sotto * are met: 10bad3ecd0Sotto * 1. Redistributions of source code must retain the above copyright 11bad3ecd0Sotto * notice, this list of conditions and the following disclaimer. 12bad3ecd0Sotto * 2. Redistributions in binary form must reproduce the above copyright 13bad3ecd0Sotto * notice, this list of conditions and the following disclaimer in the 14bad3ecd0Sotto * documentation and/or other materials provided with the distribution. 15*7dad4e2aSderaadt * 3. Neither the name of the University nor the names of its contributors 16bad3ecd0Sotto * may be used to endorse or promote products derived from this software 17bad3ecd0Sotto * without specific prior written permission. 18bad3ecd0Sotto * 19bad3ecd0Sotto * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20bad3ecd0Sotto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21bad3ecd0Sotto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22bad3ecd0Sotto * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23bad3ecd0Sotto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24bad3ecd0Sotto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25bad3ecd0Sotto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26bad3ecd0Sotto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27bad3ecd0Sotto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28bad3ecd0Sotto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29bad3ecd0Sotto * SUCH DAMAGE. 30bad3ecd0Sotto * 31bad3ecd0Sotto * @(#)kern_malloc.c 8.3 (Berkeley) 1/4/94 32bad3ecd0Sotto */ 33bad3ecd0Sotto 34bad3ecd0Sotto#include <sys/param.h> 35bad3ecd0Sotto#include <sys/proc.h> 36bad3ecd0Sotto#include <sys/map.h> 37bad3ecd0Sotto#include <sys/kernel.h> 38bad3ecd0Sotto#include <sys/malloc.h> 39bad3ecd0Sotto 40bad3ecd0Sotto#include <vm/vm.h> 41bad3ecd0Sotto#include <vm/vm_kern.h> 42bad3ecd0Sotto 43bad3ecd0Sottostruct kmembuckets bucket[MINBUCKET + 16]; 44bad3ecd0Sottostruct kmemstats kmemstats[M_LAST]; 45bad3ecd0Sottostruct kmemusage *kmemusage; 46bad3ecd0Sottochar *kmembase, *kmemlimit; 47bad3ecd0Sottochar *memname[] = INITKMEMNAMES; 48bad3ecd0Sotto 49bad3ecd0Sotto#ifdef DIAGNOSTIC 50bad3ecd0Sotto/* 51bad3ecd0Sotto * This structure provides a set of masks to catch unaligned frees. 52bad3ecd0Sotto */ 53bad3ecd0Sottolong addrmask[] = { 0, 54bad3ecd0Sotto 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 55bad3ecd0Sotto 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 56bad3ecd0Sotto 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, 57bad3ecd0Sotto 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff, 58bad3ecd0Sotto}; 59bad3ecd0Sotto 60bad3ecd0Sotto/* 61bad3ecd0Sotto * The WEIRD_ADDR is used as known text to copy into free objects so 62bad3ecd0Sotto * that modifications after frees can be detected. 63bad3ecd0Sotto */ 64bad3ecd0Sotto#define WEIRD_ADDR 0xdeadbeef 65bad3ecd0Sotto#define MAX_COPY 32 66bad3ecd0Sotto 67bad3ecd0Sotto/* 68bad3ecd0Sotto * Normally the freelist structure is used only to hold the list pointer 69bad3ecd0Sotto * for free objects. However, when running with diagnostics, the first 70bad3ecd0Sotto * 8 bytes of the structure is unused except for diagnostic information, 71bad3ecd0Sotto * and the free list pointer is at offst 8 in the structure. Since the 72bad3ecd0Sotto * first 8 bytes is the portion of the structure most often modified, this 73bad3ecd0Sotto * helps to detect memory reuse problems and avoid free list corruption. 74bad3ecd0Sotto */ 75bad3ecd0Sottostruct freelist { 76bad3ecd0Sotto int32_t spare0; 77bad3ecd0Sotto int16_t type; 78bad3ecd0Sotto int16_t spare1; 79bad3ecd0Sotto caddr_t next; 80bad3ecd0Sotto}; 81bad3ecd0Sotto#else /* !DIAGNOSTIC */ 82bad3ecd0Sottostruct freelist { 83bad3ecd0Sotto caddr_t next; 84bad3ecd0Sotto}; 85bad3ecd0Sotto#endif /* DIAGNOSTIC */ 86bad3ecd0Sotto 87bad3ecd0Sotto/* 88bad3ecd0Sotto * Allocate a block of memory 89bad3ecd0Sotto */ 90bad3ecd0Sottovoid * 91bad3ecd0Sottomalloc(size, type, flags) 92bad3ecd0Sotto unsigned long size; 93bad3ecd0Sotto int type, flags; 94bad3ecd0Sotto{ 95bad3ecd0Sotto register struct kmembuckets *kbp; 96bad3ecd0Sotto register struct kmemusage *kup; 97bad3ecd0Sotto register struct freelist *freep; 98bad3ecd0Sotto long indx, npg, allocsize; 99bad3ecd0Sotto int s; 100bad3ecd0Sotto caddr_t va, cp, savedlist; 101bad3ecd0Sotto#ifdef DIAGNOSTIC 102bad3ecd0Sotto int32_t *end, *lp; 103bad3ecd0Sotto int copysize; 104bad3ecd0Sotto char *savedtype; 105bad3ecd0Sotto#endif 106bad3ecd0Sotto#ifdef KMEMSTATS 107bad3ecd0Sotto register struct kmemstats *ksp = &kmemstats[type]; 108bad3ecd0Sotto 109bad3ecd0Sotto if (((unsigned long)type) > M_LAST) 110bad3ecd0Sotto panic("malloc - bogus type"); 111bad3ecd0Sotto#endif 112bad3ecd0Sotto indx = BUCKETINDX(size); 113bad3ecd0Sotto kbp = &bucket[indx]; 114bad3ecd0Sotto s = splimp(); 115bad3ecd0Sotto#ifdef KMEMSTATS 116bad3ecd0Sotto while (ksp->ks_memuse >= ksp->ks_limit) { 117bad3ecd0Sotto if (flags & M_NOWAIT) { 118bad3ecd0Sotto splx(s); 119bad3ecd0Sotto return ((void *) NULL); 120bad3ecd0Sotto } 121bad3ecd0Sotto if (ksp->ks_limblocks < 65535) 122bad3ecd0Sotto ksp->ks_limblocks++; 123bad3ecd0Sotto tsleep((caddr_t)ksp, PSWP+2, memname[type], 0); 124bad3ecd0Sotto } 125bad3ecd0Sotto ksp->ks_size |= 1 << indx; 126bad3ecd0Sotto#endif 127bad3ecd0Sotto#ifdef DIAGNOSTIC 128bad3ecd0Sotto copysize = 1 << indx < MAX_COPY ? 1 << indx : MAX_COPY; 129bad3ecd0Sotto#endif 130bad3ecd0Sotto if (kbp->kb_next == NULL) { 131bad3ecd0Sotto kbp->kb_last = NULL; 132bad3ecd0Sotto if (size > MAXALLOCSAVE) 133bad3ecd0Sotto allocsize = roundup(size, CLBYTES); 134bad3ecd0Sotto else 135bad3ecd0Sotto allocsize = 1 << indx; 136bad3ecd0Sotto npg = clrnd(btoc(allocsize)); 137bad3ecd0Sotto va = (caddr_t) kmem_malloc(kmem_map, (vm_size_t)ctob(npg), 138bad3ecd0Sotto !(flags & M_NOWAIT)); 139bad3ecd0Sotto if (va == NULL) { 140bad3ecd0Sotto splx(s); 141bad3ecd0Sotto return ((void *) NULL); 142bad3ecd0Sotto } 143bad3ecd0Sotto#ifdef KMEMSTATS 144bad3ecd0Sotto kbp->kb_total += kbp->kb_elmpercl; 145bad3ecd0Sotto#endif 146bad3ecd0Sotto kup = btokup(va); 147bad3ecd0Sotto kup->ku_indx = indx; 148bad3ecd0Sotto if (allocsize > MAXALLOCSAVE) { 149bad3ecd0Sotto if (npg > 65535) 150bad3ecd0Sotto panic("malloc: allocation too large"); 151bad3ecd0Sotto kup->ku_pagecnt = npg; 152bad3ecd0Sotto#ifdef KMEMSTATS 153bad3ecd0Sotto ksp->ks_memuse += allocsize; 154bad3ecd0Sotto#endif 155bad3ecd0Sotto goto out; 156bad3ecd0Sotto } 157bad3ecd0Sotto#ifdef KMEMSTATS 158bad3ecd0Sotto kup->ku_freecnt = kbp->kb_elmpercl; 159bad3ecd0Sotto kbp->kb_totalfree += kbp->kb_elmpercl; 160bad3ecd0Sotto#endif 161bad3ecd0Sotto /* 162bad3ecd0Sotto * Just in case we blocked while allocating memory, 163bad3ecd0Sotto * and someone else also allocated memory for this 164bad3ecd0Sotto * bucket, don't assume the list is still empty. 165bad3ecd0Sotto */ 166bad3ecd0Sotto savedlist = kbp->kb_next; 167bad3ecd0Sotto kbp->kb_next = cp = va + (npg * NBPG) - allocsize; 168bad3ecd0Sotto for (;;) { 169bad3ecd0Sotto freep = (struct freelist *)cp; 170bad3ecd0Sotto#ifdef DIAGNOSTIC 171bad3ecd0Sotto /* 172bad3ecd0Sotto * Copy in known text to detect modification 173bad3ecd0Sotto * after freeing. 174bad3ecd0Sotto */ 175bad3ecd0Sotto end = (int32_t *)&cp[copysize]; 176bad3ecd0Sotto for (lp = (int32_t *)cp; lp < end; lp++) 177bad3ecd0Sotto *lp = WEIRD_ADDR; 178bad3ecd0Sotto freep->type = M_FREE; 179bad3ecd0Sotto#endif /* DIAGNOSTIC */ 180bad3ecd0Sotto if (cp <= va) 181bad3ecd0Sotto break; 182bad3ecd0Sotto cp -= allocsize; 183bad3ecd0Sotto freep->next = cp; 184bad3ecd0Sotto } 185bad3ecd0Sotto freep->next = savedlist; 186bad3ecd0Sotto if (kbp->kb_last == NULL) 187bad3ecd0Sotto kbp->kb_last = (caddr_t)freep; 188bad3ecd0Sotto } 189bad3ecd0Sotto va = kbp->kb_next; 190bad3ecd0Sotto kbp->kb_next = ((struct freelist *)va)->next; 191bad3ecd0Sotto#ifdef DIAGNOSTIC 192bad3ecd0Sotto freep = (struct freelist *)va; 193bad3ecd0Sotto savedtype = (unsigned)freep->type < M_LAST ? 194bad3ecd0Sotto memname[freep->type] : "???"; 195bad3ecd0Sotto if (kbp->kb_next && 196bad3ecd0Sotto !kernacc(kbp->kb_next, sizeof(struct freelist), 0)) { 197bad3ecd0Sotto printf("%s %d of object %p size %d %s %s (invalid addr %p)\n", 198bad3ecd0Sotto "Data modified on freelist: word", 199bad3ecd0Sotto (int32_t *)&kbp->kb_next - (int32_t *)kbp, va, size, 200bad3ecd0Sotto "previous type", savedtype, kbp->kb_next); 201bad3ecd0Sotto kbp->kb_next = NULL; 202bad3ecd0Sotto } 203bad3ecd0Sotto 204bad3ecd0Sotto /* Fill the fields that we've used with WEIRD_ADDR */ 205bad3ecd0Sotto#if BYTE_ORDER == BIG_ENDIAN 206bad3ecd0Sotto freep->type = WEIRD_ADDR >> 16; 207bad3ecd0Sotto#endif 208bad3ecd0Sotto#if BYTE_ORDER == LITTLE_ENDIAN 209bad3ecd0Sotto freep->type = (short)WEIRD_ADDR; 210bad3ecd0Sotto#endif 211bad3ecd0Sotto end = (int32_t *)&freep->next + 212bad3ecd0Sotto (sizeof(freep->next) / sizeof(int32_t)); 213bad3ecd0Sotto for (lp = (int32_t *)&freep->next; lp < end; lp++) 214bad3ecd0Sotto *lp = WEIRD_ADDR; 215bad3ecd0Sotto 216bad3ecd0Sotto /* and check that the data hasn't been modified. */ 217bad3ecd0Sotto end = (int32_t *)&va[copysize]; 218bad3ecd0Sotto for (lp = (int32_t *)va; lp < end; lp++) { 219bad3ecd0Sotto if (*lp == WEIRD_ADDR) 220bad3ecd0Sotto continue; 221bad3ecd0Sotto printf("%s %d of object %p size %d %s %s (%p != %p)\n", 222bad3ecd0Sotto "Data modified on freelist: word", lp - (int32_t *)va, 223bad3ecd0Sotto va, size, "previous type", savedtype, *lp, WEIRD_ADDR); 224bad3ecd0Sotto break; 225bad3ecd0Sotto } 226bad3ecd0Sotto 227bad3ecd0Sotto freep->spare0 = 0; 228bad3ecd0Sotto#endif /* DIAGNOSTIC */ 229bad3ecd0Sotto#ifdef KMEMSTATS 230bad3ecd0Sotto kup = btokup(va); 231bad3ecd0Sotto if (kup->ku_indx != indx) 232bad3ecd0Sotto panic("malloc: wrong bucket"); 233bad3ecd0Sotto if (kup->ku_freecnt == 0) 234bad3ecd0Sotto panic("malloc: lost data"); 235bad3ecd0Sotto kup->ku_freecnt--; 236bad3ecd0Sotto kbp->kb_totalfree--; 237bad3ecd0Sotto ksp->ks_memuse += 1 << indx; 238bad3ecd0Sottoout: 239bad3ecd0Sotto kbp->kb_calls++; 240bad3ecd0Sotto ksp->ks_inuse++; 241bad3ecd0Sotto ksp->ks_calls++; 242bad3ecd0Sotto if (ksp->ks_memuse > ksp->ks_maxused) 243bad3ecd0Sotto ksp->ks_maxused = ksp->ks_memuse; 244bad3ecd0Sotto#else 245bad3ecd0Sottoout: 246bad3ecd0Sotto#endif 247bad3ecd0Sotto splx(s); 248bad3ecd0Sotto return ((void *) va); 249bad3ecd0Sotto} 250bad3ecd0Sotto 251bad3ecd0Sotto/* 252bad3ecd0Sotto * Free a block of memory allocated by malloc. 253bad3ecd0Sotto */ 254bad3ecd0Sottovoid 255bad3ecd0Sottofree(addr, type) 256bad3ecd0Sotto void *addr; 257bad3ecd0Sotto int type; 258bad3ecd0Sotto{ 259bad3ecd0Sotto register struct kmembuckets *kbp; 260bad3ecd0Sotto register struct kmemusage *kup; 261bad3ecd0Sotto register struct freelist *freep; 262bad3ecd0Sotto long size; 263bad3ecd0Sotto int s; 264bad3ecd0Sotto#ifdef DIAGNOSTIC 265bad3ecd0Sotto caddr_t cp; 266bad3ecd0Sotto int32_t *end, *lp; 267bad3ecd0Sotto long alloc, copysize; 268bad3ecd0Sotto#endif 269bad3ecd0Sotto#ifdef KMEMSTATS 270bad3ecd0Sotto register struct kmemstats *ksp = &kmemstats[type]; 271bad3ecd0Sotto#endif 272bad3ecd0Sotto 273bad3ecd0Sotto kup = btokup(addr); 274bad3ecd0Sotto size = 1 << kup->ku_indx; 275bad3ecd0Sotto kbp = &bucket[kup->ku_indx]; 276bad3ecd0Sotto s = splimp(); 277bad3ecd0Sotto#ifdef DIAGNOSTIC 278bad3ecd0Sotto /* 279bad3ecd0Sotto * Check for returns of data that do not point to the 280bad3ecd0Sotto * beginning of the allocation. 281bad3ecd0Sotto */ 282bad3ecd0Sotto if (size > NBPG * CLSIZE) 283bad3ecd0Sotto alloc = addrmask[BUCKETINDX(NBPG * CLSIZE)]; 284bad3ecd0Sotto else 285bad3ecd0Sotto alloc = addrmask[kup->ku_indx]; 286bad3ecd0Sotto if (((u_long)addr & alloc) != 0) 287bad3ecd0Sotto panic("free: unaligned addr 0x%x, size %d, type %s, mask %d\n", 288bad3ecd0Sotto addr, size, memname[type], alloc); 289bad3ecd0Sotto#endif /* DIAGNOSTIC */ 290bad3ecd0Sotto if (size > MAXALLOCSAVE) { 291bad3ecd0Sotto kmem_free(kmem_map, (vm_offset_t)addr, ctob(kup->ku_pagecnt)); 292bad3ecd0Sotto#ifdef KMEMSTATS 293bad3ecd0Sotto size = kup->ku_pagecnt << PGSHIFT; 294bad3ecd0Sotto ksp->ks_memuse -= size; 295bad3ecd0Sotto kup->ku_indx = 0; 296bad3ecd0Sotto kup->ku_pagecnt = 0; 297bad3ecd0Sotto if (ksp->ks_memuse + size >= ksp->ks_limit && 298bad3ecd0Sotto ksp->ks_memuse < ksp->ks_limit) 299bad3ecd0Sotto wakeup((caddr_t)ksp); 300bad3ecd0Sotto ksp->ks_inuse--; 301bad3ecd0Sotto kbp->kb_total -= 1; 302bad3ecd0Sotto#endif 303bad3ecd0Sotto splx(s); 304bad3ecd0Sotto return; 305bad3ecd0Sotto } 306bad3ecd0Sotto freep = (struct freelist *)addr; 307bad3ecd0Sotto#ifdef DIAGNOSTIC 308bad3ecd0Sotto /* 309bad3ecd0Sotto * Check for multiple frees. Use a quick check to see if 310bad3ecd0Sotto * it looks free before laboriously searching the freelist. 311bad3ecd0Sotto */ 312bad3ecd0Sotto if (freep->spare0 == WEIRD_ADDR) { 313bad3ecd0Sotto for (cp = kbp->kb_next; cp; cp = *(caddr_t *)cp) { 314bad3ecd0Sotto if (addr != cp) 315bad3ecd0Sotto continue; 316bad3ecd0Sotto printf("multiply freed item %p\n", addr); 317bad3ecd0Sotto panic("free: duplicated free"); 318bad3ecd0Sotto } 319bad3ecd0Sotto } 320bad3ecd0Sotto /* 321bad3ecd0Sotto * Copy in known text to detect modification after freeing 322bad3ecd0Sotto * and to make it look free. Also, save the type being freed 323bad3ecd0Sotto * so we can list likely culprit if modification is detected 324bad3ecd0Sotto * when the object is reallocated. 325bad3ecd0Sotto */ 326bad3ecd0Sotto copysize = size < MAX_COPY ? size : MAX_COPY; 327bad3ecd0Sotto end = (int32_t *)&((caddr_t)addr)[copysize]; 328bad3ecd0Sotto for (lp = (int32_t *)addr; lp < end; lp++) 329bad3ecd0Sotto *lp = WEIRD_ADDR; 330bad3ecd0Sotto freep->type = type; 331bad3ecd0Sotto#endif /* DIAGNOSTIC */ 332bad3ecd0Sotto#ifdef KMEMSTATS 333bad3ecd0Sotto kup->ku_freecnt++; 334bad3ecd0Sotto if (kup->ku_freecnt >= kbp->kb_elmpercl) 335bad3ecd0Sotto if (kup->ku_freecnt > kbp->kb_elmpercl) 336bad3ecd0Sotto panic("free: multiple frees"); 337bad3ecd0Sotto else if (kbp->kb_totalfree > kbp->kb_highwat) 338bad3ecd0Sotto kbp->kb_couldfree++; 339bad3ecd0Sotto kbp->kb_totalfree++; 340bad3ecd0Sotto ksp->ks_memuse -= size; 341bad3ecd0Sotto if (ksp->ks_memuse + size >= ksp->ks_limit && 342bad3ecd0Sotto ksp->ks_memuse < ksp->ks_limit) 343bad3ecd0Sotto wakeup((caddr_t)ksp); 344bad3ecd0Sotto ksp->ks_inuse--; 345bad3ecd0Sotto#endif 346bad3ecd0Sotto if (kbp->kb_next == NULL) 347bad3ecd0Sotto kbp->kb_next = addr; 348bad3ecd0Sotto else 349bad3ecd0Sotto ((struct freelist *)kbp->kb_last)->next = addr; 350bad3ecd0Sotto freep->next = NULL; 351bad3ecd0Sotto kbp->kb_last = addr; 352bad3ecd0Sotto splx(s); 353bad3ecd0Sotto} 354bad3ecd0Sotto 355bad3ecd0Sotto/* 356bad3ecd0Sotto * Initialize the kernel memory allocator 357bad3ecd0Sotto */ 358bad3ecd0Sottokmeminit() 359bad3ecd0Sotto{ 360bad3ecd0Sotto register long indx; 361bad3ecd0Sotto int npg; 362bad3ecd0Sotto 363bad3ecd0Sotto#if ((MAXALLOCSAVE & (MAXALLOCSAVE - 1)) != 0) 364bad3ecd0Sotto ERROR!_kmeminit:_MAXALLOCSAVE_not_power_of_2 365bad3ecd0Sotto#endif 366bad3ecd0Sotto#if (MAXALLOCSAVE > MINALLOCSIZE * 32768) 367bad3ecd0Sotto ERROR!_kmeminit:_MAXALLOCSAVE_too_big 368bad3ecd0Sotto#endif 369bad3ecd0Sotto#if (MAXALLOCSAVE < CLBYTES) 370bad3ecd0Sotto ERROR!_kmeminit:_MAXALLOCSAVE_too_small 371bad3ecd0Sotto#endif 372bad3ecd0Sotto 373bad3ecd0Sotto if (sizeof(struct freelist) > (1 << MINBUCKET)) 374bad3ecd0Sotto panic("minbucket too small/struct freelist too big"); 375bad3ecd0Sotto 376bad3ecd0Sotto npg = VM_KMEM_SIZE/ NBPG; 377bad3ecd0Sotto kmemusage = (struct kmemusage *) kmem_alloc(kernel_map, 378bad3ecd0Sotto (vm_size_t)(npg * sizeof(struct kmemusage))); 379bad3ecd0Sotto kmem_map = kmem_suballoc(kernel_map, (vm_offset_t *)&kmembase, 380bad3ecd0Sotto (vm_offset_t *)&kmemlimit, (vm_size_t)(npg * NBPG), FALSE); 381bad3ecd0Sotto#ifdef KMEMSTATS 382bad3ecd0Sotto for (indx = 0; indx < MINBUCKET + 16; indx++) { 383bad3ecd0Sotto if (1 << indx >= CLBYTES) 384bad3ecd0Sotto bucket[indx].kb_elmpercl = 1; 385bad3ecd0Sotto else 386bad3ecd0Sotto bucket[indx].kb_elmpercl = CLBYTES / (1 << indx); 387bad3ecd0Sotto bucket[indx].kb_highwat = 5 * bucket[indx].kb_elmpercl; 388bad3ecd0Sotto } 389bad3ecd0Sotto for (indx = 0; indx < M_LAST; indx++) 390bad3ecd0Sotto kmemstats[indx].ks_limit = npg * NBPG * 6 / 10; 391bad3ecd0Sotto#endif 392bad3ecd0Sotto} 393