1/* 2 * Copyright (c) 2005-2007 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29/* 30 * DTrace kalloc emulation. 31 * 32 * This is a subset of kalloc functionality, to allow dtrace 33 * specific allocation to be accounted for separately from the 34 * general kalloc pool. 35 * 36 * Note that allocations greater than dalloc_max still go into 37 * the kalloc.large bucket, as it seems impossible to emulate 38 * that functionality in the bsd kern. 39 */ 40 41#include <stdarg.h> 42#include <string.h> 43#include <sys/malloc.h> 44#include <sys/dtrace.h> 45#include <kern/zalloc.h> 46 47#if defined(DTRACE_MEMORY_ZONES) 48 49#define DTRACE_ALLOC_MINSIZE 16 50 51vm_size_t dtrace_alloc_max; 52vm_size_t dtrace_alloc_max_prerounded; 53int first_d_zone = -1; 54struct zone *d_zone[16]; 55static const char *d_zone_name[16] = { 56 "dtrace.1", "dtrace.2", 57 "dtrace.4", "dtrace.8", 58 "dtrace.16", "dtrace.32", 59 "dtrace.64", "dtrace.128", 60 "dtrace.256", "dtrace.512", 61 "dtrace.1024", "dtrace.2048", 62 "dtrace.4096", "dtrace.8192", 63 "dtrace.16384", "dtrace.32768" 64}; 65 66unsigned long d_zone_max[16] = { 67 1024, /* 1 Byte */ 68 1024, /* 2 Byte */ 69 1024, /* 4 Byte */ 70 1024, /* 8 Byte */ 71 1024, /* 16 Byte */ 72 4096, /* 32 Byte */ 73 4096, /* 64 Byte */ 74 4096, /* 128 Byte */ 75 4096, /* 256 Byte */ 76 1024, /* 512 Byte */ 77 1024, /* 1024 Byte */ 78 1024, /* 2048 Byte */ 79 1024, /* 4096 Byte */ 80 4096, /* 8192 Byte */ 81 64, /* 16384 Byte */ 82 64, /* 32768 Byte */ 83}; 84 85void dtrace_alloc_init(void) 86{ 87 vm_size_t size; 88 int i; 89 90 if (PAGE_SIZE < 16*1024) 91 dtrace_alloc_max = 16*1024; 92 else 93 dtrace_alloc_max = PAGE_SIZE; 94 dtrace_alloc_max_prerounded = dtrace_alloc_max / 2 + 1; 95 96 /* 97 * Allocate a zone for each size we are going to handle. 98 * We specify non-paged memory. 99 */ 100 for (i = 0, size = 1; size < dtrace_alloc_max; i++, size <<= 1) { 101 if (size < DTRACE_ALLOC_MINSIZE) { 102 d_zone[i] = NULL; 103 continue; 104 } 105 if (size == DTRACE_ALLOC_MINSIZE) { 106 first_d_zone = i; 107 } 108 d_zone[i] = zinit(size, d_zone_max[i] * size, size, d_zone_name[i]); 109 } 110} 111 112void *dtrace_alloc(vm_size_t size) 113{ 114 int zindex; 115 vm_size_t allocsize; 116 117 /* 118 * If size is too large for a zone, then use kmem_alloc. 119 * (We use kmem_alloc instead of kmem_alloc_wired so that 120 * krealloc can use kmem_realloc.) 121 */ 122 123 if (size >= dtrace_alloc_max_prerounded) { 124 return _MALLOC(size, M_TEMP, M_WAITOK); 125 } 126 127 /* compute the size of the block that we will actually allocate */ 128 allocsize = DTRACE_ALLOC_MINSIZE; 129 zindex = first_d_zone; 130 while (allocsize < size) { 131 allocsize <<= 1; 132 zindex++; 133 } 134 135 return(zalloc_canblock(d_zone[zindex], TRUE)); 136} 137 138void dtrace_free(void *data, vm_size_t size) 139{ 140 int zindex; 141 vm_size_t freesize; 142 143 if (size >= dtrace_alloc_max_prerounded) { 144 _FREE(data, M_TEMP); 145 return; 146 } 147 148 /* compute the size of the block that we actually allocated from */ 149 freesize = DTRACE_ALLOC_MINSIZE; 150 zindex = first_d_zone; 151 while (freesize < size) { 152 freesize <<= 1; 153 zindex++; 154 } 155 156 /* free to the appropriate zone */ 157 zfree(d_zone[zindex], data); 158} 159 160#endif /* DTRACE_MEMORY_ZONES */ 161