|
|
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.