|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University.
4: * Copyright (c) 1993,1994 The University of Utah and
5: * the Computer Systems Laboratory (CSL).
6: * All rights reserved.
7: *
8: * Permission to use, copy, modify and distribute this software and its
9: * documentation is hereby granted, provided that both the copyright
10: * notice and this permission notice appear in all copies of the
11: * software, derivative works or modified versions, and any portions
12: * thereof, and that both notices appear in supporting documentation.
13: *
14: * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
15: * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
16: * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
17: * THIS SOFTWARE.
18: *
19: * Carnegie Mellon requests users of this software to return to
20: *
21: * Software Distribution Coordinator or [email protected]
22: * School of Computer Science
23: * Carnegie Mellon University
24: * Pittsburgh PA 15213-3890
25: *
26: * any improvements or extensions that they make and grant Carnegie Mellon
27: * the rights to redistribute these changes.
28: */
29: /*
30: * File: kern/kalloc.c
31: * Author: Avadis Tevanian, Jr.
32: * Date: 1985
33: *
34: * General kernel memory allocator. This allocator is designed
35: * to be used by the kernel to manage dynamic memory fast.
36: */
37:
38: #include <mach/machine/vm_types.h>
39: #include <mach/vm_param.h>
40:
41: #include <kern/zalloc.h>
42: #include <kern/kalloc.h>
43: #include <vm/vm_kern.h>
44: #include <vm/vm_object.h>
45: #include <vm/vm_map.h>
46:
47:
48:
49: vm_map_t kalloc_map;
50: vm_size_t kalloc_map_size = 8 * 1024 * 1024;
51: vm_size_t kalloc_max;
52:
53: /*
54: * All allocations of size less than kalloc_max are rounded to the
55: * next highest power of 2. This allocator is built on top of
56: * the zone allocator. A zone is created for each potential size
57: * that we are willing to get in small blocks.
58: *
59: * We assume that kalloc_max is not greater than 64K;
60: * thus 16 is a safe array size for k_zone and k_zone_name.
61: */
62:
63: int first_k_zone = -1;
64: struct zone *k_zone[16];
65: static char *k_zone_name[16] = {
66: "kalloc.1", "kalloc.2",
67: "kalloc.4", "kalloc.8",
68: "kalloc.16", "kalloc.32",
69: "kalloc.64", "kalloc.128",
70: "kalloc.256", "kalloc.512",
71: "kalloc.1024", "kalloc.2048",
72: "kalloc.4096", "kalloc.8192",
73: "kalloc.16384", "kalloc.32768"
74: };
75:
76: /*
77: * Max number of elements per zone. zinit rounds things up correctly
78: * Doing things this way permits each zone to have a different maximum size
79: * based on need, rather than just guessing; it also
80: * means its patchable in case you're wrong!
81: */
82: unsigned long k_zone_max[16] = {
83: 1024, /* 1 Byte */
84: 1024, /* 2 Byte */
85: 1024, /* 4 Byte */
86: 1024, /* 8 Byte */
87: 1024, /* 16 Byte */
88: 4096, /* 32 Byte */
89: 4096, /* 64 Byte */
90: 4096, /* 128 Byte */
91: 4096, /* 256 Byte */
92: 1024, /* 512 Byte */
93: 1024, /* 1024 Byte */
94: 1024, /* 2048 Byte */
95: 1024, /* 4096 Byte */
96: 4096, /* 8192 Byte */
97: 64, /* 16384 Byte */
98: 64, /* 32768 Byte */
99: };
100:
101: /*
102: * Initialize the memory allocator. This should be called only
103: * once on a system wide basis (i.e. first processor to get here
104: * does the initialization).
105: *
106: * This initializes all of the zones.
107: */
108:
109: void kalloc_init()
110: {
111: vm_offset_t min, max;
112: vm_size_t size;
113: register int i;
114:
115: kalloc_map = kmem_suballoc(kernel_map, &min, &max,
116: kalloc_map_size, FALSE);
117:
118: /*
119: * Ensure that zones up to size 8192 bytes exist.
120: * This is desirable because messages are allocated
121: * with kalloc, and messages up through size 8192 are common.
122: */
123:
124: if (PAGE_SIZE < 16*1024)
125: kalloc_max = 16*1024;
126: else
127: kalloc_max = PAGE_SIZE;
128:
129: /*
130: * Allocate a zone for each size we are going to handle.
131: * We specify non-paged memory.
132: */
133: for (i = 0, size = 1; size < kalloc_max; i++, size <<= 1) {
134: if (size < MINSIZE) {
135: k_zone[i] = 0;
136: continue;
137: }
138: if (size == MINSIZE) {
139: first_k_zone = i;
140: }
141: k_zone[i] = zinit(size, k_zone_max[i] * size, size,
142: size >= PAGE_SIZE ? ZONE_COLLECTABLE : 0,
143: k_zone_name[i]);
144: }
145: }
146:
147: vm_offset_t kalloc(size)
148: vm_size_t size;
149: {
150: register int zindex;
151: register vm_size_t allocsize;
152: vm_offset_t addr;
153:
154: /* compute the size of the block that we will actually allocate */
155:
156: allocsize = size;
157: if (size < kalloc_max) {
158: allocsize = MINSIZE;
159: zindex = first_k_zone;
160: while (allocsize < size) {
161: allocsize <<= 1;
162: zindex++;
163: }
164: }
165:
166: /*
167: * If our size is still small enough, check the queue for that size
168: * and allocate.
169: */
170:
171: if (allocsize < kalloc_max) {
172: addr = zalloc(k_zone[zindex]);
173: } else {
174: if (kmem_alloc_wired(kalloc_map, &addr, allocsize)
175: != KERN_SUCCESS)
176: addr = 0;
177: }
178: return(addr);
179: }
180:
181: vm_offset_t kget(size)
182: vm_size_t size;
183: {
184: register int zindex;
185: register vm_size_t allocsize;
186: vm_offset_t addr;
187:
188: /* compute the size of the block that we will actually allocate */
189:
190: allocsize = size;
191: if (size < kalloc_max) {
192: allocsize = MINSIZE;
193: zindex = first_k_zone;
194: while (allocsize < size) {
195: allocsize <<= 1;
196: zindex++;
197: }
198: }
199:
200: /*
201: * If our size is still small enough, check the queue for that size
202: * and allocate.
203: */
204:
205: if (allocsize < kalloc_max) {
206: addr = zget(k_zone[zindex]);
207: } else {
208: /* This will never work, so we might as well panic */
209: panic("kget");
210: }
211: return(addr);
212: }
213:
214: void
215: kfree(data, size)
216: vm_offset_t data;
217: vm_size_t size;
218: {
219: register int zindex;
220: register vm_size_t freesize;
221:
222: freesize = size;
223: if (size < kalloc_max) {
224: freesize = MINSIZE;
225: zindex = first_k_zone;
226: while (freesize < size) {
227: freesize <<= 1;
228: zindex++;
229: }
230: }
231:
232: if (freesize < kalloc_max) {
233: zfree(k_zone[zindex], data);
234: } else {
235: kmem_free(kalloc_map, data, freesize);
236: }
237: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.