1 /* 2 * Copyright (c) 1987 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)kern_malloc.c 7.1 (Berkeley) 06/06/87 7 */ 8 9 #include "param.h" 10 #include "vm.h" 11 #include "cmap.h" 12 #include "time.h" 13 #include "proc.h" 14 #include "map.h" 15 #include "kernel.h" 16 #include "malloc.h" 17 18 #include "../machine/pte.h" 19 20 struct kmembuckets bucket[MINBUCKET + 16]; 21 struct kmemstats kmemstats[M_LAST]; 22 struct kmemusage *kmemusage; 23 24 /* 25 * Allocate a block of memory 26 */ 27 qaddr_t malloc(size, type, flags) 28 unsigned long size; 29 long type, flags; 30 { 31 register struct kmembuckets *kbp; 32 register struct kmemusage *kup; 33 long indx, npg, alloc, allocsize, s; 34 caddr_t va, cp; 35 #ifdef KMEMSTATS 36 register struct kmemstats *ksp; 37 38 ksp = &kmemstats[type]; 39 if (ksp->ks_inuse >= ksp->ks_limit) 40 return (0); 41 #endif 42 indx = BUCKETINDX(size); 43 kbp = &bucket[indx]; 44 s = splimp(); 45 if (kbp->kb_next == NULL) { 46 if (size > MAXALLOCSAVE) 47 allocsize = roundup(size, CLBYTES); 48 else 49 allocsize = 1 << indx; 50 npg = clrnd(btoc(allocsize)); 51 if ((flags & M_NOWAIT) && freemem < npg) { 52 splx(s); 53 return (0); 54 } 55 alloc = rmalloc(kmemmap, npg); 56 if (alloc == 0) { 57 splx(s); 58 return (0); 59 } 60 if (vmemall(&kmempt[alloc], npg, &proc[0], CSYS) == 0) { 61 rmfree(kmemmap, npg, alloc); 62 splx(s); 63 return (0); 64 } 65 va = (caddr_t) kmemxtob(alloc); 66 vmaccess(&kmempt[alloc], va, npg); 67 #ifdef KMEMSTATS 68 kbp->kb_total += kbp->kb_elmpercl; 69 #endif 70 kup = btokup(va); 71 kup->ku_indx = indx; 72 if (allocsize > MAXALLOCSAVE) { 73 if (npg > 65535) 74 panic("malloc: allocation too large"); 75 kup->ku_pagecnt = npg; 76 goto out; 77 } 78 #ifdef KMEMSTATS 79 kup->ku_freecnt = kbp->kb_elmpercl; 80 kbp->kb_totalfree += kbp->kb_elmpercl; 81 #endif 82 kbp->kb_next = va + (npg * NBPG) - allocsize; 83 for(cp = kbp->kb_next; cp > va; cp -= allocsize) 84 *(caddr_t *)cp = cp - allocsize; 85 *(caddr_t *)cp = NULL; 86 } 87 va = kbp->kb_next; 88 kbp->kb_next = *(caddr_t *)va; 89 #ifdef KMEMSTATS 90 kup = btokup(va); 91 if (kup->ku_indx != indx) 92 panic("malloc: wrong bucket"); 93 if (kup->ku_freecnt == 0) 94 panic("malloc: lost data"); 95 kup->ku_freecnt--; 96 kbp->kb_totalfree--; 97 out: 98 kbp->kb_calls++; 99 ksp->ks_inuse++; 100 ksp->ks_calls++; 101 if (ksp->ks_inuse > ksp->ks_maxused) 102 ksp->ks_maxused = ksp->ks_inuse; 103 #else 104 out: 105 #endif 106 splx(s); 107 return ((qaddr_t)va); 108 } 109 110 /* 111 * Free a block of memory allocated by malloc. 112 */ 113 void free(addr, type) 114 caddr_t addr; 115 long type; 116 { 117 register struct kmembuckets *kbp; 118 register struct kmemusage *kup; 119 long alloc, s; 120 121 kup = btokup(addr); 122 s = splimp(); 123 if (1 << kup->ku_indx > MAXALLOCSAVE) { 124 alloc = btokmemx(addr); 125 (void) memfree(&kmempt[alloc], kup->ku_pagecnt, 0); 126 rmfree(kmemmap, (long)kup->ku_pagecnt, alloc); 127 #ifdef KMEMSTATS 128 kup->ku_indx = 0; 129 kup->ku_pagecnt = 0; 130 kbp->kb_total -= kbp->kb_elmpercl; 131 kmemstats[type].ks_inuse--; 132 #endif 133 splx(s); 134 return; 135 } 136 kbp = &bucket[kup->ku_indx]; 137 #ifdef KMEMSTATS 138 kup->ku_freecnt++; 139 if (kup->ku_freecnt >= kbp->kb_elmpercl) 140 if (kup->ku_freecnt > kbp->kb_elmpercl) 141 panic("free: multiple frees"); 142 else if (kbp->kb_totalfree > kbp->kb_highwat) 143 kbp->kb_couldfree++; 144 kbp->kb_totalfree++; 145 kmemstats[type].ks_inuse--; 146 #endif 147 *(caddr_t *)addr = kbp->kb_next; 148 kbp->kb_next = addr; 149 splx(s); 150 } 151 152 /* 153 * Initialize the kernel memory allocator 154 */ 155 kmeminit() 156 { 157 register long indx; 158 159 if (!powerof2(MAXALLOCSAVE)) 160 panic("kmeminit: MAXALLOCSAVE not power of 2"); 161 if (MAXALLOCSAVE > MINALLOCSIZE * 32768) 162 panic("kmeminit: MAXALLOCSAVE too big"); 163 if (MAXALLOCSAVE < CLBYTES) 164 panic("kmeminit: MAXALLOCSAVE too small"); 165 rminit(kmemmap, ekmempt - kmempt, (long)1, 166 "malloc map", ekmempt - kmempt); 167 #ifdef KMEMSTATS 168 for (indx = 0; indx < MINBUCKET + 16; indx++) { 169 if (1 << indx >= CLBYTES) 170 bucket[indx].kb_elmpercl = 1; 171 else 172 bucket[indx].kb_elmpercl = CLBYTES / (1 << indx); 173 bucket[indx].kb_highwat = 5 * bucket[indx].kb_elmpercl; 174 } 175 for (indx = 0; indx < M_LAST; indx++) 176 kmemstats[indx].ks_limit = 0x7fffffff; 177 #endif 178 } 179