tty now holds pointer to process group, not a process group id
[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 5 * Redistribution and use in source and binary forms are permitted
616d42db
KB
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2420c94a 16 *
dbe43ea1 17 * @(#)kern_malloc.c 7.13 (Berkeley) %G%
d4202556
KM
18 */
19
20#include "param.h"
21#include "vm.h"
22#include "cmap.h"
23#include "time.h"
24#include "proc.h"
25#include "map.h"
26#include "kernel.h"
27#include "malloc.h"
28
40ed2c45 29#include "machine/pte.h"
d4202556
KM
30
31struct kmembuckets bucket[MINBUCKET + 16];
32struct kmemstats kmemstats[M_LAST];
33struct kmemusage *kmemusage;
fd78e9f6 34long wantkmemmap;
d4202556
KM
35
36/*
37 * Allocate a block of memory
38 */
738ba0d6
KM
39qaddr_t
40malloc(size, type, flags)
d4202556 41 unsigned long size;
47516941 42 int type, flags;
d4202556
KM
43{
44 register struct kmembuckets *kbp;
45 register struct kmemusage *kup;
47516941
MK
46 long indx, npg, alloc, allocsize;
47 int s;
d4202556
KM
48 caddr_t va, cp;
49#ifdef KMEMSTATS
fd78e9f6 50 register struct kmemstats *ksp = &kmemstats[type];
dbe43ea1
MK
51
52 if (((unsigned long)type) > M_LAST)
a2aebb63 53 panic("malloc - bogus type");
d4202556 54#endif
fd78e9f6 55
d4202556
KM
56 indx = BUCKETINDX(size);
57 kbp = &bucket[indx];
58 s = splimp();
fd78e9f6
KM
59again:
60#ifdef KMEMSTATS
0a4aff4d 61 while (ksp->ks_memuse >= ksp->ks_limit) {
fd78e9f6
KM
62 if (flags & M_NOWAIT) {
63 splx(s);
64 return (0);
65 }
66 if (ksp->ks_limblocks < 65535)
67 ksp->ks_limblocks++;
68 sleep((caddr_t)ksp, PSWP+2);
69 }
70#endif
d4202556
KM
71 if (kbp->kb_next == NULL) {
72 if (size > MAXALLOCSAVE)
73 allocsize = roundup(size, CLBYTES);
74 else
75 allocsize = 1 << indx;
76 npg = clrnd(btoc(allocsize));
77 if ((flags & M_NOWAIT) && freemem < npg) {
78 splx(s);
79 return (0);
80 }
81 alloc = rmalloc(kmemmap, npg);
82 if (alloc == 0) {
fd78e9f6
KM
83 if (flags & M_NOWAIT) {
84 splx(s);
85 return (0);
86 }
87#ifdef KMEMSTATS
88 if (ksp->ks_mapblocks < 65535)
89 ksp->ks_mapblocks++;
90#endif
91 wantkmemmap++;
92 sleep((caddr_t)&wantkmemmap, PSWP+2);
93 goto again;
d4202556 94 }
7656fce5 95 alloc -= CLSIZE; /* convert to base 0 */
47516941 96 (void) vmemall(&kmempt[alloc], (int)npg, &proc[0], CSYS);
d4202556 97 va = (caddr_t) kmemxtob(alloc);
47516941 98 vmaccess(&kmempt[alloc], va, (int)npg);
d4202556
KM
99#ifdef KMEMSTATS
100 kbp->kb_total += kbp->kb_elmpercl;
101#endif
102 kup = btokup(va);
103 kup->ku_indx = indx;
104 if (allocsize > MAXALLOCSAVE) {
105 if (npg > 65535)
106 panic("malloc: allocation too large");
107 kup->ku_pagecnt = npg;
fd78e9f6
KM
108#ifdef KMEMSTATS
109 ksp->ks_memuse += allocsize;
110#endif
d4202556
KM
111 goto out;
112 }
113#ifdef KMEMSTATS
114 kup->ku_freecnt = kbp->kb_elmpercl;
115 kbp->kb_totalfree += kbp->kb_elmpercl;
116#endif
117 kbp->kb_next = va + (npg * NBPG) - allocsize;
fd78e9f6 118 for (cp = kbp->kb_next; cp > va; cp -= allocsize)
d4202556
KM
119 *(caddr_t *)cp = cp - allocsize;
120 *(caddr_t *)cp = NULL;
121 }
122 va = kbp->kb_next;
123 kbp->kb_next = *(caddr_t *)va;
124#ifdef KMEMSTATS
125 kup = btokup(va);
126 if (kup->ku_indx != indx)
127 panic("malloc: wrong bucket");
128 if (kup->ku_freecnt == 0)
129 panic("malloc: lost data");
130 kup->ku_freecnt--;
131 kbp->kb_totalfree--;
fd78e9f6 132 ksp->ks_memuse += 1 << indx;
d4202556
KM
133out:
134 kbp->kb_calls++;
135 ksp->ks_inuse++;
136 ksp->ks_calls++;
0a4aff4d
KM
137 if (ksp->ks_memuse > ksp->ks_maxused)
138 ksp->ks_maxused = ksp->ks_memuse;
d4202556
KM
139#else
140out:
141#endif
142 splx(s);
143 return ((qaddr_t)va);
144}
145
146/*
147 * Free a block of memory allocated by malloc.
148 */
738ba0d6
KM
149void
150free(addr, type)
d4202556 151 caddr_t addr;
47516941 152 int type;
d4202556
KM
153{
154 register struct kmembuckets *kbp;
155 register struct kmemusage *kup;
47516941
MK
156 long alloc, size;
157 int s;
fd78e9f6
KM
158#ifdef KMEMSTATS
159 register struct kmemstats *ksp = &kmemstats[type];
160#endif
d4202556
KM
161
162 kup = btokup(addr);
738ba0d6 163 kbp = &bucket[kup->ku_indx];
d4202556 164 s = splimp();
0a4aff4d
KM
165 size = 1 << kup->ku_indx;
166 if (size > MAXALLOCSAVE) {
d4202556 167 alloc = btokmemx(addr);
47516941 168 (void) memfree(&kmempt[alloc], (int)kup->ku_pagecnt, 0);
fd78e9f6
KM
169 rmfree(kmemmap, (long)kup->ku_pagecnt, alloc + CLSIZE);
170 if (wantkmemmap) {
171 wakeup((caddr_t)&wantkmemmap);
172 wantkmemmap = 0;
173 }
d4202556 174#ifdef KMEMSTATS
0a4aff4d
KM
175 size = kup->ku_pagecnt << PGSHIFT;
176 ksp->ks_memuse -= size;
d4202556
KM
177 kup->ku_indx = 0;
178 kup->ku_pagecnt = 0;
0a4aff4d
KM
179 if (ksp->ks_memuse + size >= ksp->ks_limit &&
180 ksp->ks_memuse < ksp->ks_limit)
fd78e9f6
KM
181 wakeup((caddr_t)ksp);
182 ksp->ks_inuse--;
738ba0d6 183 kbp->kb_total -= 1;
d4202556
KM
184#endif
185 splx(s);
186 return;
187 }
d4202556
KM
188#ifdef KMEMSTATS
189 kup->ku_freecnt++;
190 if (kup->ku_freecnt >= kbp->kb_elmpercl)
191 if (kup->ku_freecnt > kbp->kb_elmpercl)
192 panic("free: multiple frees");
193 else if (kbp->kb_totalfree > kbp->kb_highwat)
194 kbp->kb_couldfree++;
195 kbp->kb_totalfree++;
0a4aff4d
KM
196 ksp->ks_memuse -= size;
197 if (ksp->ks_memuse + size >= ksp->ks_limit &&
198 ksp->ks_memuse < ksp->ks_limit)
fd78e9f6
KM
199 wakeup((caddr_t)ksp);
200 ksp->ks_inuse--;
d4202556
KM
201#endif
202 *(caddr_t *)addr = kbp->kb_next;
203 kbp->kb_next = addr;
204 splx(s);
205}
206
207/*
208 * Initialize the kernel memory allocator
209 */
210kmeminit()
211{
212 register long indx;
738ba0d6 213 int npg;
d4202556 214
47516941
MK
215#if ((MAXALLOCSAVE & (MAXALLOCSAVE - 1)) != 0)
216 ERROR!_kmeminit:_MAXALLOCSAVE_not_power_of_2
217#endif
218#if (MAXALLOCSAVE > MINALLOCSIZE * 32768)
219 ERROR!_kmeminit:_MAXALLOCSAVE_too_big
220#endif
221#if (MAXALLOCSAVE < CLBYTES)
222 ERROR!_kmeminit:_MAXALLOCSAVE_too_small
223#endif
738ba0d6 224 npg = ekmempt - kmempt;
47516941 225 rminit(kmemmap, (long)npg, (long)CLSIZE, "malloc map", npg);
d4202556
KM
226#ifdef KMEMSTATS
227 for (indx = 0; indx < MINBUCKET + 16; indx++) {
228 if (1 << indx >= CLBYTES)
229 bucket[indx].kb_elmpercl = 1;
230 else
231 bucket[indx].kb_elmpercl = CLBYTES / (1 << indx);
232 bucket[indx].kb_highwat = 5 * bucket[indx].kb_elmpercl;
233 }
234 for (indx = 0; indx < M_LAST; indx++)
738ba0d6 235 kmemstats[indx].ks_limit = npg * CLBYTES * 8 / 10;
d4202556
KM
236#endif
237}