diff options
author | tholo <> | 1996-09-26 04:19:42 +0000 |
---|---|---|
committer | tholo <> | 1996-09-26 04:19:42 +0000 |
commit | 40954213683da2af94f45d9b0f35806b54e5e306 (patch) | |
tree | 4d52bb67398acd4227bd70258a69403ba2acf910 /src/lib | |
parent | 7bfb6e73ddb58269b8ec906a008d5999e1b70abf (diff) | |
download | openbsd-40954213683da2af94f45d9b0f35806b54e5e306.tar.gz openbsd-40954213683da2af94f45d9b0f35806b54e5e306.tar.bz2 openbsd-40954213683da2af94f45d9b0f35806b54e5e306.zip |
Latest changes from FreeBSD
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libc/stdlib/malloc.3 | 118 | ||||
-rw-r--r-- | src/lib/libc/stdlib/malloc.c | 491 |
2 files changed, 381 insertions, 228 deletions
diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3 index 979e77016d..e206245cc2 100644 --- a/src/lib/libc/stdlib/malloc.3 +++ b/src/lib/libc/stdlib/malloc.3 | |||
@@ -33,11 +33,11 @@ | |||
33 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 33 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
34 | .\" SUCH DAMAGE. | 34 | .\" SUCH DAMAGE. |
35 | .\" | 35 | .\" |
36 | .\" $OpenBSD: malloc.3,v 1.3 1996/08/21 03:12:18 downsj Exp $ | 36 | .\" $OpenBSD: malloc.3,v 1.4 1996/09/26 04:19:41 tholo Exp $ |
37 | .\" | 37 | .\" |
38 | .Dd June 4, 1993 | 38 | .Dd August 27, 1996 |
39 | .Dt MALLOC 3 | 39 | .Dt MALLOC 3 |
40 | .Os BSD 4 | 40 | .Os OpenBSD |
41 | .Sh NAME | 41 | .Sh NAME |
42 | .Nm malloc , | 42 | .Nm malloc , |
43 | .Nd general memory allocation function | 43 | .Nd general memory allocation function |
@@ -58,6 +58,8 @@ | |||
58 | .Fn cfree "void *ptr" | 58 | .Fn cfree "void *ptr" |
59 | .Ft void * | 59 | .Ft void * |
60 | .Fn realloc "void *ptr" "size_t size" | 60 | .Fn realloc "void *ptr" "size_t size" |
61 | .Ft char * | ||
62 | .Va malloc_options | ||
61 | .Sh DESCRIPTION | 63 | .Sh DESCRIPTION |
62 | The | 64 | The |
63 | .Fn malloc | 65 | .Fn malloc |
@@ -120,11 +122,13 @@ is zero and | |||
120 | .Fa ptr | 122 | .Fa ptr |
121 | is not a null pointer, the object it points to is freed. | 123 | is not a null pointer, the object it points to is freed. |
122 | .Pp | 124 | .Pp |
123 | 125 | Malloc will first look for a symbolic link called | |
124 | .Sh ENVIRONMENT | 126 | .Pa /etc/malloc.conf |
125 | This malloc will check the environment for a variable called | 127 | and next check the environment for a variable called |
126 | .Em MALLOC_OPTIONS | 128 | .Ev MALLOC_OPTIONS |
127 | and scan it for flags. | 129 | and finally for the global variable |
130 | .Va malloc_options | ||
131 | and scan them for flags in that order. | ||
128 | Flags are single letters, uppercase means on, lowercase means off. | 132 | Flags are single letters, uppercase means on, lowercase means off. |
129 | .Bl -tag -width indent | 133 | .Bl -tag -width indent |
130 | .It A | 134 | .It A |
@@ -142,21 +146,42 @@ order to have any effect. | |||
142 | ``junk'' fill some junk into the area allocated. | 146 | ``junk'' fill some junk into the area allocated. |
143 | Currently junk is bytes of 0xd0, this is pronounced ``Duh'' :-) | 147 | Currently junk is bytes of 0xd0, this is pronounced ``Duh'' :-) |
144 | 148 | ||
149 | .It H | ||
150 | ``hint'' pass a hint to the kernel about pages we don't use. If the | ||
151 | machine is paging a lot this may help a bit. | ||
152 | |||
145 | .It R | 153 | .It R |
146 | ``realloc'' always reallocate when | 154 | ``realloc'' always reallocate when |
147 | .Fn realloc | 155 | .Fn realloc |
148 | is called, even if the initial allocation was big enough. | 156 | is called, even if the initial allocation was big enough. |
149 | This can substantially aid in compacting memory. | 157 | This can substantially aid in compacting memory. |
150 | 158 | ||
159 | .It U | ||
160 | ``utrace'' generate entries for ktrace(1) for all operations. | ||
161 | Consult the source for this one. | ||
162 | |||
151 | .It Z | 163 | .It Z |
152 | ``zero'' fill some junk into the area allocated (see ``J''), | 164 | ``zero'' fill some junk into the area allocated (see ``J''), |
153 | except for the exact length the user asked for, which is zeroed. | 165 | except for the exact length the user asked for, which is zeroed. |
154 | 166 | ||
167 | .It < | ||
168 | ``Half the cache size'' Reduce the size of the cache by a factor of two. | ||
169 | |||
170 | .It > | ||
171 | ``Double the cache size'' Double the size of the cache by a factor of two. | ||
155 | .El | 172 | .El |
156 | .Pp | 173 | .Pp |
174 | So to set a systemwide reduction of cache size and coredumps on problems | ||
175 | one would: | ||
176 | .Li ln -s 'A<' /etc/malloc.conf | ||
177 | .Pp | ||
157 | The ``J'' and ``Z'' is mostly for testing and debugging, | 178 | The ``J'' and ``Z'' is mostly for testing and debugging, |
158 | if a program changes behavior if either of these options are used, | 179 | if a program changes behavior if either of these options are used, |
159 | it is buggy. | 180 | it is buggy. |
181 | .Pp | ||
182 | The default cache size is 16 pages. | ||
183 | .Sh ENVIRONMENT | ||
184 | See above. | ||
160 | .Sh RETURN VALUES | 185 | .Sh RETURN VALUES |
161 | The | 186 | The |
162 | .Fn malloc | 187 | .Fn malloc |
@@ -172,12 +197,89 @@ The | |||
172 | .Fn realloc | 197 | .Fn realloc |
173 | function returns either a null pointer or a pointer | 198 | function returns either a null pointer or a pointer |
174 | to the possibly moved allocated space. | 199 | to the possibly moved allocated space. |
200 | .Sh MESSAGES | ||
201 | If | ||
202 | .Fn malloc , | ||
203 | .Fn free | ||
204 | or | ||
205 | .Fn realloc | ||
206 | detects an error or warning condition, | ||
207 | a message will be printed to filedescriptor | ||
208 | 2 (not using stdio). | ||
209 | Errors will always result in the process being | ||
210 | .Xr abort 2 'ed, | ||
211 | If the ``A'' option has been specified, also warnings will | ||
212 | .Xr abort 2 | ||
213 | the process. | ||
214 | .Pp | ||
215 | Here is a brief description of the error messages and what they mean: | ||
216 | .Pp | ||
217 | ``(ES): mumble mumble mumble'': | ||
218 | malloc have been compiled with -DEXTRA_SANITY and something looks | ||
219 | fishy in there. Consult sources and or wizards. | ||
220 | .Pp | ||
221 | ``allocation failed'' | ||
222 | if the ``A'' option is specified it is an error for | ||
223 | .Fn malloc | ||
224 | or | ||
225 | .Fn realloc | ||
226 | to return NULL. | ||
227 | .Pp | ||
228 | ``mmap(2) failed, check limits.'' | ||
229 | This is a rather weird condition that is most likely to mean that | ||
230 | the system is seriously overloaded or that your ulimits are sick. | ||
231 | .Pp | ||
232 | ``freelist is destroyed.'' | ||
233 | mallocs internal freelist has been stomped on. | ||
234 | .Pp | ||
235 | Here is a brief description of the warning messages and what they mean: | ||
236 | .Pp | ||
237 | ``chunk/page is already free.'' | ||
238 | A pointer to a free chunk is attempted freed again. | ||
239 | .Pp | ||
240 | ``junk pointer, too high to make sense.'' | ||
241 | The pointer doesn't make sense. It's above the area of memory that | ||
242 | malloc knows something about. | ||
243 | This could be a pointer from some | ||
244 | .Xr mmap 2 'ed | ||
245 | memory. | ||
246 | .Pp | ||
247 | ``junk pointer, too low to make sense.'' | ||
248 | The pointer doesn't make sense. It's below the area of memory that | ||
249 | malloc knows something about. | ||
250 | This pointer probably came from your data or bss segments. | ||
251 | .Pp | ||
252 | ``malloc() has never been called.'' | ||
253 | Nothing has ever been allocated, yet something is being freed or | ||
254 | realloc'ed. | ||
255 | .Pp | ||
256 | ``modified (chunk-/page-) pointer.'' | ||
257 | The pointer passed to free or realloc has been modified. | ||
258 | .Pp | ||
259 | ``pointer to wrong page.'' | ||
260 | The pointer that malloc is trying to free is not pointing to | ||
261 | a sensible page. | ||
262 | .Pp | ||
263 | ``recursive call.'' | ||
264 | You have tried to call recursively into these functions. | ||
265 | I can only imagine this as happening if you call one of these | ||
266 | functions from a signal function, which happens to be called | ||
267 | while you're already in here. | ||
268 | Well, sorry to say: that's not supported. | ||
269 | If this is a problem for you I'd like to hear about it. It | ||
270 | would be possible to add a sigblock() around this package, | ||
271 | but it would have a performance penalty that is not acceptable | ||
272 | as the default. | ||
273 | .Pp | ||
274 | ``unknown char in MALLOC_OPTIONS'' | ||
275 | we found something we didn't understand. | ||
175 | .Sh SEE ALSO | 276 | .Sh SEE ALSO |
176 | .Xr brk 2 , | 277 | .Xr brk 2 , |
177 | .Xr alloca 3 , | 278 | .Xr alloca 3 , |
178 | .Xr calloc 3 , | 279 | .Xr calloc 3 , |
179 | .Xr getpagesize 3 , | 280 | .Xr getpagesize 3 , |
180 | .Xr memory 3 | 281 | .Xr memory 3 |
282 | .Pa /usr/share/doc/papers/malloc.ascii.gz | ||
181 | .Sh STANDARDS | 283 | .Sh STANDARDS |
182 | The | 284 | The |
183 | .Fn malloc | 285 | .Fn malloc |
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index bff70c7b54..a6f60b3fe3 100644 --- a/src/lib/libc/stdlib/malloc.c +++ b/src/lib/libc/stdlib/malloc.c | |||
@@ -8,12 +8,15 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #if defined(LIBC_SCCS) && !defined(lint) | 10 | #if defined(LIBC_SCCS) && !defined(lint) |
11 | static char rcsid[] = "$OpenBSD: malloc.c,v 1.13 1996/09/19 20:38:48 tholo Exp $"; | 11 | static char rcsid[] = "$OpenBSD: malloc.c,v 1.14 1996/09/26 04:19:42 tholo Exp $"; |
12 | #endif /* LIBC_SCCS and not lint */ | 12 | #endif /* LIBC_SCCS and not lint */ |
13 | 13 | ||
14 | /* | 14 | /* |
15 | * Defining EXTRA_SANITY will enable some checks which are related | 15 | * Defining EXTRA_SANITY will enable extra checks which are related |
16 | * to internal conditions and consistency in malloc.c | 16 | * to internal conditions and consistency in malloc.c. This has a |
17 | * noticeable runtime performance hit, and generally will not do you | ||
18 | * any good unless you fiddle with the internals of malloc or want | ||
19 | * to catch random pointer corruption as early as possible. | ||
17 | */ | 20 | */ |
18 | #undef EXTRA_SANITY | 21 | #undef EXTRA_SANITY |
19 | 22 | ||
@@ -29,23 +32,23 @@ static char rcsid[] = "$OpenBSD: malloc.c,v 1.13 1996/09/19 20:38:48 tholo Exp $ | |||
29 | #endif | 32 | #endif |
30 | 33 | ||
31 | /* | 34 | /* |
32 | * What to use for Junk | 35 | * What to use for Junk. This is the byte value we use to fill with |
36 | * when the 'J' option is enabled. | ||
33 | */ | 37 | */ |
34 | #define SOME_JUNK 0xd0 /* as in "Duh" :-) */ | 38 | #define SOME_JUNK 0xd0 /* as in "Duh" :-) */ |
35 | 39 | ||
40 | /* | ||
41 | * No user serviceable parts behind this point. | ||
42 | */ | ||
43 | |||
36 | #include <stdio.h> | 44 | #include <stdio.h> |
37 | #include <stdlib.h> | 45 | #include <stdlib.h> |
46 | #include <string.h> | ||
38 | #include <unistd.h> | 47 | #include <unistd.h> |
39 | #include <memory.h> | ||
40 | #include <errno.h> | 48 | #include <errno.h> |
41 | #include <err.h> | ||
42 | #include <sys/types.h> | 49 | #include <sys/types.h> |
43 | #include <sys/param.h> | 50 | #include <sys/param.h> |
44 | #include <sys/mman.h> | 51 | #include <sys/mman.h> |
45 | #ifdef _THREAD_SAFE | ||
46 | #include <pthread.h> | ||
47 | #include "pthread_private.h" | ||
48 | #endif | ||
49 | 52 | ||
50 | /* | 53 | /* |
51 | * If these weren't defined here, they would be calculated on the fly, | 54 | * If these weren't defined here, they would be calculated on the fly, |
@@ -108,14 +111,14 @@ struct pgfree { | |||
108 | * We might as well use them. There are C-language backups, but | 111 | * We might as well use them. There are C-language backups, but |
109 | * they are considerably slower. | 112 | * they are considerably slower. |
110 | */ | 113 | */ |
111 | #ifdef __i386__ | 114 | #if defined(__i386__) && defined(__GNUC__) |
112 | #define ffs _ffs | 115 | #define ffs _ffs |
113 | static __inline int | 116 | static __inline int |
114 | _ffs(input) | 117 | _ffs(input) |
115 | unsigned input; | 118 | unsigned input; |
116 | { | 119 | { |
117 | int result; | 120 | int result; |
118 | __asm("bsfl %1,%0" : "=r" (result) : "r" (input)); | 121 | __asm("bsfl %1, %0" : "=r" (result) : "r" (input)); |
119 | return result+1; | 122 | return result+1; |
120 | } | 123 | } |
121 | 124 | ||
@@ -125,7 +128,7 @@ _fls(input) | |||
125 | unsigned input; | 128 | unsigned input; |
126 | { | 129 | { |
127 | int result; | 130 | int result; |
128 | __asm("bsrl %1,%0" : "=r" (result) : "r" (input)); | 131 | __asm("bsrl %1, %0" : "=r" (result) : "r" (input)); |
129 | return result+1; | 132 | return result+1; |
130 | } | 133 | } |
131 | 134 | ||
@@ -135,7 +138,7 @@ _set_bit(pi, bit) | |||
135 | struct pginfo *pi; | 138 | struct pginfo *pi; |
136 | int bit; | 139 | int bit; |
137 | { | 140 | { |
138 | __asm("btsl %0,(%1)" : | 141 | __asm("btsl %0, (%1)" : |
139 | : "r" (bit & (MALLOC_BITS-1)), "r" (pi->bits+(bit/MALLOC_BITS))); | 142 | : "r" (bit & (MALLOC_BITS-1)), "r" (pi->bits+(bit/MALLOC_BITS))); |
140 | } | 143 | } |
141 | 144 | ||
@@ -145,11 +148,11 @@ _clr_bit(pi, bit) | |||
145 | struct pginfo *pi; | 148 | struct pginfo *pi; |
146 | int bit; | 149 | int bit; |
147 | { | 150 | { |
148 | __asm("btcl %0,(%1)" : | 151 | __asm("btcl %0, (%1)" : |
149 | : "r" (bit & (MALLOC_BITS-1)), "r" (pi->bits+(bit/MALLOC_BITS))); | 152 | : "r" (bit & (MALLOC_BITS-1)), "r" (pi->bits+(bit/MALLOC_BITS))); |
150 | } | 153 | } |
151 | 154 | ||
152 | #endif /* __i386__ */ | 155 | #endif /* __i386__ && __GNUC__ */ |
153 | 156 | ||
154 | /* | 157 | /* |
155 | * Set to one when malloc_init has been called | 158 | * Set to one when malloc_init has been called |
@@ -165,17 +168,13 @@ static unsigned initialized; | |||
165 | static unsigned malloc_pagesize; | 168 | static unsigned malloc_pagesize; |
166 | #endif /* malloc_pagesize */ | 169 | #endif /* malloc_pagesize */ |
167 | 170 | ||
168 | /* | 171 | /* A mask for the offset inside a page. */ |
169 | * A mask for the offset inside a page. | ||
170 | */ | ||
171 | #define malloc_pagemask ((malloc_pagesize)-1) | 172 | #define malloc_pagemask ((malloc_pagesize)-1) |
172 | 173 | ||
173 | #define pageround(foo) (((foo) + (malloc_pagemask))&(~(malloc_pagemask))) | 174 | #define pageround(foo) (((foo) + (malloc_pagemask))&(~(malloc_pagemask))) |
174 | #define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)-malloc_origo) | 175 | #define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)-malloc_origo) |
175 | 176 | ||
176 | /* | 177 | /* malloc_pagesize == 1 << malloc_pageshift */ |
177 | * malloc_pagesize == 1 << malloc_pageshift | ||
178 | */ | ||
179 | #ifndef malloc_pageshift | 178 | #ifndef malloc_pageshift |
180 | static unsigned malloc_pageshift; | 179 | static unsigned malloc_pageshift; |
181 | #endif /* malloc_pageshift */ | 180 | #endif /* malloc_pageshift */ |
@@ -197,85 +196,78 @@ static unsigned malloc_minsize; | |||
197 | static unsigned malloc_maxsize; | 196 | static unsigned malloc_maxsize; |
198 | #endif /* malloc_maxsize */ | 197 | #endif /* malloc_maxsize */ |
199 | 198 | ||
200 | /* | 199 | /* The minimum size (in pages) of the free page cache. */ |
201 | * The minimum size (in bytes) of the free page cache. | 200 | static unsigned malloc_cache = 16; |
202 | */ | ||
203 | #ifndef malloc_cache | ||
204 | static unsigned malloc_cache; | ||
205 | #endif /* malloc_cache */ | ||
206 | 201 | ||
207 | /* | 202 | /* The offset from pagenumber to index into the page directory */ |
208 | * The offset from pagenumber to index into the page directory | ||
209 | */ | ||
210 | static u_long malloc_origo; | 203 | static u_long malloc_origo; |
211 | 204 | ||
212 | /* | 205 | /* The last index in the page directory we care about */ |
213 | * The last index in the page directory we care about | ||
214 | */ | ||
215 | static u_long last_index; | 206 | static u_long last_index; |
216 | 207 | ||
217 | /* | 208 | /* Pointer to page directory. Allocated "as if with" malloc */ |
218 | * Pointer to page directory. | ||
219 | * Allocated "as if with" malloc | ||
220 | */ | ||
221 | static struct pginfo **page_dir; | 209 | static struct pginfo **page_dir; |
222 | 210 | ||
223 | /* | 211 | /* How many slots in the page directory */ |
224 | * How many slots in the page directory | ||
225 | */ | ||
226 | static unsigned malloc_ninfo; | 212 | static unsigned malloc_ninfo; |
227 | 213 | ||
228 | /* | 214 | /* Free pages line up here */ |
229 | * Free pages line up here | ||
230 | */ | ||
231 | static struct pgfree free_list; | 215 | static struct pgfree free_list; |
232 | 216 | ||
233 | /* | 217 | /* Abort(), user doesn't handle problems. */ |
234 | * Abort() if we fail to get VM ? | ||
235 | */ | ||
236 | static int malloc_abort; | 218 | static int malloc_abort; |
237 | 219 | ||
238 | /* | 220 | /* Are we trying to die ? */ |
239 | * Are we trying to die ? | ||
240 | */ | ||
241 | static int suicide; | 221 | static int suicide; |
242 | 222 | ||
243 | #ifdef MALLOC_STATS | 223 | #ifdef MALLOC_STATS |
244 | /* | 224 | /* dump statistics */ |
245 | * dump statistics | ||
246 | */ | ||
247 | static int malloc_stats; | 225 | static int malloc_stats; |
248 | #endif /* MALLOC_STATS */ | 226 | #endif /* MALLOC_STATS */ |
249 | 227 | ||
250 | /* | 228 | /* always realloc ? */ |
251 | * always realloc ? | ||
252 | */ | ||
253 | static int malloc_realloc; | 229 | static int malloc_realloc; |
254 | 230 | ||
255 | /* | 231 | #ifdef __FreeBSD__ |
256 | * zero fill ? | 232 | /* pass the kernel a hint on free pages ? */ |
257 | */ | 233 | static int malloc_hint; |
234 | #endif | ||
235 | |||
236 | /* zero fill ? */ | ||
258 | static int malloc_zero; | 237 | static int malloc_zero; |
259 | 238 | ||
260 | /* | 239 | /* junk fill ? */ |
261 | * junk fill ? | ||
262 | */ | ||
263 | static int malloc_junk; | 240 | static int malloc_junk; |
264 | 241 | ||
265 | /* | 242 | #ifdef __FreeBSD__ |
266 | * my last break. | 243 | /* utrace ? */ |
267 | */ | 244 | static int malloc_utrace; |
245 | |||
246 | struct ut { void *p; size_t s; void *r; }; | ||
247 | |||
248 | #define UTRACE(a, b, c) \ | ||
249 | if (malloc_utrace) \ | ||
250 | {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);} | ||
251 | #else /* !__FreeBSD__ */ | ||
252 | #define UTRACE(a,b,c) | ||
253 | #endif | ||
254 | |||
255 | /* my last break. */ | ||
268 | static void *malloc_brk; | 256 | static void *malloc_brk; |
269 | 257 | ||
270 | /* | 258 | /* one location cache for free-list holders */ |
271 | * one location cache for free-list holders | ||
272 | */ | ||
273 | static struct pgfree *px; | 259 | static struct pgfree *px; |
274 | 260 | ||
261 | /* compile-time options */ | ||
262 | char *malloc_options; | ||
263 | |||
275 | /* | 264 | /* |
276 | * Necessary function declarations | 265 | * Necessary function declarations |
277 | */ | 266 | */ |
278 | static int extend_pgdir(u_long index); | 267 | static int extend_pgdir(u_long index); |
268 | static void *imalloc(size_t size); | ||
269 | static void ifree(void *ptr); | ||
270 | static void *irealloc(void *ptr, size_t size); | ||
279 | 271 | ||
280 | #ifdef MALLOC_STATS | 272 | #ifdef MALLOC_STATS |
281 | void | 273 | void |
@@ -290,60 +282,63 @@ malloc_dump(fd) | |||
290 | 282 | ||
291 | /* print out all the pages */ | 283 | /* print out all the pages */ |
292 | for(j=0;j<=last_index;j++) { | 284 | for(j=0;j<=last_index;j++) { |
293 | fprintf(fd,"%08lx %5d ",(j+malloc_origo) << malloc_pageshift,j); | 285 | fprintf(fd, "%08lx %5d ", (j+malloc_origo) << malloc_pageshift, j); |
294 | if (pd[j] == MALLOC_NOT_MINE) { | 286 | if (pd[j] == MALLOC_NOT_MINE) { |
295 | for(j++;j<=last_index && pd[j] == MALLOC_NOT_MINE;j++) | 287 | for(j++;j<=last_index && pd[j] == MALLOC_NOT_MINE;j++) |
296 | ; | 288 | ; |
297 | j--; | 289 | j--; |
298 | fprintf(fd,".. %5d not mine\n", j); | 290 | fprintf(fd, ".. %5d not mine\n", j); |
299 | } else if (pd[j] == MALLOC_FREE) { | 291 | } else if (pd[j] == MALLOC_FREE) { |
300 | for(j++;j<=last_index && pd[j] == MALLOC_FREE;j++) | 292 | for(j++;j<=last_index && pd[j] == MALLOC_FREE;j++) |
301 | ; | 293 | ; |
302 | j--; | 294 | j--; |
303 | fprintf(fd,".. %5d free\n", j); | 295 | fprintf(fd, ".. %5d free\n", j); |
304 | } else if (pd[j] == MALLOC_FIRST) { | 296 | } else if (pd[j] == MALLOC_FIRST) { |
305 | for(j++;j<=last_index && pd[j] == MALLOC_FOLLOW;j++) | 297 | for(j++;j<=last_index && pd[j] == MALLOC_FOLLOW;j++) |
306 | ; | 298 | ; |
307 | j--; | 299 | j--; |
308 | fprintf(fd,".. %5d in use\n", j); | 300 | fprintf(fd, ".. %5d in use\n", j); |
309 | } else if (pd[j] < MALLOC_MAGIC) { | 301 | } else if (pd[j] < MALLOC_MAGIC) { |
310 | fprintf(fd,"(%p)\n", pd[j]); | 302 | fprintf(fd, "(%p)\n", pd[j]); |
311 | } else { | 303 | } else { |
312 | fprintf(fd,"%p %d (of %d) x %d @ %p --> %p\n", | 304 | fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n", |
313 | pd[j],pd[j]->free, pd[j]->total, | 305 | pd[j], pd[j]->free, pd[j]->total, |
314 | pd[j]->size, pd[j]->page, pd[j]->next); | 306 | pd[j]->size, pd[j]->page, pd[j]->next); |
315 | } | 307 | } |
316 | } | 308 | } |
317 | 309 | ||
318 | for(pf=free_list.next; pf; pf=pf->next) { | 310 | for(pf=free_list.next; pf; pf=pf->next) { |
319 | fprintf(fd,"Free: @%p [%p...%p[ %ld ->%p <-%p\n", | 311 | fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n", |
320 | pf,pf->page,pf->end,pf->size,pf->prev,pf->next); | 312 | pf, pf->page, pf->end, pf->size, pf->prev, pf->next); |
321 | if (pf == pf->next) { | 313 | if (pf == pf->next) { |
322 | fprintf(fd,"Free_list loops.\n"); | 314 | + fprintf(fd, "Free_list loops.\n"); |
323 | break; | 315 | break; |
324 | } | 316 | } |
325 | } | 317 | } |
326 | 318 | ||
327 | /* print out various info */ | 319 | /* print out various info */ |
328 | fprintf(fd,"Minsize\t%d\n",malloc_minsize); | 320 | fprintf(fd, "Minsize\t%d\n", malloc_minsize); |
329 | fprintf(fd,"Maxsize\t%d\n",malloc_maxsize); | 321 | fprintf(fd, "Maxsize\t%d\n", malloc_maxsize); |
330 | fprintf(fd,"Pagesize\t%d\n",malloc_pagesize); | 322 | fprintf(fd, "Pagesize\t%d\n", malloc_pagesize); |
331 | fprintf(fd,"Pageshift\t%d\n",malloc_pageshift); | 323 | fprintf(fd, "Pageshift\t%d\n", malloc_pageshift); |
332 | fprintf(fd,"FirstPage\t%ld\n",malloc_origo); | 324 | fprintf(fd, "FirstPage\t%ld\n", malloc_origo); |
333 | fprintf(fd,"LastPage\t%ld %lx\n",last_index+malloc_pageshift, | 325 | fprintf(fd, "LastPage\t%ld %lx\n", last_index+malloc_pageshift, |
334 | (last_index + malloc_pageshift) << malloc_pageshift); | 326 | (last_index + malloc_pageshift) << malloc_pageshift); |
335 | fprintf(fd,"Break\t%ld\n",(u_long)sbrk(0) >> malloc_pageshift); | 327 | fprintf(fd, "Break\t%ld\n", (u_long)sbrk(0) >> malloc_pageshift); |
336 | } | 328 | } |
337 | #endif /* MALLOC_STATS */ | 329 | #endif /* MALLOC_STATS */ |
338 | 330 | ||
331 | static char *malloc_func; | ||
332 | |||
339 | static void | 333 | static void |
340 | wrterror(p) | 334 | wrterror(p) |
341 | char *p; | 335 | char *p; |
342 | { | 336 | { |
343 | char *q = "Malloc error: "; | 337 | char *q = "Malloc error: "; |
344 | suicide = 1; | 338 | suicide = 1; |
345 | write(2,q,strlen(q)); | 339 | write(2, q, strlen(q)); |
346 | write(2,p,strlen(p)); | 340 | write(2, malloc_func, strlen(malloc_func)); |
341 | write(2, p, strlen(p)); | ||
347 | #ifdef MALLOC_STATS | 342 | #ifdef MALLOC_STATS |
348 | if (malloc_stats) | 343 | if (malloc_stats) |
349 | malloc_dump(stderr); | 344 | malloc_dump(stderr); |
@@ -358,21 +353,22 @@ wrtwarning(p) | |||
358 | char *q = "Malloc warning: "; | 353 | char *q = "Malloc warning: "; |
359 | if (malloc_abort) | 354 | if (malloc_abort) |
360 | wrterror(p); | 355 | wrterror(p); |
361 | write(2,q,strlen(q)); | 356 | write(2, q, strlen(q)); |
362 | write(2,p,strlen(p)); | 357 | write(2, malloc_func, strlen(malloc_func)); |
358 | write(2, p, strlen(p)); | ||
363 | } | 359 | } |
364 | 360 | ||
365 | #ifdef EXTRA_SANITY | 361 | #ifdef EXTRA_SANITY |
366 | static void | 362 | static void |
367 | malloc_exit() | 363 | malloc_exit() |
368 | { | 364 | { |
369 | FILE *fd = fopen("malloc.out","a"); | 365 | FILE *fd = fopen("malloc.out", "a"); |
370 | char *q = "malloc() warning: Couldn't dump stats.\n"; | 366 | char *q = "malloc() warning: Couldn't dump stats.\n"; |
371 | if (fd) { | 367 | if (fd) { |
372 | malloc_dump(fd); | 368 | malloc_dump(fd); |
373 | fclose(fd); | 369 | fclose(fd); |
374 | } else | 370 | } else |
375 | write(2,q,strlen(q)); | 371 | write(2, q, strlen(q)); |
376 | } | 372 | } |
377 | #endif /* EXTRA_SANITY */ | 373 | #endif /* EXTRA_SANITY */ |
378 | 374 | ||
@@ -384,14 +380,14 @@ static caddr_t | |||
384 | map_pages(pages) | 380 | map_pages(pages) |
385 | int pages; | 381 | int pages; |
386 | { | 382 | { |
387 | caddr_t result,tail; | 383 | caddr_t result, tail; |
388 | 384 | ||
389 | result = (caddr_t)pageround((u_long)sbrk(0)); | 385 | result = (caddr_t)pageround((u_long)sbrk(0)); |
390 | tail = result + (pages << malloc_pageshift); | 386 | tail = result + (pages << malloc_pageshift); |
391 | 387 | ||
392 | if (brk(tail)) { | 388 | if (brk(tail)) { |
393 | #ifdef EXTRA_SANITY | 389 | #ifdef EXTRA_SANITY |
394 | wrterror("(internal): map_pages fails\n"); | 390 | wrterror("(ES): map_pages fails\n"); |
395 | #endif /* EXTRA_SANITY */ | 391 | #endif /* EXTRA_SANITY */ |
396 | return 0; | 392 | return 0; |
397 | } | 393 | } |
@@ -466,7 +462,7 @@ static int | |||
466 | extend_pgdir(index) | 462 | extend_pgdir(index) |
467 | u_long index; | 463 | u_long index; |
468 | { | 464 | { |
469 | struct pginfo **new,**old; | 465 | struct pginfo **new, **old; |
470 | int i, oldlen; | 466 | int i, oldlen; |
471 | 467 | ||
472 | /* Make it this many pages */ | 468 | /* Make it this many pages */ |
@@ -520,35 +516,61 @@ extend_pgdir(index) | |||
520 | static void | 516 | static void |
521 | malloc_init () | 517 | malloc_init () |
522 | { | 518 | { |
523 | char *p; | 519 | char *p, b[64]; |
520 | int i, j; | ||
524 | 521 | ||
525 | #ifdef EXTRA_SANITY | 522 | #ifdef EXTRA_SANITY |
526 | malloc_junk = 1; | 523 | malloc_junk = 1; |
527 | #endif /* EXTRA_SANITY */ | 524 | #endif /* EXTRA_SANITY */ |
528 | 525 | ||
529 | if (issetugid() == 0) { | 526 | for (i = 0; i < 3; i++) { |
530 | for (p=getenv("MALLOC_OPTIONS"); p && *p; p++) { | 527 | if (i == 0) { |
528 | j = readlink("/etc/malloc.conf", b, sizeof b - 1); | ||
529 | if (j <= 0) | ||
530 | continue; | ||
531 | b[j] = '\0'; | ||
532 | p = b; | ||
533 | } else if (i == 1) { | ||
534 | p = getenv("MALLOC_OPTIONS"); | ||
535 | } else if (i == 2) { | ||
536 | p = malloc_options; | ||
537 | } | ||
538 | for (; p && *p; p++) { | ||
531 | switch (*p) { | 539 | switch (*p) { |
532 | case 'a': malloc_abort = 0; break; | 540 | case '>': malloc_cache <<= 1; break; |
533 | case 'A': malloc_abort = 1; break; | 541 | case '<': malloc_cache >>= 1; break; |
542 | case 'a': malloc_abort = 0; break; | ||
543 | case 'A': malloc_abort = 1; break; | ||
534 | #ifdef MALLOC_STATS | 544 | #ifdef MALLOC_STATS |
535 | case 'd': malloc_stats = 0; break; | 545 | case 'd': malloc_stats = 0; break; |
536 | case 'D': malloc_stats = 1; break; | 546 | case 'D': malloc_stats = 1; break; |
537 | #endif /* MALLOC_STATS */ | 547 | #endif /* MALLOC_STATS */ |
538 | case 'r': malloc_realloc = 0; break; | 548 | #ifdef __FreeBSD__ |
539 | case 'R': malloc_realloc = 1; break; | 549 | case 'h': malloc_hint = 0; break; |
540 | case 'j': malloc_junk = 0; break; | 550 | case 'H': malloc_hint = 1; break; |
541 | case 'J': malloc_junk = 1; break; | 551 | #endif /* __FreeBSD__ */ |
542 | case 'z': malloc_zero = 0; break; | 552 | case 'r': malloc_realloc = 0; break; |
543 | case 'Z': malloc_zero = 1; break; | 553 | case 'R': malloc_realloc = 1; break; |
544 | default: | 554 | case 'j': malloc_junk = 0; break; |
545 | wrtwarning("(Init): Unknown char in MALLOC_OPTIONS\n"); | 555 | case 'J': malloc_junk = 1; break; |
546 | p = 0; | 556 | #ifdef __FreeBSD__ |
547 | break; | 557 | case 'u': malloc_utrace = 0; break; |
558 | case 'U': malloc_utrace = 1; break; | ||
559 | #endif /* __FreeBSD__ */ | ||
560 | case 'z': malloc_zero = 0; break; | ||
561 | case 'Z': malloc_zero = 1; break; | ||
562 | default: | ||
563 | j = malloc_abort; | ||
564 | malloc_abort = 0; | ||
565 | wrtwarning("unknown char in MALLOC_OPTIONS\n"); | ||
566 | malloc_abort = j; | ||
567 | break; | ||
548 | } | 568 | } |
549 | } | 569 | } |
550 | } | 570 | } |
551 | 571 | ||
572 | UTRACE(0, 0, 0); | ||
573 | |||
552 | /* | 574 | /* |
553 | * We want junk in the entire allocation, and zero only in the part | 575 | * We want junk in the entire allocation, and zero only in the part |
554 | * the user asked for. | 576 | * the user asked for. |
@@ -579,10 +601,6 @@ malloc_init () | |||
579 | } | 601 | } |
580 | #endif /* malloc_pageshift */ | 602 | #endif /* malloc_pageshift */ |
581 | 603 | ||
582 | #ifndef malloc_cache | ||
583 | malloc_cache = 100 << malloc_pageshift; | ||
584 | #endif /* malloc_cache */ | ||
585 | |||
586 | #ifndef malloc_minsize | 604 | #ifndef malloc_minsize |
587 | { | 605 | { |
588 | int i; | 606 | int i; |
@@ -612,7 +630,7 @@ malloc_init () | |||
612 | page_dir = (struct pginfo **) mmap(0, malloc_pagesize, PROT_READ|PROT_WRITE, | 630 | page_dir = (struct pginfo **) mmap(0, malloc_pagesize, PROT_READ|PROT_WRITE, |
613 | MAP_ANON|MAP_PRIVATE, -1, (off_t)0); | 631 | MAP_ANON|MAP_PRIVATE, -1, (off_t)0); |
614 | if (page_dir == (struct pginfo **) -1) | 632 | if (page_dir == (struct pginfo **) -1) |
615 | wrterror("(Init) my first mmap failed. (check limits ?)\n"); | 633 | wrterror("mmap(2) failed, check limits.\n"); |
616 | 634 | ||
617 | /* | 635 | /* |
618 | * We need a maximum of malloc_pageshift buckets, steal these from the | 636 | * We need a maximum of malloc_pageshift buckets, steal these from the |
@@ -630,7 +648,12 @@ malloc_init () | |||
630 | * This is a nice hack from Kaleb Keithly (kaleb@x.org). | 648 | * This is a nice hack from Kaleb Keithly (kaleb@x.org). |
631 | * We can sbrk(2) further back when we keep this on a low address. | 649 | * We can sbrk(2) further back when we keep this on a low address. |
632 | */ | 650 | */ |
633 | px = (struct pgfree *) malloc (sizeof *px); | 651 | px = (struct pgfree *) imalloc (sizeof *px); |
652 | |||
653 | if (!malloc_cache) | ||
654 | malloc_cache++; | ||
655 | |||
656 | malloc_cache <<= malloc_pageshift; | ||
634 | } | 657 | } |
635 | 658 | ||
636 | /* | 659 | /* |
@@ -640,7 +663,7 @@ void * | |||
640 | malloc_pages(size) | 663 | malloc_pages(size) |
641 | size_t size; | 664 | size_t size; |
642 | { | 665 | { |
643 | void *p,*delay_free = 0; | 666 | void *p, *delay_free = 0; |
644 | int i; | 667 | int i; |
645 | struct pgfree *pf; | 668 | struct pgfree *pf; |
646 | u_long index; | 669 | u_long index; |
@@ -705,14 +728,14 @@ malloc_pages(size) | |||
705 | page_dir[index+i] = MALLOC_FOLLOW; | 728 | page_dir[index+i] = MALLOC_FOLLOW; |
706 | 729 | ||
707 | if (malloc_junk) | 730 | if (malloc_junk) |
708 | memset(p, SOME_JUNK,size << malloc_pageshift); | 731 | memset(p, SOME_JUNK, size << malloc_pageshift); |
709 | } | 732 | } |
710 | 733 | ||
711 | if (delay_free) { | 734 | if (delay_free) { |
712 | if (!px) | 735 | if (!px) |
713 | px = delay_free; | 736 | px = delay_free; |
714 | else | 737 | else |
715 | free(delay_free); | 738 | ifree(delay_free); |
716 | } | 739 | } |
717 | 740 | ||
718 | return p; | 741 | return p; |
@@ -728,7 +751,7 @@ malloc_make_chunks(bits) | |||
728 | { | 751 | { |
729 | struct pginfo *bp; | 752 | struct pginfo *bp; |
730 | void *pp; | 753 | void *pp; |
731 | int i,k,l; | 754 | int i, k, l; |
732 | 755 | ||
733 | /* Allocate a new bucket */ | 756 | /* Allocate a new bucket */ |
734 | pp = malloc_pages(malloc_pagesize); | 757 | pp = malloc_pages(malloc_pagesize); |
@@ -744,7 +767,7 @@ malloc_make_chunks(bits) | |||
744 | if ((1<<(bits)) <= l+l) { | 767 | if ((1<<(bits)) <= l+l) { |
745 | bp = (struct pginfo *)pp; | 768 | bp = (struct pginfo *)pp; |
746 | } else { | 769 | } else { |
747 | bp = (struct pginfo *)malloc(l); | 770 | bp = (struct pginfo *)imalloc(l); |
748 | if (!bp) | 771 | if (!bp) |
749 | return 0; | 772 | return 0; |
750 | } | 773 | } |
@@ -768,12 +791,12 @@ malloc_make_chunks(bits) | |||
768 | bp->bits[i / MALLOC_BITS] = (u_long)~0; | 791 | bp->bits[i / MALLOC_BITS] = (u_long)~0; |
769 | 792 | ||
770 | for(; i < k; i++) | 793 | for(; i < k; i++) |
771 | set_bit(bp,i); | 794 | set_bit(bp, i); |
772 | 795 | ||
773 | if (bp == bp->page) { | 796 | if (bp == bp->page) { |
774 | /* Mark the ones we stole for ourselves */ | 797 | /* Mark the ones we stole for ourselves */ |
775 | for(i=0;l > 0;i++) { | 798 | for(i=0;l > 0;i++) { |
776 | clr_bit(bp,i); | 799 | clr_bit(bp, i); |
777 | bp->free--; | 800 | bp->free--; |
778 | bp->total--; | 801 | bp->total--; |
779 | l -= (1 << bits); | 802 | l -= (1 << bits); |
@@ -835,8 +858,8 @@ malloc_bytes(size) | |||
835 | /* | 858 | /* |
836 | * Allocate a piece of memory | 859 | * Allocate a piece of memory |
837 | */ | 860 | */ |
838 | void * | 861 | static void * |
839 | malloc(size) | 862 | imalloc(size) |
840 | size_t size; | 863 | size_t size; |
841 | { | 864 | { |
842 | void *result; | 865 | void *result; |
@@ -850,36 +873,30 @@ malloc(size) | |||
850 | if (suicide) | 873 | if (suicide) |
851 | abort(); | 874 | abort(); |
852 | 875 | ||
853 | #ifdef _THREAD_SAFE | ||
854 | _thread_kern_sig_block(&status); | ||
855 | #endif | ||
856 | if (size <= malloc_maxsize) | 876 | if (size <= malloc_maxsize) |
857 | result = malloc_bytes(size); | 877 | result = malloc_bytes(size); |
858 | else | 878 | else |
859 | result = malloc_pages(size); | 879 | result = malloc_pages(size); |
860 | 880 | ||
861 | if (malloc_abort && !result) | 881 | if (malloc_abort && !result) |
862 | wrterror("malloc(): returns NULL\n"); | 882 | wrterror("allocation failed.\n"); |
863 | 883 | ||
864 | if (malloc_zero) | 884 | if (malloc_zero) |
865 | memset(result,0,size); | 885 | memset(result, 0, size); |
866 | 886 | ||
867 | #ifdef _THREAD_SAFE | ||
868 | _thread_kern_sig_unblock(status); | ||
869 | #endif | ||
870 | return result; | 887 | return result; |
871 | } | 888 | } |
872 | 889 | ||
873 | /* | 890 | /* |
874 | * Change the size of an allocation. | 891 | * Change the size of an allocation. |
875 | */ | 892 | */ |
876 | void * | 893 | static void * |
877 | realloc(ptr, size) | 894 | irealloc(ptr, size) |
878 | void *ptr; | 895 | void *ptr; |
879 | size_t size; | 896 | size_t size; |
880 | { | 897 | { |
881 | void *p; | 898 | void *p; |
882 | u_long osize,index; | 899 | u_long osize, index; |
883 | struct pginfo **mp; | 900 | struct pginfo **mp; |
884 | int i; | 901 | int i; |
885 | #ifdef _THREAD_SAFE | 902 | #ifdef _THREAD_SAFE |
@@ -889,37 +906,20 @@ realloc(ptr, size) | |||
889 | if (suicide) | 906 | if (suicide) |
890 | return 0; | 907 | return 0; |
891 | 908 | ||
892 | if (!ptr) /* Bounce to malloc() */ | ||
893 | return malloc(size); | ||
894 | |||
895 | if (!initialized) { | 909 | if (!initialized) { |
896 | wrtwarning("realloc(): malloc() never got called.\n"); | 910 | wrtwarning("malloc() has never been called.\n"); |
897 | return 0; | ||
898 | } | ||
899 | |||
900 | if (ptr && !size) { /* Bounce to free() */ | ||
901 | free(ptr); | ||
902 | return 0; | 911 | return 0; |
903 | } | 912 | } |
904 | 913 | ||
905 | #ifdef _THREAD_SAFE | ||
906 | _thread_kern_sig_block(&status); | ||
907 | #endif | ||
908 | index = ptr2index(ptr); | 914 | index = ptr2index(ptr); |
909 | 915 | ||
910 | if (index < malloc_pageshift) { | 916 | if (index < malloc_pageshift) { |
911 | wrtwarning("realloc(): junk pointer (too low)\n"); | 917 | wrtwarning("junk pointer, too low to make sense.\n"); |
912 | #ifdef _THREAD_SAFE | ||
913 | _thread_kern_sig_unblock(status); | ||
914 | #endif | ||
915 | return 0; | 918 | return 0; |
916 | } | 919 | } |
917 | 920 | ||
918 | if (index > last_index) { | 921 | if (index > last_index) { |
919 | wrtwarning("realloc(): junk pointer (too high)\n"); | 922 | wrtwarning("junk pointer, too high to make sense.\n"); |
920 | #ifdef _THREAD_SAFE | ||
921 | _thread_kern_sig_unblock(status); | ||
922 | #endif | ||
923 | return 0; | 923 | return 0; |
924 | } | 924 | } |
925 | 925 | ||
@@ -929,10 +929,7 @@ realloc(ptr, size) | |||
929 | 929 | ||
930 | /* Check the pointer */ | 930 | /* Check the pointer */ |
931 | if ((u_long)ptr & malloc_pagemask) { | 931 | if ((u_long)ptr & malloc_pagemask) { |
932 | wrtwarning("realloc(): modified page pointer.\n"); | 932 | wrtwarning("modified (page-) pointer.\n"); |
933 | #ifdef _THREAD_SAFE | ||
934 | _thread_kern_sig_unblock(status); | ||
935 | #endif | ||
936 | return 0; | 933 | return 0; |
937 | } | 934 | } |
938 | 935 | ||
@@ -943,9 +940,6 @@ realloc(ptr, size) | |||
943 | if (!malloc_realloc && /* unless we have to, */ | 940 | if (!malloc_realloc && /* unless we have to, */ |
944 | size <= osize && /* .. or are too small, */ | 941 | size <= osize && /* .. or are too small, */ |
945 | size > (osize - malloc_pagesize)) { /* .. or can free a page, */ | 942 | size > (osize - malloc_pagesize)) { /* .. or can free a page, */ |
946 | #ifdef _THREAD_SAFE | ||
947 | _thread_kern_sig_unblock(status); | ||
948 | #endif | ||
949 | return ptr; /* don't do anything. */ | 943 | return ptr; /* don't do anything. */ |
950 | } | 944 | } |
951 | 945 | ||
@@ -953,10 +947,7 @@ realloc(ptr, size) | |||
953 | 947 | ||
954 | /* Check the pointer for sane values */ | 948 | /* Check the pointer for sane values */ |
955 | if (((u_long)ptr & ((*mp)->size-1))) { | 949 | if (((u_long)ptr & ((*mp)->size-1))) { |
956 | wrtwarning("realloc(): modified chunk pointer.\n"); | 950 | wrtwarning("modified (chunk-) pointer.\n"); |
957 | #ifdef _THREAD_SAFE | ||
958 | _thread_kern_sig_unblock(status); | ||
959 | #endif | ||
960 | return 0; | 951 | return 0; |
961 | } | 952 | } |
962 | 953 | ||
@@ -964,11 +955,8 @@ realloc(ptr, size) | |||
964 | i = ((u_long)ptr & malloc_pagemask) >> (*mp)->shift; | 955 | i = ((u_long)ptr & malloc_pagemask) >> (*mp)->shift; |
965 | 956 | ||
966 | /* Verify that it isn't a free chunk already */ | 957 | /* Verify that it isn't a free chunk already */ |
967 | if (tst_bit(*mp,i)) { | 958 | if (tst_bit(*mp, i)) { |
968 | wrtwarning("realloc(): already free chunk.\n"); | 959 | wrtwarning("chunk is already free.\n"); |
969 | #ifdef _THREAD_SAFE | ||
970 | _thread_kern_sig_unblock(status); | ||
971 | #endif | ||
972 | return 0; | 960 | return 0; |
973 | } | 961 | } |
974 | 962 | ||
@@ -978,33 +966,24 @@ realloc(ptr, size) | |||
978 | size < osize && /* ..or are too small, */ | 966 | size < osize && /* ..or are too small, */ |
979 | (size > osize/2 || /* ..or could use a smaller size, */ | 967 | (size > osize/2 || /* ..or could use a smaller size, */ |
980 | osize == malloc_minsize)) { /* ..(if there is one) */ | 968 | osize == malloc_minsize)) { /* ..(if there is one) */ |
981 | #ifdef _THREAD_SAFE | ||
982 | _thread_kern_sig_unblock(status); | ||
983 | #endif | ||
984 | return ptr; /* ..Don't do anything */ | 969 | return ptr; /* ..Don't do anything */ |
985 | } | 970 | } |
986 | 971 | ||
987 | } else { | 972 | } else { |
988 | wrtwarning("realloc(): wrong page pointer.\n"); | 973 | wrtwarning("pointer to wrong page.\n"); |
989 | #ifdef _THREAD_SAFE | ||
990 | _thread_kern_sig_unblock(status); | ||
991 | #endif | ||
992 | return 0; | 974 | return 0; |
993 | } | 975 | } |
994 | 976 | ||
995 | p = malloc(size); | 977 | p = imalloc(size); |
996 | 978 | ||
997 | if (p) { | 979 | if (p) { |
998 | /* copy the lesser of the two sizes, and free the old one */ | 980 | /* copy the lesser of the two sizes, and free the old one */ |
999 | if (osize < size) | 981 | if (osize < size) |
1000 | memcpy(p,ptr,osize); | 982 | memcpy(p, ptr, osize); |
1001 | else | 983 | else |
1002 | memcpy(p,ptr,size); | 984 | memcpy(p, ptr, size); |
1003 | free(ptr); | 985 | ifree(ptr); |
1004 | } | 986 | } |
1005 | #ifdef _THREAD_SAFE | ||
1006 | _thread_kern_sig_unblock(status); | ||
1007 | #endif | ||
1008 | return p; | 987 | return p; |
1009 | } | 988 | } |
1010 | 989 | ||
@@ -1019,22 +998,22 @@ free_pages(ptr, index, info) | |||
1019 | struct pginfo *info; | 998 | struct pginfo *info; |
1020 | { | 999 | { |
1021 | int i; | 1000 | int i; |
1022 | struct pgfree *pf,*pt=0; | 1001 | struct pgfree *pf, *pt=0; |
1023 | u_long l; | 1002 | u_long l; |
1024 | void *tail; | 1003 | void *tail; |
1025 | 1004 | ||
1026 | if (info == MALLOC_FREE) { | 1005 | if (info == MALLOC_FREE) { |
1027 | wrtwarning("free(): already free page.\n"); | 1006 | wrtwarning("page is already free.\n"); |
1028 | return; | 1007 | return; |
1029 | } | 1008 | } |
1030 | 1009 | ||
1031 | if (info != MALLOC_FIRST) { | 1010 | if (info != MALLOC_FIRST) { |
1032 | wrtwarning("free(): freeing wrong page.\n"); | 1011 | wrtwarning("pointer to wrong page.\n"); |
1033 | return; | 1012 | return; |
1034 | } | 1013 | } |
1035 | 1014 | ||
1036 | if ((u_long)ptr & malloc_pagemask) { | 1015 | if ((u_long)ptr & malloc_pagemask) { |
1037 | wrtwarning("free(): modified page pointer.\n"); | 1016 | wrtwarning("modified (page-) pointer.\n"); |
1038 | return; | 1017 | return; |
1039 | } | 1018 | } |
1040 | 1019 | ||
@@ -1045,11 +1024,16 @@ free_pages(ptr, index, info) | |||
1045 | 1024 | ||
1046 | l = i << malloc_pageshift; | 1025 | l = i << malloc_pageshift; |
1047 | 1026 | ||
1048 | tail = (char *)ptr + l; | 1027 | #ifdef __FreeBSD__ |
1028 | if (malloc_hint) | ||
1029 | madvise(ptr, l, MADV_FREE); | ||
1030 | #endif | ||
1031 | |||
1032 | tail = (char *)ptr+l; | ||
1049 | 1033 | ||
1050 | /* add to free-list */ | 1034 | /* add to free-list */ |
1051 | if (!px) | 1035 | if (!px) |
1052 | px = malloc(sizeof *pt); /* This cannot fail... */ | 1036 | px = imalloc(sizeof *pt); /* This cannot fail... */ |
1053 | px->page = ptr; | 1037 | px->page = ptr; |
1054 | px->end = tail; | 1038 | px->end = tail; |
1055 | px->size = l; | 1039 | px->size = l; |
@@ -1065,7 +1049,7 @@ free_pages(ptr, index, info) | |||
1065 | } else { | 1049 | } else { |
1066 | 1050 | ||
1067 | /* Find the right spot, leave pf pointing to the modified entry. */ | 1051 | /* Find the right spot, leave pf pointing to the modified entry. */ |
1068 | tail = (char *)ptr + l; | 1052 | tail = (char *)ptr+l; |
1069 | 1053 | ||
1070 | for(pf = free_list.next; pf->end < ptr && pf->next; pf = pf->next) | 1054 | for(pf = free_list.next; pf->end < ptr && pf->next; pf = pf->next) |
1071 | ; /* Race ahead here */ | 1055 | ; /* Race ahead here */ |
@@ -1103,7 +1087,7 @@ free_pages(ptr, index, info) | |||
1103 | pf = px; | 1087 | pf = px; |
1104 | px = 0; | 1088 | px = 0; |
1105 | } else { | 1089 | } else { |
1106 | wrterror("messed up free list"); | 1090 | wrterror("freelist is destroyed.\n"); |
1107 | } | 1091 | } |
1108 | } | 1092 | } |
1109 | 1093 | ||
@@ -1132,7 +1116,7 @@ free_pages(ptr, index, info) | |||
1132 | /* XXX: We could realloc/shrink the pagedir here I guess. */ | 1116 | /* XXX: We could realloc/shrink the pagedir here I guess. */ |
1133 | } | 1117 | } |
1134 | if (pt) | 1118 | if (pt) |
1135 | free(pt); | 1119 | ifree(pt); |
1136 | } | 1120 | } |
1137 | 1121 | ||
1138 | /* | 1122 | /* |
@@ -1154,16 +1138,16 @@ free_bytes(ptr, index, info) | |||
1154 | i = ((u_long)ptr & malloc_pagemask) >> info->shift; | 1138 | i = ((u_long)ptr & malloc_pagemask) >> info->shift; |
1155 | 1139 | ||
1156 | if (((u_long)ptr & (info->size-1))) { | 1140 | if (((u_long)ptr & (info->size-1))) { |
1157 | wrtwarning("free(): modified pointer.\n"); | 1141 | wrtwarning("modified (chunk-) pointer.\n"); |
1158 | return; | 1142 | return; |
1159 | } | 1143 | } |
1160 | 1144 | ||
1161 | if (tst_bit(info,i)) { | 1145 | if (tst_bit(info, i)) { |
1162 | wrtwarning("free(): already free chunk.\n"); | 1146 | wrtwarning("chunk is already free.\n"); |
1163 | return; | 1147 | return; |
1164 | } | 1148 | } |
1165 | 1149 | ||
1166 | set_bit(info,i); | 1150 | set_bit(info, i); |
1167 | info->free++; | 1151 | info->free++; |
1168 | 1152 | ||
1169 | mp = page_dir + info->shift; | 1153 | mp = page_dir + info->shift; |
@@ -1198,12 +1182,12 @@ free_bytes(ptr, index, info) | |||
1198 | page_dir[ptr2index(info->page)] = MALLOC_FIRST; | 1182 | page_dir[ptr2index(info->page)] = MALLOC_FIRST; |
1199 | vp = info->page; /* Order is important ! */ | 1183 | vp = info->page; /* Order is important ! */ |
1200 | if(vp != (void*)info) | 1184 | if(vp != (void*)info) |
1201 | free(info); | 1185 | ifree(info); |
1202 | free(vp); | 1186 | ifree(vp); |
1203 | } | 1187 | } |
1204 | 1188 | ||
1205 | void | 1189 | static void |
1206 | free(ptr) | 1190 | ifree(ptr) |
1207 | void *ptr; | 1191 | void *ptr; |
1208 | { | 1192 | { |
1209 | struct pginfo *info; | 1193 | struct pginfo *info; |
@@ -1217,7 +1201,7 @@ free(ptr) | |||
1217 | return; | 1201 | return; |
1218 | 1202 | ||
1219 | if (!initialized) { | 1203 | if (!initialized) { |
1220 | wrtwarning("free(): malloc() never got called.\n"); | 1204 | wrtwarning("malloc() has never been called.\n"); |
1221 | return; | 1205 | return; |
1222 | } | 1206 | } |
1223 | 1207 | ||
@@ -1225,35 +1209,102 @@ free(ptr) | |||
1225 | if (suicide) | 1209 | if (suicide) |
1226 | return; | 1210 | return; |
1227 | 1211 | ||
1228 | #ifdef _THREAD_SAFE | ||
1229 | _thread_kern_sig_block(&status); | ||
1230 | #endif | ||
1231 | index = ptr2index(ptr); | 1212 | index = ptr2index(ptr); |
1232 | 1213 | ||
1233 | if (index < malloc_pageshift) { | 1214 | if (index < malloc_pageshift) { |
1234 | wrtwarning("free(): junk pointer (too low)\n"); | 1215 | wrtwarning("junk pointer, too low to make sense.\n"); |
1235 | #ifdef _THREAD_SAFE | ||
1236 | _thread_kern_sig_unblock(status); | ||
1237 | #endif | ||
1238 | return; | 1216 | return; |
1239 | } | 1217 | } |
1240 | 1218 | ||
1241 | if (index > last_index) { | 1219 | if (index > last_index) { |
1242 | wrtwarning("free(): junk pointer (too high)\n"); | 1220 | wrtwarning("junk pointer, too high to make sense.\n"); |
1243 | #ifdef _THREAD_SAFE | ||
1244 | _thread_kern_sig_unblock(status); | ||
1245 | #endif | ||
1246 | return; | 1221 | return; |
1247 | } | 1222 | } |
1248 | 1223 | ||
1249 | info = page_dir[index]; | 1224 | info = page_dir[index]; |
1250 | 1225 | ||
1251 | if (info < MALLOC_MAGIC) | 1226 | if (info < MALLOC_MAGIC) |
1252 | free_pages(ptr,index,info); | 1227 | free_pages(ptr, index, info); |
1253 | else | 1228 | else |
1254 | free_bytes(ptr,index,info); | 1229 | free_bytes(ptr, index, info); |
1255 | #ifdef _THREAD_SAFE | 1230 | return; |
1256 | _thread_kern_sig_unblock(status); | 1231 | } |
1232 | |||
1233 | /* | ||
1234 | * These are the public exported interface routines. | ||
1235 | */ | ||
1236 | |||
1237 | #ifdef _THREAD_SAFE | ||
1238 | #include <pthread.h> | ||
1239 | #include "pthread_private.h" | ||
1240 | static int malloc_lock; | ||
1241 | #define THREAD_LOCK() _thread_kern_sig_block(&malloc_lock); | ||
1242 | #define THREAD_UNLOCK() _thread_kern_sig_unblock(&malloc_lock); | ||
1243 | #else | ||
1244 | #define THREAD_LOCK() | ||
1245 | #define THREAD_UNLOCK() | ||
1257 | #endif | 1246 | #endif |
1247 | |||
1248 | static int malloc_active; | ||
1249 | |||
1250 | void * | ||
1251 | malloc(size_t size) | ||
1252 | { | ||
1253 | register void *r; | ||
1254 | |||
1255 | malloc_func = "malloc():"; | ||
1256 | THREAD_LOCK(); | ||
1257 | if (malloc_active++) { | ||
1258 | wrtwarning("recursive call.\n"); | ||
1259 | malloc_active--; | ||
1260 | return (0); | ||
1261 | } | ||
1262 | r = imalloc(size); | ||
1263 | UTRACE(0, size, r); | ||
1264 | malloc_active--; | ||
1265 | THREAD_UNLOCK(); | ||
1266 | return (r); | ||
1267 | } | ||
1268 | |||
1269 | void | ||
1270 | free(void *ptr) | ||
1271 | { | ||
1272 | malloc_func = "free():"; | ||
1273 | THREAD_LOCK(); | ||
1274 | if (malloc_active++) { | ||
1275 | wrtwarning("recursive call.\n"); | ||
1276 | malloc_active--; | ||
1277 | return; | ||
1278 | } | ||
1279 | ifree(ptr); | ||
1280 | UTRACE(ptr, 0, 0); | ||
1281 | malloc_active--; | ||
1282 | THREAD_UNLOCK(); | ||
1258 | return; | 1283 | return; |
1259 | } | 1284 | } |
1285 | |||
1286 | void * | ||
1287 | realloc(void *ptr, size_t size) | ||
1288 | { | ||
1289 | register void *r; | ||
1290 | |||
1291 | malloc_func = "realloc():"; | ||
1292 | THREAD_LOCK(); | ||
1293 | if (malloc_active++) { | ||
1294 | wrtwarning("recursive call.\n"); | ||
1295 | malloc_active--; | ||
1296 | return (0); | ||
1297 | } | ||
1298 | if (!ptr) { | ||
1299 | r = imalloc(size); | ||
1300 | } else if (ptr && !size) { | ||
1301 | ifree(ptr); | ||
1302 | r = 0; | ||
1303 | } else { | ||
1304 | r = irealloc(ptr, size); | ||
1305 | } | ||
1306 | UTRACE(ptr, size, r); | ||
1307 | malloc_active--; | ||
1308 | THREAD_UNLOCK(); | ||
1309 | return (r); | ||
1310 | } | ||