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