1 | /* $NetBSD: kern_malloc.c,v 1.145 2015/02/06 18:21:29 maxv Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 1987, 1991, 1993 |
5 | * The Regents of the University of California. All rights reserved. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions |
9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. |
15 | * 3. Neither the name of the University nor the names of its contributors |
16 | * may be used to endorse or promote products derived from this software |
17 | * without specific prior written permission. |
18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 | * SUCH DAMAGE. |
30 | * |
31 | * @(#)kern_malloc.c 8.4 (Berkeley) 5/20/95 |
32 | */ |
33 | |
34 | /* |
35 | * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. |
36 | * |
37 | * Redistribution and use in source and binary forms, with or without |
38 | * modification, are permitted provided that the following conditions |
39 | * are met: |
40 | * 1. Redistributions of source code must retain the above copyright |
41 | * notice, this list of conditions and the following disclaimer. |
42 | * 2. Redistributions in binary form must reproduce the above copyright |
43 | * notice, this list of conditions and the following disclaimer in the |
44 | * documentation and/or other materials provided with the distribution. |
45 | * 3. All advertising materials mentioning features or use of this software |
46 | * must display the following acknowledgement: |
47 | * This product includes software developed by the University of |
48 | * California, Berkeley and its contributors. |
49 | * 4. Neither the name of the University nor the names of its contributors |
50 | * may be used to endorse or promote products derived from this software |
51 | * without specific prior written permission. |
52 | * |
53 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
54 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
55 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
56 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
57 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
58 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
59 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
60 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
61 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
62 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
63 | * SUCH DAMAGE. |
64 | * |
65 | * @(#)kern_malloc.c 8.4 (Berkeley) 5/20/95 |
66 | */ |
67 | |
68 | /* |
69 | * Wrapper interface for obsolete malloc(9). |
70 | */ |
71 | |
72 | #include <sys/cdefs.h> |
73 | __KERNEL_RCSID(0, "$NetBSD: kern_malloc.c,v 1.145 2015/02/06 18:21:29 maxv Exp $" ); |
74 | |
75 | #include <sys/param.h> |
76 | #include <sys/malloc.h> |
77 | #include <sys/kmem.h> |
78 | |
79 | /* |
80 | * Built-in malloc types. Note: ought to be removed. |
81 | */ |
82 | MALLOC_DEFINE(M_DEVBUF, "devbuf" , "device driver memory" ); |
83 | MALLOC_DEFINE(M_DMAMAP, "DMA map" , "bus_dma(9) structures" ); |
84 | MALLOC_DEFINE(M_FREE, "free" , "should be on free list" ); |
85 | MALLOC_DEFINE(M_TEMP, "temp" , "misc. temporary data buffers" ); |
86 | MALLOC_DEFINE(M_RTABLE, "routetbl" , "routing tables" ); |
87 | MALLOC_DEFINE(M_FTABLE, "fragtbl" , "fragment reassembly header" ); |
88 | MALLOC_DEFINE(M_UFSMNT, "UFS mount" , "UFS mount structure" ); |
89 | MALLOC_DEFINE(M_NETADDR, "Export Host" , "Export host address structure" ); |
90 | MALLOC_DEFINE(M_MRTABLE, "mrt" , "multicast routing tables" ); |
91 | |
92 | /* |
93 | * Header contains total size, including the header itself. |
94 | */ |
95 | struct { |
96 | size_t ; |
97 | } __aligned(ALIGNBYTES + 1); |
98 | |
99 | void * |
100 | kern_malloc(unsigned long size, int flags) |
101 | { |
102 | const int kmflags = (flags & M_NOWAIT) ? KM_NOSLEEP : KM_SLEEP; |
103 | size_t allocsize, hdroffset; |
104 | struct malloc_header *mh; |
105 | void *p; |
106 | |
107 | if (size >= PAGE_SIZE) { |
108 | allocsize = PAGE_SIZE + size; /* for page alignment */ |
109 | hdroffset = PAGE_SIZE - sizeof(struct malloc_header); |
110 | } else { |
111 | allocsize = sizeof(struct malloc_header) + size; |
112 | hdroffset = 0; |
113 | } |
114 | |
115 | p = kmem_intr_alloc(allocsize, kmflags); |
116 | if (p == NULL) |
117 | return NULL; |
118 | |
119 | if ((flags & M_ZERO) != 0) { |
120 | memset(p, 0, allocsize); |
121 | } |
122 | mh = (void *)((char *)p + hdroffset); |
123 | mh->mh_size = allocsize - hdroffset; |
124 | |
125 | return mh + 1; |
126 | } |
127 | |
128 | void |
129 | kern_free(void *addr) |
130 | { |
131 | struct malloc_header *mh; |
132 | |
133 | mh = addr; |
134 | mh--; |
135 | |
136 | if (mh->mh_size >= PAGE_SIZE + sizeof(struct malloc_header)) |
137 | kmem_intr_free((char *)addr - PAGE_SIZE, |
138 | mh->mh_size + PAGE_SIZE - sizeof(struct malloc_header)); |
139 | else |
140 | kmem_intr_free(mh, mh->mh_size); |
141 | } |
142 | |
143 | void * |
144 | kern_realloc(void *curaddr, unsigned long newsize, int flags) |
145 | { |
146 | struct malloc_header *mh; |
147 | unsigned long cursize; |
148 | void *newaddr; |
149 | |
150 | /* |
151 | * realloc() with a NULL pointer is the same as malloc(). |
152 | */ |
153 | if (curaddr == NULL) |
154 | return malloc(newsize, ksp, flags); |
155 | |
156 | /* |
157 | * realloc() with zero size is the same as free(). |
158 | */ |
159 | if (newsize == 0) { |
160 | free(curaddr, ksp); |
161 | return NULL; |
162 | } |
163 | |
164 | if ((flags & M_NOWAIT) == 0) { |
165 | ASSERT_SLEEPABLE(); |
166 | } |
167 | |
168 | mh = curaddr; |
169 | mh--; |
170 | |
171 | cursize = mh->mh_size - sizeof(struct malloc_header); |
172 | |
173 | /* |
174 | * If we already actually have as much as they want, we're done. |
175 | */ |
176 | if (newsize <= cursize) |
177 | return curaddr; |
178 | |
179 | /* |
180 | * Can't satisfy the allocation with the existing block. |
181 | * Allocate a new one and copy the data. |
182 | */ |
183 | newaddr = malloc(newsize, ksp, flags); |
184 | if (__predict_false(newaddr == NULL)) { |
185 | /* |
186 | * malloc() failed, because flags included M_NOWAIT. |
187 | * Return NULL to indicate that failure. The old |
188 | * pointer is still valid. |
189 | */ |
190 | return NULL; |
191 | } |
192 | memcpy(newaddr, curaddr, cursize); |
193 | |
194 | /* |
195 | * We were successful: free the old allocation and return |
196 | * the new one. |
197 | */ |
198 | free(curaddr, ksp); |
199 | return newaddr; |
200 | } |
201 | |