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