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