|
|
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: #include <oskit/x86/debug_reg.h>
110:
111: void kalloc_init()
112: {
113: vm_offset_t min, max;
114: vm_size_t size;
115: register int i;
116:
117: kalloc_map = kmem_suballoc(kernel_map, &min, &max,
118: kalloc_map_size, FALSE);
119:
120: /*
121: * Ensure that zones up to size 8192 bytes exist.
122: * This is desirable because messages are allocated
123: * with kalloc, and messages up through size 8192 are common.
124: */
125:
126: if (PAGE_SIZE < 16*1024)
127: kalloc_max = 16*1024;
128: else
129: kalloc_max = PAGE_SIZE;
130:
131: /*
132: * Allocate a zone for each size we are going to handle.
133: * We specify non-paged memory.
134: */
135: for (i = 0, size = 1; size < kalloc_max; i++, size <<= 1) {
136: if (size < MINSIZE) {
137: k_zone[i] = 0;
138: continue;
139: }
140: if (size == MINSIZE) {
141: first_k_zone = i;
142: }
143: k_zone[i] = zinit(size, k_zone_max[i] * size, size,
144: size >= PAGE_SIZE ? ZONE_COLLECTABLE : 0,
145: k_zone_name[i]);
146: }
147: }
148:
149: vm_offset_t kalloc(size)
150: vm_size_t size;
151: {
152: register int zindex;
153: register vm_size_t allocsize;
154: vm_offset_t addr;
155:
156: /* compute the size of the block that we will actually allocate */
157:
158: allocsize = size;
159: if (size < kalloc_max) {
160: allocsize = MINSIZE;
161: zindex = first_k_zone;
162: while (allocsize < size) {
163: allocsize <<= 1;
164: zindex++;
165: }
166: }
167:
168: /*
169: * If our size is still small enough, check the queue for that size
170: * and allocate.
171: */
172:
173: if (allocsize < kalloc_max) {
174: addr = zalloc(k_zone[zindex]);
175: } else {
176: if (kmem_alloc_wired(kalloc_map, &addr, allocsize)
177: != KERN_SUCCESS)
178: addr = 0;
179: }
180: return(addr);
181: }
182:
183: vm_offset_t kget(size)
184: vm_size_t size;
185: {
186: register int zindex;
187: register vm_size_t allocsize;
188: vm_offset_t addr;
189:
190: /* compute the size of the block that we will actually allocate */
191:
192: allocsize = size;
193: if (size < kalloc_max) {
194: allocsize = MINSIZE;
195: zindex = first_k_zone;
196: while (allocsize < size) {
197: allocsize <<= 1;
198: zindex++;
199: }
200: }
201:
202: /*
203: * If our size is still small enough, check the queue for that size
204: * and allocate.
205: */
206:
207: if (allocsize < kalloc_max) {
208: addr = zget(k_zone[zindex]);
209: } else {
210: /* This will never work, so we might as well panic */
211: panic("kget");
212: }
213: return(addr);
214: }
215:
216: void
217: kfree(data, size)
218: vm_offset_t data;
219: vm_size_t size;
220: {
221: register int zindex;
222: register vm_size_t freesize;
223:
224: freesize = size;
225: if (size < kalloc_max) {
226: freesize = MINSIZE;
227: zindex = first_k_zone;
228: while (freesize < size) {
229: freesize <<= 1;
230: zindex++;
231: }
232: }
233:
234: if (freesize < kalloc_max) {
235: zfree(k_zone[zindex], data);
236: } else {
237: kmem_free(kalloc_map, data, freesize);
238: }
239: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.