2.10BSD long/int fix
[unix-history] / usr / src / sys / kern / kern_malloc.c
CommitLineData
d4202556
KM
1/*
2 * Copyright (c) 1987 Regents of the University of California.
2420c94a 3 * All rights reserved.
d4202556 4 *
2420c94a
KM
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to the University of California at Berkeley. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
11 *
738ba0d6 12 * @(#)kern_malloc.c 7.7 (Berkeley) %G%
d4202556
KM
13 */
14
15#include "param.h"
16#include "vm.h"
17#include "cmap.h"
18#include "time.h"
19#include "proc.h"
20#include "map.h"
21#include "kernel.h"
22#include "malloc.h"
23
24#include "../machine/pte.h"
25
26struct kmembuckets bucket[MINBUCKET + 16];
27struct kmemstats kmemstats[M_LAST];
28struct kmemusage *kmemusage;
fd78e9f6 29long wantkmemmap;
d4202556
KM
30
31/*
32 * Allocate a block of memory
33 */
738ba0d6
KM
34qaddr_t
35malloc(size, type, flags)
d4202556
KM
36 unsigned long size;
37 long type, flags;
38{
39 register struct kmembuckets *kbp;
40 register struct kmemusage *kup;
41 long indx, npg, alloc, allocsize, s;
42 caddr_t va, cp;
43#ifdef KMEMSTATS
fd78e9f6 44 register struct kmemstats *ksp = &kmemstats[type];
d4202556 45#endif
fd78e9f6 46
d4202556
KM
47 indx = BUCKETINDX(size);
48 kbp = &bucket[indx];
49 s = splimp();
fd78e9f6
KM
50again:
51#ifdef KMEMSTATS
52 while (ksp->ks_inuse >= ksp->ks_limit) {
53 if (flags & M_NOWAIT) {
54 splx(s);
55 return (0);
56 }
57 if (ksp->ks_limblocks < 65535)
58 ksp->ks_limblocks++;
59 sleep((caddr_t)ksp, PSWP+2);
60 }
61#endif
d4202556
KM
62 if (kbp->kb_next == NULL) {
63 if (size > MAXALLOCSAVE)
64 allocsize = roundup(size, CLBYTES);
65 else
66 allocsize = 1 << indx;
67 npg = clrnd(btoc(allocsize));
68 if ((flags & M_NOWAIT) && freemem < npg) {
69 splx(s);
70 return (0);
71 }
72 alloc = rmalloc(kmemmap, npg);
73 if (alloc == 0) {
fd78e9f6
KM
74 if (flags & M_NOWAIT) {
75 splx(s);
76 return (0);
77 }
78#ifdef KMEMSTATS
79 if (ksp->ks_mapblocks < 65535)
80 ksp->ks_mapblocks++;
81#endif
82 wantkmemmap++;
83 sleep((caddr_t)&wantkmemmap, PSWP+2);
84 goto again;
d4202556 85 }
7656fce5 86 alloc -= CLSIZE; /* convert to base 0 */
fd78e9f6 87 (void) vmemall(&kmempt[alloc], npg, &proc[0], CSYS);
d4202556
KM
88 va = (caddr_t) kmemxtob(alloc);
89 vmaccess(&kmempt[alloc], va, npg);
90#ifdef KMEMSTATS
91 kbp->kb_total += kbp->kb_elmpercl;
92#endif
93 kup = btokup(va);
94 kup->ku_indx = indx;
95 if (allocsize > MAXALLOCSAVE) {
96 if (npg > 65535)
97 panic("malloc: allocation too large");
98 kup->ku_pagecnt = npg;
fd78e9f6
KM
99#ifdef KMEMSTATS
100 ksp->ks_memuse += allocsize;
101#endif
d4202556
KM
102 goto out;
103 }
104#ifdef KMEMSTATS
105 kup->ku_freecnt = kbp->kb_elmpercl;
106 kbp->kb_totalfree += kbp->kb_elmpercl;
107#endif
108 kbp->kb_next = va + (npg * NBPG) - allocsize;
fd78e9f6 109 for (cp = kbp->kb_next; cp > va; cp -= allocsize)
d4202556
KM
110 *(caddr_t *)cp = cp - allocsize;
111 *(caddr_t *)cp = NULL;
112 }
113 va = kbp->kb_next;
114 kbp->kb_next = *(caddr_t *)va;
115#ifdef KMEMSTATS
116 kup = btokup(va);
117 if (kup->ku_indx != indx)
118 panic("malloc: wrong bucket");
119 if (kup->ku_freecnt == 0)
120 panic("malloc: lost data");
121 kup->ku_freecnt--;
122 kbp->kb_totalfree--;
fd78e9f6 123 ksp->ks_memuse += 1 << indx;
d4202556
KM
124out:
125 kbp->kb_calls++;
126 ksp->ks_inuse++;
127 ksp->ks_calls++;
128 if (ksp->ks_inuse > ksp->ks_maxused)
129 ksp->ks_maxused = ksp->ks_inuse;
130#else
131out:
132#endif
133 splx(s);
134 return ((qaddr_t)va);
135}
136
137/*
138 * Free a block of memory allocated by malloc.
139 */
738ba0d6
KM
140void
141free(addr, type)
d4202556
KM
142 caddr_t addr;
143 long type;
144{
145 register struct kmembuckets *kbp;
146 register struct kmemusage *kup;
147 long alloc, s;
fd78e9f6
KM
148#ifdef KMEMSTATS
149 register struct kmemstats *ksp = &kmemstats[type];
150#endif
d4202556
KM
151
152 kup = btokup(addr);
738ba0d6 153 kbp = &bucket[kup->ku_indx];
d4202556
KM
154 s = splimp();
155 if (1 << kup->ku_indx > MAXALLOCSAVE) {
156 alloc = btokmemx(addr);
157 (void) memfree(&kmempt[alloc], kup->ku_pagecnt, 0);
fd78e9f6
KM
158 rmfree(kmemmap, (long)kup->ku_pagecnt, alloc + CLSIZE);
159 if (wantkmemmap) {
160 wakeup((caddr_t)&wantkmemmap);
161 wantkmemmap = 0;
162 }
d4202556 163#ifdef KMEMSTATS
fd78e9f6 164 ksp->ks_memuse -= kup->ku_pagecnt << PGSHIFT;
d4202556
KM
165 kup->ku_indx = 0;
166 kup->ku_pagecnt = 0;
fd78e9f6
KM
167 if (ksp->ks_inuse == ksp->ks_limit)
168 wakeup((caddr_t)ksp);
169 ksp->ks_inuse--;
738ba0d6 170 kbp->kb_total -= 1;
d4202556
KM
171#endif
172 splx(s);
173 return;
174 }
d4202556
KM
175#ifdef KMEMSTATS
176 kup->ku_freecnt++;
177 if (kup->ku_freecnt >= kbp->kb_elmpercl)
178 if (kup->ku_freecnt > kbp->kb_elmpercl)
179 panic("free: multiple frees");
180 else if (kbp->kb_totalfree > kbp->kb_highwat)
181 kbp->kb_couldfree++;
182 kbp->kb_totalfree++;
fd78e9f6
KM
183 if (ksp->ks_inuse == ksp->ks_limit)
184 wakeup((caddr_t)ksp);
185 ksp->ks_inuse--;
186 ksp->ks_memuse -= 1 << kup->ku_indx;
d4202556
KM
187#endif
188 *(caddr_t *)addr = kbp->kb_next;
189 kbp->kb_next = addr;
190 splx(s);
191}
192
193/*
194 * Initialize the kernel memory allocator
195 */
196kmeminit()
197{
198 register long indx;
738ba0d6 199 int npg;
d4202556
KM
200
201 if (!powerof2(MAXALLOCSAVE))
202 panic("kmeminit: MAXALLOCSAVE not power of 2");
203 if (MAXALLOCSAVE > MINALLOCSIZE * 32768)
204 panic("kmeminit: MAXALLOCSAVE too big");
205 if (MAXALLOCSAVE < CLBYTES)
206 panic("kmeminit: MAXALLOCSAVE too small");
738ba0d6
KM
207 npg = ekmempt - kmempt;
208 rminit(kmemmap, npg, (long)CLSIZE, "malloc map", npg);
d4202556
KM
209#ifdef KMEMSTATS
210 for (indx = 0; indx < MINBUCKET + 16; indx++) {
211 if (1 << indx >= CLBYTES)
212 bucket[indx].kb_elmpercl = 1;
213 else
214 bucket[indx].kb_elmpercl = CLBYTES / (1 << indx);
215 bucket[indx].kb_highwat = 5 * bucket[indx].kb_elmpercl;
216 }
217 for (indx = 0; indx < M_LAST; indx++)
738ba0d6 218 kmemstats[indx].ks_limit = npg * CLBYTES * 8 / 10;
d4202556
KM
219#endif
220}