|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: */
25: /*
26: * HISTORY
27: *
28: * Revision 1.1.1.1 1998/09/22 21:05:34 wsanchez
29: * Import of Mac OS X kernel (~semeria)
30: *
31: * Revision 1.1.1.1 1998/03/07 02:25:55 wsanchez
32: * Import of OSF Mach kernel (~mburg)
33: *
34: * Revision 1.2.19.5 1995/02/24 15:20:29 alanl
35: * Lock package cleanup.
36: * [95/02/15 alanl]
37: *
38: * Merge with DIPC2_SHARED.
39: * [1995/01/05 15:11:02 alanl]
40: *
41: * Revision 1.2.28.2 1994/11/10 06:12:50 dwm
42: * mk6 CR764 - s/spinlock/simple_lock/ (name change only)
43: * [1994/11/10 05:28:35 dwm]
44: *
45: * Revision 1.2.28.1 1994/11/04 10:07:40 dwm
46: * mk6 CR668 - 1.3b26 merge
47: * * Revision 1.2.2.4 1993/11/08 15:04:18 gm
48: * CR9710: Updated to new zinit() and zone_change() interfaces.
49: * * End1.3merge
50: * [1994/11/04 09:25:48 dwm]
51: *
52: * Revision 1.2.19.3 1994/09/23 02:20:52 ezf
53: * change marker to not FREE
54: * [1994/09/22 21:33:57 ezf]
55: *
56: * Revision 1.2.19.2 1994/06/14 18:36:36 bolinger
57: * NMK17.2 merge: Replace simple_lock ops.
58: * [1994/06/14 18:35:17 bolinger]
59: *
60: * Revision 1.2.19.1 1994/06/14 17:04:23 bolinger
61: * Merge up to NMK17.2.
62: * [1994/06/14 16:54:19 bolinger]
63: *
64: * Revision 1.2.23.3 1994/10/14 12:24:33 sjs
65: * Removed krealloc_spinl routine: the newer locking scheme makes it
66: * obsolete.
67: * [94/10/13 sjs]
68: *
69: * Revision 1.2.23.2 1994/08/11 14:42:46 rwd
70: * Post merge cleanup
71: * [94/08/09 rwd]
72: *
73: * Changed zcollectable to use zchange.
74: * [94/08/04 rwd]
75: *
76: * Revision 1.2.17.2 1994/07/08 01:58:45 alanl
77: * Change comment to match function name.
78: * [1994/07/08 01:47:59 alanl]
79: *
80: * Revision 1.2.17.1 1994/05/26 16:20:38 sjs
81: * Added krealloc_spinl: same as krealloc but uses spin locks.
82: * [94/05/25 sjs]
83: *
84: * Revision 1.2.23.1 1994/08/04 02:24:55 mmp
85: * Added krealloc_spinl: same as krealloc but uses spin locks.
86: * [94/05/25 sjs]
87: *
88: * Revision 1.2.13.1 1994/02/11 14:27:12 paire
89: * Changed krealloc() to make it work on a MP system. Added a new parameter
90: * which is the simple lock that should be held while modifying the memory
91: * area already initialized.
92: * Change from NMK16.1 [93/09/02 paire]
93: *
94: * Do not set debug for kalloc zones as default. It wastes
95: * to much space.
96: * Change from NMK16.1 [93/08/16 bernadat]
97: * [94/02/07 paire]
98: *
99: * Revision 1.2.2.3 1993/07/28 17:15:44 bernard
100: * CR9523 -- Prototypes.
101: * [1993/07/27 20:14:12 bernard]
102: *
103: * Revision 1.2.2.2 1993/06/02 23:37:46 jeffc
104: * Added to OSF/1 R1.3 from NMK15.0.
105: * [1993/06/02 21:12:59 jeffc]
106: *
107: * Revision 1.2 1992/12/07 21:28:42 robert
108: * integrate any changes below for 14.0 (branch from 13.16 base)
109: *
110: * Joseph Barrera (jsb) at Carnegie-Mellon University 11-Sep-92
111: * Added krealloc. Added kalloc_max_prerounded for quicker choice between
112: * zalloc and kmem_alloc. Renamed MINSIZE to KALLOC_MINSIZE.
113: * [1992/12/06 19:47:16 robert]
114: *
115: * Revision 1.1 1992/09/30 02:09:23 robert
116: * Initial revision
117: *
118: * $EndLog$
119: */
120: /* CMU_HIST */
121: /*
122: * Revision 2.9 91/05/14 16:43:17 mrt
123: * Correcting copyright
124: *
125: * Revision 2.8 91/03/16 14:50:37 rpd
126: * Updated for new kmem_alloc interface.
127: * [91/03/03 rpd]
128: *
129: * Revision 2.7 91/02/05 17:27:22 mrt
130: * Changed to new Mach copyright
131: * [91/02/01 16:14:12 mrt]
132: *
133: * Revision 2.6 90/06/19 22:59:06 rpd
134: * Made the big kalloc zones collectable.
135: * [90/06/05 rpd]
136: *
137: * Revision 2.5 90/06/02 14:54:47 rpd
138: * Added kalloc_max, kalloc_map_size.
139: * [90/03/26 22:06:39 rpd]
140: *
141: * Revision 2.4 90/01/11 11:43:13 dbg
142: * De-lint.
143: * [89/12/06 dbg]
144: *
145: * Revision 2.3 89/09/08 11:25:51 dbg
146: * MACH_KERNEL: remove non-MACH data types.
147: * [89/07/11 dbg]
148: *
149: * Revision 2.2 89/08/31 16:18:59 rwd
150: * First Checkin
151: * [89/08/23 15:41:37 rwd]
152: *
153: * Revision 2.6 89/08/02 08:03:28 jsb
154: * Make all kalloc zones 8 MB big. (No more kalloc panics!)
155: * [89/08/01 14:10:17 jsb]
156: *
157: * Revision 2.4 89/04/05 13:03:10 rvb
158: * Guarantee a zone max of at least 100 elements or 10 pages
159: * which ever is greater. Afs (AllocDouble()) puts a great demand
160: * on the 2048 zone and used to blow away.
161: * [89/03/09 rvb]
162: *
163: * Revision 2.3 89/02/25 18:04:39 gm0w
164: * Changes for cleanup.
165: *
166: * Revision 2.2 89/01/18 02:07:04 jsb
167: * Give each kalloc zone a meaningful name (for panics);
168: * create a zone for each power of 2 between MINSIZE
169: * and PAGE_SIZE, instead of using (obsoleted) NQUEUES.
170: * [89/01/17 10:16:33 jsb]
171: *
172: *
173: * 13-Feb-88 John Seamons (jks) at NeXT
174: * Updated to use kmem routines instead of vmem routines.
175: *
176: * 21-Jun-85 Avadis Tevanian (avie) at Carnegie-Mellon University
177: * Created.
178: */
179: /* CMU_ENDHIST */
180: /*
181: * Mach Operating System
182: * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
183: * All Rights Reserved.
184: *
185: * Permission to use, copy, modify and distribute this software and its
186: * documentation is hereby granted, provided that both the copyright
187: * notice and this permission notice appear in all copies of the
188: * software, derivative works or modified versions, and any portions
189: * thereof, and that both notices appear in supporting documentation.
190: *
191: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
192: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
193: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
194: *
195: * Carnegie Mellon requests users of this software to return to
196: *
197: * Software Distribution Coordinator or [email protected]
198: * School of Computer Science
199: * Carnegie Mellon University
200: * Pittsburgh PA 15213-3890
201: *
202: * any improvements or extensions that they make and grant Carnegie Mellon
203: * the rights to redistribute these changes.
204: */
205: /*
206: */
207: /*
208: * File: kern/kalloc.c
209: * Author: Avadis Tevanian, Jr.
210: * Date: 1985
211: *
212: * General kernel memory allocator. This allocator is designed
213: * to be used by the kernel to manage dynamic memory fast.
214: */
215:
216: #include <zone_debug.h>
217:
218: #include <mach/boolean.h>
219: #include <mach/machine/vm_types.h>
220: #include <mach/vm_param.h>
221: #include <kern/misc_protos.h>
222: #include <kern/zalloc.h>
223: #include <kern/kalloc.h>
224: #include <kern/lock.h>
225: #include <vm/vm_kern.h>
226: #include <vm/vm_object.h>
227: #include <vm/vm_map.h>
228:
229: #ifdef MACH_BSD
230: zone_t kalloc_zone(vm_size_t);
231: #endif
232:
233: vm_map_t kalloc_map;
234: vm_size_t kalloc_map_size = 8 * 1024 * 1024;
235: vm_size_t kalloc_max;
236: vm_size_t kalloc_max_prerounded;
237:
238: /*
239: * All allocations of size less than kalloc_max are rounded to the
240: * next highest power of 2. This allocator is built on top of
241: * the zone allocator. A zone is created for each potential size
242: * that we are willing to get in small blocks.
243: *
244: * We assume that kalloc_max is not greater than 64K;
245: * thus 16 is a safe array size for k_zone and k_zone_name.
246: *
247: * Note that kalloc_max is somewhat confusingly named.
248: * It represents the first power of two for which no zone exists.
249: * kalloc_max_prerounded is the smallest allocation size, before
250: * rounding, for which no zone exists.
251: */
252:
253: int first_k_zone = -1;
254: struct zone *k_zone[16];
255: static char *k_zone_name[16] = {
256: "kalloc.1", "kalloc.2",
257: "kalloc.4", "kalloc.8",
258: "kalloc.16", "kalloc.32",
259: "kalloc.64", "kalloc.128",
260: "kalloc.256", "kalloc.512",
261: "kalloc.1024", "kalloc.2048",
262: "kalloc.4096", "kalloc.8192",
263: "kalloc.16384", "kalloc.32768"
264: };
265:
266: /*
267: * Max number of elements per zone. zinit rounds things up correctly
268: * Doing things this way permits each zone to have a different maximum size
269: * based on need, rather than just guessing; it also
270: * means its patchable in case you're wrong!
271: */
272: unsigned long k_zone_max[16] = {
273: 1024, /* 1 Byte */
274: 1024, /* 2 Byte */
275: 1024, /* 4 Byte */
276: 1024, /* 8 Byte */
277: 1024, /* 16 Byte */
278: 4096, /* 32 Byte */
279: 4096, /* 64 Byte */
280: 4096, /* 128 Byte */
281: 4096, /* 256 Byte */
282: 1024, /* 512 Byte */
283: 1024, /* 1024 Byte */
284: 1024, /* 2048 Byte */
285: 1024, /* 4096 Byte */
286: 4096, /* 8192 Byte */
287: 64, /* 16384 Byte */
288: 64, /* 32768 Byte */
289: };
290:
291: /*
292: * Initialize the memory allocator. This should be called only
293: * once on a system wide basis (i.e. first processor to get here
294: * does the initialization).
295: *
296: * This initializes all of the zones.
297: */
298:
299: void
300: kalloc_init(
301: void)
302: {
303: kern_return_t retval;
304: vm_offset_t min;
305: vm_size_t size;
306: register int i;
307:
308: retval = kmem_suballoc(kernel_map, &min, kalloc_map_size,
309: FALSE, TRUE, &kalloc_map);
310: if (retval != KERN_SUCCESS)
311: panic("kalloc_init: kmem_suballoc failed");
312:
313: /*
314: * Ensure that zones up to size 8192 bytes exist.
315: * This is desirable because messages are allocated
316: * with kalloc, and messages up through size 8192 are common.
317: */
318:
319: if (PAGE_SIZE < 16*1024)
320: kalloc_max = 16*1024;
321: else
322: kalloc_max = PAGE_SIZE;
323: kalloc_max_prerounded = kalloc_max / 2 + 1;
324:
325: /*
326: * Allocate a zone for each size we are going to handle.
327: * We specify non-paged memory.
328: */
329: for (i = 0, size = 1; size < kalloc_max; i++, size <<= 1) {
330: if (size < KALLOC_MINSIZE) {
331: k_zone[i] = 0;
332: continue;
333: }
334: if (size == KALLOC_MINSIZE) {
335: first_k_zone = i;
336: }
337: k_zone[i] = zinit(size, k_zone_max[i] * size, size,
338: k_zone_name[i]);
339: }
340: }
341:
342: vm_offset_t
343: kalloc(
344: vm_size_t size)
345: {
346: register int zindex;
347: register vm_size_t allocsize;
348:
349: /*
350: * If size is too large for a zone, then use kmem_alloc.
351: * (We use kmem_alloc instead of kmem_alloc_wired so that
352: * krealloc can use kmem_realloc.)
353: */
354:
355: if (size >= kalloc_max_prerounded) {
356: vm_offset_t addr;
357:
358: if (kmem_alloc(kalloc_map, &addr, size) != KERN_SUCCESS)
359: addr = 0;
360: return(addr);
361: }
362:
363: /* compute the size of the block that we will actually allocate */
364:
365: allocsize = KALLOC_MINSIZE;
366: zindex = first_k_zone;
367: while (allocsize < size) {
368: allocsize <<= 1;
369: zindex++;
370: }
371:
372: /* allocate from the appropriate zone */
373:
374: assert(allocsize < kalloc_max);
375: return(zalloc(k_zone[zindex]));
376: }
377:
378: void
379: krealloc(
380: vm_offset_t *addrp,
381: vm_size_t old_size,
382: vm_size_t new_size,
383: simple_lock_t lock)
384: {
385: register int zindex;
386: register vm_size_t allocsize;
387: vm_offset_t naddr;
388:
389: /* can only be used for increasing allocation size */
390:
391: assert(new_size > old_size);
392:
393: /* if old_size is zero, then we are simply allocating */
394:
395: if (old_size == 0) {
396: simple_unlock(lock);
397: naddr = kalloc(new_size);
398: simple_lock(lock);
399: *addrp = naddr;
400: return;
401: }
402:
403: /* if old block was kmem_alloc'd, then use kmem_realloc if necessary */
404:
405: if (old_size >= kalloc_max_prerounded) {
406: old_size = round_page(old_size);
407: new_size = round_page(new_size);
408: if (new_size > old_size) {
409:
410: if (kmem_realloc(kalloc_map, *addrp, old_size, &naddr,
411:
412:
413:
414:
415: new_size) != KERN_SUCCESS) {
416: panic("krealloc: kmem_realloc");
417: naddr = 0;
418: }
419:
420: simple_lock(lock);
421: *addrp = naddr;
422:
423: /* kmem_realloc() doesn't free old page range. */
424: kmem_free(kalloc_map, *addrp, old_size);
425: }
426: return;
427: }
428:
429: /* compute the size of the block that we actually allocated */
430:
431: allocsize = KALLOC_MINSIZE;
432: zindex = first_k_zone;
433: while (allocsize < old_size) {
434: allocsize <<= 1;
435: zindex++;
436: }
437:
438: /* if new size fits in old block, then return */
439:
440: if (new_size <= allocsize) {
441: return;
442: }
443:
444: /* if new size does not fit in zone, kmem_alloc it, else zalloc it */
445:
446: simple_unlock(lock);
447: if (new_size >= kalloc_max_prerounded) {
448: if (kmem_alloc(kalloc_map, &naddr, new_size) != KERN_SUCCESS) {
449: panic("krealloc: kmem_alloc");
450: simple_lock(lock);
451: *addrp = 0;
452: return;
453: }
454: } else {
455: register int new_zindex;
456:
457: allocsize <<= 1;
458: new_zindex = zindex + 1;
459: while (allocsize < new_size) {
460: allocsize <<= 1;
461: new_zindex++;
462: }
463: naddr = zalloc(k_zone[new_zindex]);
464: }
465: simple_lock(lock);
466:
467: /* copy existing data */
468:
469: bcopy((const char *)*addrp, (char *)naddr, old_size);
470:
471: /* free old block, and return */
472:
473: zfree(k_zone[zindex], *addrp);
474:
475: /* set up new address */
476:
477: *addrp = naddr;
478: }
479:
480:
481: vm_offset_t
482: kget(
483: vm_size_t size)
484: {
485: register int zindex;
486: register vm_size_t allocsize;
487:
488: /* size must not be too large for a zone */
489:
490: if (size >= kalloc_max_prerounded) {
491: /* This will never work, so we might as well panic */
492: panic("kget");
493: }
494:
495: /* compute the size of the block that we will actually allocate */
496:
497: allocsize = KALLOC_MINSIZE;
498: zindex = first_k_zone;
499: while (allocsize < size) {
500: allocsize <<= 1;
501: zindex++;
502: }
503:
504: /* allocate from the appropriate zone */
505:
506: assert(allocsize < kalloc_max);
507: return(zget(k_zone[zindex]));
508: }
509:
510: void
511: kfree(
512: vm_offset_t data,
513: vm_size_t size)
514: {
515: register int zindex;
516: register vm_size_t freesize;
517:
518: /* if size was too large for a zone, then use kmem_free */
519:
520: if (size >= kalloc_max_prerounded) {
521: kmem_free(kalloc_map, data, size);
522: return;
523: }
524:
525: /* compute the size of the block that we actually allocated from */
526:
527: freesize = KALLOC_MINSIZE;
528: zindex = first_k_zone;
529: while (freesize < size) {
530: freesize <<= 1;
531: zindex++;
532: }
533:
534: /* free to the appropriate zone */
535:
536: assert(freesize < kalloc_max);
537: zfree(k_zone[zindex], data);
538: }
539:
540: #ifdef MACH_BSD
541: zone_t
542: kalloc_zone(
543: vm_size_t size)
544: {
545: register int zindex = 0;
546: register vm_size_t allocsize;
547:
548: /* compute the size of the block that we will actually allocate */
549:
550: allocsize = size;
551: if (size <= kalloc_max) {
552: allocsize = KALLOC_MINSIZE;
553: zindex = first_k_zone;
554: while (allocsize < size) {
555: allocsize <<= 1;
556: zindex++;
557: }
558: return (k_zone[zindex]);
559: }
560: return (ZONE_NULL);
561: }
562: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.