|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1987 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution is only permitted until one year after the first shipment ! 6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 7: * binary forms are permitted provided that: (1) source distributions retain ! 8: * this entire copyright notice and comment, and (2) distributions including ! 9: * binaries display the following acknowledgement: This product includes ! 10: * software developed by the University of California, Berkeley and its ! 11: * contributors'' in the documentation or other materials provided with the ! 12: * distribution and in all advertising materials mentioning features or use ! 13: * of this software. Neither the name of the University nor the names of ! 14: * its contributors may be used to endorse or promote products derived from ! 15: * this software without specific prior written permission. ! 16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 19: * ! 20: * @(#)kern_malloc.c 7.19 (Berkeley) 7/27/90 ! 21: */ ! 22: ! 23: #include "param.h" ! 24: #include "vm.h" ! 25: #include "cmap.h" ! 26: #include "time.h" ! 27: #include "proc.h" ! 28: #include "map.h" ! 29: #include "kernel.h" ! 30: #include "malloc.h" ! 31: ! 32: #include "machine/pte.h" ! 33: ! 34: struct kmembuckets bucket[MINBUCKET + 16]; ! 35: struct kmemstats kmemstats[M_LAST]; ! 36: struct kmemusage *kmemusage; ! 37: long wantkmemmap; ! 38: ! 39: /* ! 40: * Allocate a block of memory ! 41: */ ! 42: qaddr_t ! 43: malloc(size, type, flags) ! 44: unsigned long size; ! 45: int type, flags; ! 46: { ! 47: register struct kmembuckets *kbp; ! 48: register struct kmemusage *kup; ! 49: long indx, npg, alloc, allocsize; ! 50: int s; ! 51: caddr_t va, cp; ! 52: #ifdef KMEMSTATS ! 53: register struct kmemstats *ksp = &kmemstats[type]; ! 54: ! 55: if (((unsigned long)type) > M_LAST) ! 56: panic("malloc - bogus type"); ! 57: #endif ! 58: ! 59: indx = BUCKETINDX(size); ! 60: kbp = &bucket[indx]; ! 61: s = splimp(); ! 62: again: ! 63: #ifdef KMEMSTATS ! 64: while (ksp->ks_memuse >= ksp->ks_limit) { ! 65: if (flags & M_NOWAIT) { ! 66: splx(s); ! 67: return (0); ! 68: } ! 69: if (ksp->ks_limblocks < 65535) ! 70: ksp->ks_limblocks++; ! 71: sleep((caddr_t)ksp, PSWP+2); ! 72: } ! 73: #endif ! 74: if (kbp->kb_next == NULL) { ! 75: if (size > MAXALLOCSAVE) ! 76: allocsize = roundup(size, CLBYTES); ! 77: else ! 78: allocsize = 1 << indx; ! 79: npg = clrnd(btoc(allocsize)); ! 80: if ((flags & M_NOWAIT) && freemem < npg) { ! 81: splx(s); ! 82: return (0); ! 83: } ! 84: alloc = rmalloc(kmemmap, npg); ! 85: if (alloc == 0) { ! 86: if (flags & M_NOWAIT) { ! 87: splx(s); ! 88: return (0); ! 89: } ! 90: #ifdef KMEMSTATS ! 91: if (ksp->ks_mapblocks < 65535) ! 92: ksp->ks_mapblocks++; ! 93: #endif ! 94: wantkmemmap++; ! 95: sleep((caddr_t)&wantkmemmap, PSWP+2); ! 96: goto again; ! 97: } ! 98: alloc -= CLSIZE; /* convert to base 0 */ ! 99: (void) vmemall(&kmempt[alloc], (int)npg, &proc[0], CSYS); ! 100: va = (caddr_t) kmemxtob(alloc); ! 101: vmaccess(&kmempt[alloc], va, (int)npg); ! 102: #ifdef KMEMSTATS ! 103: kbp->kb_total += kbp->kb_elmpercl; ! 104: #endif ! 105: kup = btokup(va); ! 106: kup->ku_indx = indx; ! 107: if (allocsize > MAXALLOCSAVE) { ! 108: if (npg > 65535) ! 109: panic("malloc: allocation too large"); ! 110: kup->ku_pagecnt = npg; ! 111: #ifdef KMEMSTATS ! 112: ksp->ks_memuse += allocsize; ! 113: #endif ! 114: goto out; ! 115: } ! 116: #ifdef KMEMSTATS ! 117: kup->ku_freecnt = kbp->kb_elmpercl; ! 118: kbp->kb_totalfree += kbp->kb_elmpercl; ! 119: #endif ! 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 = NULL; ! 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 ((qaddr_t)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: caddr_t 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: alloc = btokmemx(addr); ! 191: (void) memfree(&kmempt[alloc], (int)kup->ku_pagecnt, 1); ! 192: rmfree(kmemmap, (long)kup->ku_pagecnt, alloc + CLSIZE); ! 193: if (wantkmemmap) { ! 194: wakeup((caddr_t)&wantkmemmap); ! 195: wantkmemmap = 0; ! 196: } ! 197: #ifdef KMEMSTATS ! 198: size = kup->ku_pagecnt << PGSHIFT; ! 199: ksp->ks_memuse -= size; ! 200: kup->ku_indx = 0; ! 201: kup->ku_pagecnt = 0; ! 202: if (ksp->ks_memuse + size >= ksp->ks_limit && ! 203: ksp->ks_memuse < ksp->ks_limit) ! 204: wakeup((caddr_t)ksp); ! 205: ksp->ks_inuse--; ! 206: kbp->kb_total -= 1; ! 207: #endif ! 208: splx(s); ! 209: return; ! 210: } ! 211: #ifdef KMEMSTATS ! 212: kup->ku_freecnt++; ! 213: if (kup->ku_freecnt >= kbp->kb_elmpercl) ! 214: if (kup->ku_freecnt > kbp->kb_elmpercl) ! 215: panic("free: multiple frees"); ! 216: else if (kbp->kb_totalfree > kbp->kb_highwat) ! 217: kbp->kb_couldfree++; ! 218: kbp->kb_totalfree++; ! 219: ksp->ks_memuse -= size; ! 220: if (ksp->ks_memuse + size >= ksp->ks_limit && ! 221: ksp->ks_memuse < ksp->ks_limit) ! 222: wakeup((caddr_t)ksp); ! 223: ksp->ks_inuse--; ! 224: #endif ! 225: *(caddr_t *)addr = kbp->kb_next; ! 226: kbp->kb_next = addr; ! 227: splx(s); ! 228: } ! 229: ! 230: /* ! 231: * Initialize the kernel memory allocator ! 232: */ ! 233: kmeminit() ! 234: { ! 235: register long indx; ! 236: int npg; ! 237: ! 238: #if ((MAXALLOCSAVE & (MAXALLOCSAVE - 1)) != 0) ! 239: ERROR!_kmeminit:_MAXALLOCSAVE_not_power_of_2 ! 240: #endif ! 241: #if (MAXALLOCSAVE > MINALLOCSIZE * 32768) ! 242: ERROR!_kmeminit:_MAXALLOCSAVE_too_big ! 243: #endif ! 244: #if (MAXALLOCSAVE < CLBYTES) ! 245: ERROR!_kmeminit:_MAXALLOCSAVE_too_small ! 246: #endif ! 247: npg = ekmempt - kmempt; ! 248: rminit(kmemmap, (long)npg, (long)CLSIZE, "malloc map", npg); ! 249: #ifdef KMEMSTATS ! 250: for (indx = 0; indx < MINBUCKET + 16; indx++) { ! 251: if (1 << indx >= CLBYTES) ! 252: bucket[indx].kb_elmpercl = 1; ! 253: else ! 254: bucket[indx].kb_elmpercl = CLBYTES / (1 << indx); ! 255: bucket[indx].kb_highwat = 5 * bucket[indx].kb_elmpercl; ! 256: } ! 257: for (indx = 0; indx < M_LAST; indx++) ! 258: kmemstats[indx].ks_limit = npg * NBPG * 6 / 10; ! 259: #endif ! 260: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.