]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_malloc.c
xnu-123.5.tar.gz
[apple/xnu.git] / bsd / kern / kern_malloc.c
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 /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
23 /*
24 * Copyright (c) 1987, 1991, 1993
25 * The Regents of the University of California. All rights reserved.
26 *
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
29 * are met:
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * SUCH DAMAGE.
54 *
55 * @(#)kern_malloc.c 8.4 (Berkeley) 5/20/95
56 */
57
58 #include <sys/param.h>
59 #include <sys/malloc.h>
60
61 #include <sys/socket.h>
62 #include <sys/socketvar.h>
63
64 #include <net/route.h>
65
66 #include <netinet/in.h>
67 #include <netinet/in_systm.h>
68 #include <netinet/ip.h>
69 #include <netinet/in_pcb.h>
70
71 #include <sys/proc.h>
72 #include <sys/mount.h>
73 #include <sys/vnode.h>
74 #include <sys/namei.h>
75 #include <sys/file.h>
76 #include <sys/filedesc.h>
77 #include <sys/tty.h>
78
79 #include <ufs/ufs/quota.h>
80 #include <ufs/ufs/inode.h>
81
82 #include <hfs/hfs.h>
83 #include <isofs/cd9660/cd9660_node.h>
84
85 #include <miscfs/volfs/volfs.h>
86
87 #include <nfs/rpcv2.h>
88 #include <nfs/nfsproto.h>
89 #include <nfs/nfsnode.h>
90 #include <nfs/nfsmount.h>
91 #include <nfs/nqnfs.h>
92
93 #include <mach/mach_types.h>
94
95 #include <kern/zalloc.h>
96 #include <kern/kalloc.h>
97
98 struct kmemstats kmemstats[M_LAST];
99 char *memname[] = INITKMEMNAMES;
100
101 struct kmzones {
102 size_t kz_elemsize;
103 void *kz_zalloczone;
104 #define KMZ_CREATEZONE ((void *)-2)
105 #define KMZ_LOOKUPZONE ((void *)-1)
106 #define KMZ_MALLOC ((void *)0)
107 #define KMZ_SHAREZONE ((void *)1)
108 } kmzones[M_LAST] = {
109 #define SOS(sname) sizeof (struct sname)
110 #define SOX(sname) -1
111 -1, 0, /* 0 M_FREE */
112 MSIZE, KMZ_CREATEZONE, /* 1 M_MBUF */
113 0, KMZ_MALLOC, /* 2 M_DEVBUF */
114 SOS(socket), KMZ_CREATEZONE, /* 3 M_SOCKET */
115 SOS(inpcb), KMZ_LOOKUPZONE, /* 4 M_PCB */
116 M_MBUF, KMZ_SHAREZONE, /* 5 M_RTABLE */
117 M_MBUF, KMZ_SHAREZONE, /* 6 M_HTABLE */
118 M_MBUF, KMZ_SHAREZONE, /* 7 M_FTABLE */
119 SOS(rusage), KMZ_CREATEZONE, /* 8 M_ZOMBIE */
120 0, KMZ_MALLOC, /* 9 M_IFADDR */
121 M_MBUF, KMZ_SHAREZONE, /* 10 M_SOOPTS */
122 0, KMZ_MALLOC, /* 11 M_SONAME */
123 MAXPATHLEN, KMZ_CREATEZONE, /* 12 M_NAMEI */
124 0, KMZ_MALLOC, /* 13 M_GPROF */
125 0, KMZ_MALLOC, /* 14 M_IOCTLOPS */
126 0, KMZ_MALLOC, /* 15 M_MAPMEM */
127 SOS(ucred), KMZ_CREATEZONE, /* 16 M_CRED */
128 SOS(pgrp), KMZ_CREATEZONE, /* 17 M_PGRP */
129 SOS(session), KMZ_CREATEZONE, /* 18 M_SESSION */
130 SOS(iovec), KMZ_LOOKUPZONE, /* 19 M_IOV */
131 SOS(mount), KMZ_CREATEZONE, /* 20 M_MOUNT */
132 0, KMZ_MALLOC, /* 21 M_FHANDLE */
133 SOS(nfsreq), KMZ_CREATEZONE, /* 22 M_NFSREQ */
134 SOS(nfsmount), KMZ_CREATEZONE, /* 23 M_NFSMNT */
135 SOS(nfsnode), KMZ_CREATEZONE, /* 24 M_NFSNODE */
136 SOS(vnode), KMZ_CREATEZONE, /* 25 M_VNODE */
137 SOS(namecache), KMZ_CREATEZONE, /* 26 M_CACHE */
138 SOX(dquot), KMZ_LOOKUPZONE, /* 27 M_DQUOT */
139 SOX(ufsmount), KMZ_LOOKUPZONE, /* 28 M_UFSMNT */
140 0, KMZ_MALLOC, /* 29 M_CGSUM */
141 0, KMZ_MALLOC, /* 30 M_VMMAP */
142 0, KMZ_MALLOC, /* 31 M_VMMAPENT */
143 0, KMZ_MALLOC, /* 32 M_VMOBJ */
144 0, KMZ_MALLOC, /* 33 M_VMOBJHASH */
145 0, KMZ_MALLOC, /* 34 M_VMPMAP */
146 0, KMZ_MALLOC, /* 35 M_VMPVENT */
147 0, KMZ_MALLOC, /* 36 M_VMPAGER */
148 0, KMZ_MALLOC, /* 37 M_VMPGDATA */
149 SOS(file), KMZ_CREATEZONE, /* 38 M_FILE */
150 SOS(filedesc), KMZ_CREATEZONE, /* 39 M_FILEDESC */
151 SOX(lockf), KMZ_CREATEZONE, /* 40 M_LOCKF */
152 SOS(proc), KMZ_CREATEZONE, /* 41 M_PROC */
153 SOS(pcred), KMZ_CREATEZONE, /* 42 M_SUBPROC */
154 0, KMZ_MALLOC, /* 43 M_SEGMENT */
155 M_FFSNODE, KMZ_SHAREZONE, /* 44 M_LFSNODE */
156 SOS(inode), KMZ_CREATEZONE, /* 45 M_FFSNODE */
157 M_FFSNODE, KMZ_SHAREZONE, /* 46 M_MFSNODE */
158 SOS(nqlease), KMZ_CREATEZONE, /* 47 M_NQLEASE */
159 SOS(nqm), KMZ_CREATEZONE, /* 48 M_NQMHOST */
160 0, KMZ_MALLOC, /* 49 M_NETADDR */
161 SOX(nfssvc_sock),
162 KMZ_CREATEZONE, /* 50 M_NFSSVC */
163 SOS(nfsuid), KMZ_CREATEZONE, /* 51 M_NFSUID */
164 SOX(nfsrvcache),
165 KMZ_CREATEZONE, /* 52 M_NFSD */
166 SOX(ip_moptions),
167 KMZ_LOOKUPZONE, /* 53 M_IPMOPTS */
168 SOX(in_multi), KMZ_LOOKUPZONE, /* 54 M_IPMADDR */
169 SOX(ether_multi),
170 KMZ_LOOKUPZONE, /* 55 M_IFMADDR */
171 SOX(mrt), KMZ_CREATEZONE, /* 56 M_MRTABLE */
172 SOX(iso_mnt), KMZ_LOOKUPZONE, /* 57 M_ISOFSMNT */
173 SOS(iso_node), KMZ_CREATEZONE, /* 58 M_ISOFSNODE */
174 SOS(nfsrv_descript),
175 KMZ_CREATEZONE, /* 59 M_NFSRVDESC */
176 SOS(nfsdmap), KMZ_CREATEZONE, /* 60 M_NFSDIROFF */
177 SOS(fhandle), KMZ_LOOKUPZONE, /* 61 M_NFSBIGFH */
178 0, KMZ_MALLOC, /* 62 M_MSDOSFSMNT */
179 0, KMZ_MALLOC, /* 63 M_MSDOSFSFAT */
180 0, KMZ_MALLOC, /* 64 M_MSDOSFSNODE */
181 SOS(tty), KMZ_CREATEZONE, /* 65 M_TTYS */
182 0, KMZ_MALLOC, /* 66 M_EXEC */
183 0, KMZ_MALLOC, /* 67 M_MISCFSMNT */
184 0, KMZ_MALLOC, /* 68 M_MISCFSNODE */
185 0, KMZ_MALLOC, /* 69 M_ADOSFSMNT */
186 0, KMZ_MALLOC, /* 70 M_ADOSFSNODE */
187 0, KMZ_MALLOC, /* 71 M_ANODE */
188 SOX(buf), KMZ_CREATEZONE, /* 72 M_BUFHDR */
189 (NDFILE * OFILESIZE),
190 KMZ_CREATEZONE, /* 73 M_OFILETABL */
191 MCLBYTES, KMZ_CREATEZONE, /* 74 M_MCLUST */
192 SOX(hfsmount), KMZ_LOOKUPZONE, /* 75 M_HFSMNT */
193 SOS(hfsnode), KMZ_CREATEZONE, /* 76 M_HFSNODE */
194 SOS(hfsfilemeta), KMZ_CREATEZONE, /* 77 M_HFSFMETA */
195 SOX(volfs_mntdata), KMZ_LOOKUPZONE, /* 78 M_VOLFSMNT */
196 SOS(volfs_vndata), KMZ_CREATEZONE, /* 79 M_VOLFSNODE */
197 0, KMZ_MALLOC, /* 80 M_TEMP */
198 0, KMZ_MALLOC, /* 81 M_SECA */
199 0, KMZ_MALLOC, /* 82 M_DEVFS */
200 0, KMZ_MALLOC, /* 83 M_IPFW */
201 0, KMZ_MALLOC, /* 84 M_UDFNODE */
202 0, KMZ_MALLOC, /* 85 M_UDFMOUNT */
203 0, KMZ_MALLOC, /* 86 M_IP6NDP */
204 0, KMZ_MALLOC, /* 87 M_IP6OPT */
205 0, KMZ_MALLOC, /* 88 M_NATPT */
206
207 #undef SOS
208 #undef SOX
209 };
210
211
212 /*
213 * Initialize the kernel memory allocator
214 */
215 void
216 kmeminit(void)
217 {
218 struct kmzones *kmz;
219
220 kmz = kmzones;
221 while (kmz < &kmzones[M_LAST]) {
222 /* XXX */
223 if (kmz->kz_elemsize == -1)
224 ;
225 else
226 /* XXX */
227 if (kmz->kz_zalloczone == KMZ_CREATEZONE) {
228 kmz->kz_zalloczone = zinit(kmz->kz_elemsize,
229 1024 * 1024, PAGE_SIZE,
230 memname[kmz - kmzones]);
231 }
232 else if (kmz->kz_zalloczone == KMZ_LOOKUPZONE)
233 kmz->kz_zalloczone = kalloc_zone(kmz->kz_elemsize);
234
235 kmz++;
236 }
237
238 kmz = kmzones;
239 while (kmz < &kmzones[M_LAST]) {
240 /* XXX */
241 if (kmz->kz_elemsize == -1)
242 ;
243 else
244 /* XXX */
245 if (kmz->kz_zalloczone == KMZ_SHAREZONE) {
246 kmz->kz_zalloczone =
247 kmzones[kmz->kz_elemsize].kz_zalloczone;
248 kmz->kz_elemsize =
249 kmzones[kmz->kz_elemsize].kz_elemsize;
250 }
251
252 kmz++;
253 }
254 }
255
256 #define MDECL(reqlen) \
257 union { \
258 struct _mhead hdr; \
259 char _m[(reqlen) + sizeof (struct _mhead)]; \
260 }
261
262 struct _mhead {
263 size_t mlen;
264 char dat[0];
265 };
266
267 void *_MALLOC(
268 size_t size,
269 int type,
270 int flags)
271 {
272 MDECL(size) *mem;
273 size_t memsize = sizeof (*mem);
274
275 if (type >= M_LAST)
276 panic("_malloc TYPE");
277
278 if (size == 0)
279 return (0);
280
281 if (flags & M_NOWAIT) {
282 mem = (void *)kalloc_noblock(memsize);
283 } else {
284 mem = (void *)kalloc(memsize);
285 }
286 if (!mem)
287 return (0);
288
289 mem->hdr.mlen = memsize;
290
291 return (mem->hdr.dat);
292 }
293
294 void _FREE(
295 void *addr,
296 int type)
297 {
298 struct _mhead *hdr;
299
300 if (type >= M_LAST)
301 panic("_free TYPE");
302
303 if (!addr)
304 return;
305
306 hdr = addr; hdr--;
307 kfree((vm_offset_t)hdr, hdr->mlen);
308 }
309
310 void *_MALLOC_ZONE(
311 size_t size,
312 int type,
313 int flags)
314 {
315 struct kmzones *kmz;
316 void *elem;
317
318 if (type >= M_LAST)
319 panic("_malloc_zone TYPE");
320
321 kmz = &kmzones[type];
322 if (kmz->kz_zalloczone == KMZ_MALLOC)
323 panic("_malloc_zone ZONE");
324
325 /* XXX */
326 if (kmz->kz_elemsize == -1)
327 panic("_malloc_zone XXX");
328 /* XXX */
329 if (size == kmz->kz_elemsize)
330 if (flags & M_NOWAIT) {
331 elem = (void *)zalloc_noblock(kmz->kz_zalloczone);
332 } else {
333 elem = (void *)zalloc(kmz->kz_zalloczone);
334 }
335 else
336 if (flags & M_NOWAIT) {
337 elem = (void *)kalloc_noblock(size);
338 } else {
339 elem = (void *)kalloc(size);
340 }
341
342 return (elem);
343 }
344
345 void _FREE_ZONE(
346 void *elem,
347 size_t size,
348 int type)
349 {
350 struct kmzones *kmz;
351
352 if (type >= M_LAST)
353 panic("FREE_SIZE");
354
355 kmz = &kmzones[type];
356 if (kmz->kz_zalloczone == KMZ_MALLOC)
357 panic("free_zone ZONE");
358
359 /* XXX */
360 if (kmz->kz_elemsize == -1)
361 panic("FREE_SIZE XXX");
362 /* XXX */
363 if (size == kmz->kz_elemsize)
364 zfree(kmz->kz_zalloczone, (vm_offset_t)elem);
365 else
366 kfree((vm_offset_t)elem, size);
367 }