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