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.2 (Berkeley) 06/22/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 kmemstats[type].ks_inuse--; 131 #endif 132 splx(s); 133 return; 134 } 135 kbp = &bucket[kup->ku_indx]; 136 #ifdef KMEMSTATS 137 kup->ku_freecnt++; 138 if (kup->ku_freecnt >= kbp->kb_elmpercl) 139 if (kup->ku_freecnt > kbp->kb_elmpercl) 140 panic("free: multiple frees"); 141 else if (kbp->kb_totalfree > kbp->kb_highwat) 142 kbp->kb_couldfree++; 143 kbp->kb_totalfree++; 144 kmemstats[type].ks_inuse--; 145 #endif 146 *(caddr_t *)addr = kbp->kb_next; 147 kbp->kb_next = addr; 148 splx(s); 149 } 150 151 /* 152 * Initialize the kernel memory allocator 153 */ 154 kmeminit() 155 { 156 register long indx; 157 158 if (!powerof2(MAXALLOCSAVE)) 159 panic("kmeminit: MAXALLOCSAVE not power of 2"); 160 if (MAXALLOCSAVE > MINALLOCSIZE * 32768) 161 panic("kmeminit: MAXALLOCSAVE too big"); 162 if (MAXALLOCSAVE < CLBYTES) 163 panic("kmeminit: MAXALLOCSAVE too small"); 164 rminit(kmemmap, ekmempt - kmempt, (long)1, 165 "malloc map", ekmempt - kmempt); 166 #ifdef KMEMSTATS 167 for (indx = 0; indx < MINBUCKET + 16; indx++) { 168 if (1 << indx >= CLBYTES) 169 bucket[indx].kb_elmpercl = 1; 170 else 171 bucket[indx].kb_elmpercl = CLBYTES / (1 << indx); 172 bucket[indx].kb_highwat = 5 * bucket[indx].kb_elmpercl; 173 } 174 for (indx = 0; indx < M_LAST; indx++) 175 kmemstats[indx].ks_limit = 0x7fffffff; 176 #endif 177 } 178