]> git.saurik.com Git - apple/xnu.git/blob - bsd/dev/dtrace/dtrace_alloc.c
xnu-1486.2.11.tar.gz
[apple/xnu.git] / bsd / dev / dtrace / dtrace_alloc.c
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
51 vm_size_t dtrace_alloc_max;
52 vm_size_t dtrace_alloc_max_prerounded;
53 int first_d_zone = -1;
54 struct zone *d_zone[16];
55 static 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
66 unsigned 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
85 void 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
112 void *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_kobject 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
138 void 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 */