|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1987, 1991 The Regents of the University of California. ! 3: * 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 7.25 (Berkeley) 5/8/91 ! 34: */ ! 35: ! 36: #include "param.h" ! 37: #include "proc.h" ! 38: #include "map.h" ! 39: #include "kernel.h" ! 40: #include "malloc.h" ! 41: #include "vm/vm.h" ! 42: #include "vm/vm_kern.h" ! 43: ! 44: struct kmembuckets bucket[MINBUCKET + 16]; ! 45: struct kmemstats kmemstats[M_LAST]; ! 46: struct kmemusage *kmemusage; ! 47: char *kmembase, *kmemlimit; ! 48: char *memname[] = INITKMEMNAMES; ! 49: ! 50: /* ! 51: * Allocate a block of memory ! 52: */ ! 53: void * ! 54: malloc(size, type, flags) ! 55: unsigned long size; ! 56: int type, flags; ! 57: { ! 58: register struct kmembuckets *kbp; ! 59: register struct kmemusage *kup; ! 60: long indx, npg, alloc, allocsize; ! 61: int s; ! 62: caddr_t va, cp, savedlist; ! 63: #ifdef KMEMSTATS ! 64: register struct kmemstats *ksp = &kmemstats[type]; ! 65: ! 66: if (((unsigned long)type) > M_LAST) ! 67: panic("malloc - bogus type"); ! 68: #endif ! 69: ! 70: indx = BUCKETINDX(size); ! 71: kbp = &bucket[indx]; ! 72: s = splimp(); ! 73: #ifdef KMEMSTATS ! 74: while (ksp->ks_memuse >= ksp->ks_limit) { ! 75: if (flags & M_NOWAIT) { ! 76: splx(s); ! 77: return ((void *) NULL); ! 78: } ! 79: if (ksp->ks_limblocks < 65535) ! 80: ksp->ks_limblocks++; ! 81: tsleep((caddr_t)ksp, PSWP+2, memname[type], 0); ! 82: } ! 83: #endif ! 84: if (kbp->kb_next == NULL) { ! 85: if (size > MAXALLOCSAVE) ! 86: allocsize = roundup(size, CLBYTES); ! 87: else ! 88: allocsize = 1 << indx; ! 89: npg = clrnd(btoc(allocsize)); ! 90: va = (caddr_t) kmem_malloc(kmem_map, (vm_size_t)ctob(npg), ! 91: !(flags & M_NOWAIT)); ! 92: if (va == NULL) { ! 93: splx(s); ! 94: return ((void *) NULL); ! 95: } ! 96: #ifdef KMEMSTATS ! 97: kbp->kb_total += kbp->kb_elmpercl; ! 98: #endif ! 99: kup = btokup(va); ! 100: kup->ku_indx = indx; ! 101: if (allocsize > MAXALLOCSAVE) { ! 102: if (npg > 65535) ! 103: panic("malloc: allocation too large"); ! 104: kup->ku_pagecnt = npg; ! 105: #ifdef KMEMSTATS ! 106: ksp->ks_memuse += allocsize; ! 107: #endif ! 108: goto out; ! 109: } ! 110: #ifdef KMEMSTATS ! 111: kup->ku_freecnt = kbp->kb_elmpercl; ! 112: kbp->kb_totalfree += kbp->kb_elmpercl; ! 113: #endif ! 114: /* ! 115: * Just in case we blocked while allocating memory, ! 116: * and someone else also allocated memory for this ! 117: * bucket, don't assume the list is still empty. ! 118: */ ! 119: savedlist = kbp->kb_next; ! 120: kbp->kb_next = va + (npg * NBPG) - allocsize; ! 121: for (cp = kbp->kb_next; cp > va; cp -= allocsize) ! 122: *(caddr_t *)cp = cp - allocsize; ! 123: *(caddr_t *)cp = savedlist; ! 124: } ! 125: va = kbp->kb_next; ! 126: kbp->kb_next = *(caddr_t *)va; ! 127: #ifdef KMEMSTATS ! 128: kup = btokup(va); ! 129: if (kup->ku_indx != indx) ! 130: panic("malloc: wrong bucket"); ! 131: if (kup->ku_freecnt == 0) ! 132: panic("malloc: lost data"); ! 133: kup->ku_freecnt--; ! 134: kbp->kb_totalfree--; ! 135: ksp->ks_memuse += 1 << indx; ! 136: out: ! 137: kbp->kb_calls++; ! 138: ksp->ks_inuse++; ! 139: ksp->ks_calls++; ! 140: if (ksp->ks_memuse > ksp->ks_maxused) ! 141: ksp->ks_maxused = ksp->ks_memuse; ! 142: #else ! 143: out: ! 144: #endif ! 145: splx(s); ! 146: return ((void *) va); ! 147: } ! 148: ! 149: #ifdef DIAGNOSTIC ! 150: long addrmask[] = { 0x00000000, ! 151: 0x00000001, 0x00000003, 0x00000007, 0x0000000f, ! 152: 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, ! 153: 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, ! 154: 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff, ! 155: }; ! 156: #endif /* DIAGNOSTIC */ ! 157: ! 158: /* ! 159: * Free a block of memory allocated by malloc. ! 160: */ ! 161: void ! 162: free(addr, type) ! 163: void *addr; ! 164: int type; ! 165: { ! 166: register struct kmembuckets *kbp; ! 167: register struct kmemusage *kup; ! 168: long alloc, size; ! 169: int s; ! 170: #ifdef KMEMSTATS ! 171: register struct kmemstats *ksp = &kmemstats[type]; ! 172: #endif ! 173: ! 174: kup = btokup(addr); ! 175: size = 1 << kup->ku_indx; ! 176: #ifdef DIAGNOSTIC ! 177: if (size > NBPG * CLSIZE) ! 178: alloc = addrmask[BUCKETINDX(NBPG * CLSIZE)]; ! 179: else ! 180: alloc = addrmask[kup->ku_indx]; ! 181: if (((u_long)addr & alloc) != 0) { ! 182: printf("free: unaligned addr 0x%x, size %d, type %d, mask %d\n", ! 183: addr, size, type, alloc); ! 184: panic("free: unaligned addr"); ! 185: } ! 186: #endif /* DIAGNOSTIC */ ! 187: kbp = &bucket[kup->ku_indx]; ! 188: s = splimp(); ! 189: if (size > MAXALLOCSAVE) { ! 190: kmem_free(kmem_map, (vm_offset_t)addr, ctob(kup->ku_pagecnt)); ! 191: #ifdef KMEMSTATS ! 192: size = kup->ku_pagecnt << PGSHIFT; ! 193: ksp->ks_memuse -= size; ! 194: kup->ku_indx = 0; ! 195: kup->ku_pagecnt = 0; ! 196: if (ksp->ks_memuse + size >= ksp->ks_limit && ! 197: ksp->ks_memuse < ksp->ks_limit) ! 198: wakeup((caddr_t)ksp); ! 199: ksp->ks_inuse--; ! 200: kbp->kb_total -= 1; ! 201: #endif ! 202: splx(s); ! 203: return; ! 204: } ! 205: #ifdef KMEMSTATS ! 206: kup->ku_freecnt++; ! 207: if (kup->ku_freecnt >= kbp->kb_elmpercl) ! 208: if (kup->ku_freecnt > kbp->kb_elmpercl) ! 209: panic("free: multiple frees"); ! 210: else if (kbp->kb_totalfree > kbp->kb_highwat) ! 211: kbp->kb_couldfree++; ! 212: kbp->kb_totalfree++; ! 213: ksp->ks_memuse -= size; ! 214: if (ksp->ks_memuse + size >= ksp->ks_limit && ! 215: ksp->ks_memuse < ksp->ks_limit) ! 216: wakeup((caddr_t)ksp); ! 217: ksp->ks_inuse--; ! 218: #endif ! 219: *(caddr_t *)addr = kbp->kb_next; ! 220: kbp->kb_next = addr; ! 221: splx(s); ! 222: } ! 223: ! 224: /* ! 225: * Initialize the kernel memory allocator ! 226: */ ! 227: kmeminit() ! 228: { ! 229: register long indx; ! 230: int npg; ! 231: ! 232: #if ((MAXALLOCSAVE & (MAXALLOCSAVE - 1)) != 0) ! 233: ERROR!_kmeminit:_MAXALLOCSAVE_not_power_of_2 ! 234: #endif ! 235: #if (MAXALLOCSAVE > MINALLOCSIZE * 32768) ! 236: ERROR!_kmeminit:_MAXALLOCSAVE_too_big ! 237: #endif ! 238: #if (MAXALLOCSAVE < CLBYTES) ! 239: ERROR!_kmeminit:_MAXALLOCSAVE_too_small ! 240: #endif ! 241: npg = VM_KMEM_SIZE/ NBPG; ! 242: kmemusage = (struct kmemusage *) kmem_alloc(kernel_map, ! 243: (vm_size_t)(npg * sizeof(struct kmemusage))); ! 244: kmem_map = kmem_suballoc(kernel_map, (vm_offset_t)&kmembase, ! 245: (vm_offset_t)&kmemlimit, (vm_size_t)(npg * NBPG), FALSE); ! 246: #ifdef KMEMSTATS ! 247: for (indx = 0; indx < MINBUCKET + 16; indx++) { ! 248: if (1 << indx >= CLBYTES) ! 249: bucket[indx].kb_elmpercl = 1; ! 250: else ! 251: bucket[indx].kb_elmpercl = CLBYTES / (1 << indx); ! 252: bucket[indx].kb_highwat = 5 * bucket[indx].kb_elmpercl; ! 253: } ! 254: for (indx = 0; indx < M_LAST; indx++) ! 255: kmemstats[indx].ks_limit = npg * NBPG * 6 / 10; ! 256: #endif ! 257: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.