summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authortholo <>1996-09-26 04:19:42 +0000
committertholo <>1996-09-26 04:19:42 +0000
commit40954213683da2af94f45d9b0f35806b54e5e306 (patch)
tree4d52bb67398acd4227bd70258a69403ba2acf910 /src/lib
parent7bfb6e73ddb58269b8ec906a008d5999e1b70abf (diff)
downloadopenbsd-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.3118
-rw-r--r--src/lib/libc/stdlib/malloc.c491
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
62The 64The
63.Fn malloc 65.Fn malloc
@@ -120,11 +122,13 @@ is zero and
120.Fa ptr 122.Fa ptr
121is not a null pointer, the object it points to is freed. 123is not a null pointer, the object it points to is freed.
122.Pp 124.Pp
123 125Malloc will first look for a symbolic link called
124.Sh ENVIRONMENT 126.Pa /etc/malloc.conf
125This malloc will check the environment for a variable called 127and next check the environment for a variable called
126.Em MALLOC_OPTIONS 128.Ev MALLOC_OPTIONS
127and scan it for flags. 129and finally for the global variable
130.Va malloc_options
131and scan them for flags in that order.
128Flags are single letters, uppercase means on, lowercase means off. 132Flags 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.
143Currently junk is bytes of 0xd0, this is pronounced ``Duh'' :-) 147Currently 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
151machine 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
148is called, even if the initial allocation was big enough. 156is called, even if the initial allocation was big enough.
149This can substantially aid in compacting memory. 157This can substantially aid in compacting memory.
150 158
159.It U
160``utrace'' generate entries for ktrace(1) for all operations.
161Consult 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''),
153except for the exact length the user asked for, which is zeroed. 165except 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
174So to set a systemwide reduction of cache size and coredumps on problems
175one would:
176.Li ln -s 'A<' /etc/malloc.conf
177.Pp
157The ``J'' and ``Z'' is mostly for testing and debugging, 178The ``J'' and ``Z'' is mostly for testing and debugging,
158if a program changes behavior if either of these options are used, 179if a program changes behavior if either of these options are used,
159it is buggy. 180it is buggy.
181.Pp
182The default cache size is 16 pages.
183.Sh ENVIRONMENT
184See above.
160.Sh RETURN VALUES 185.Sh RETURN VALUES
161The 186The
162.Fn malloc 187.Fn malloc
@@ -172,12 +197,89 @@ The
172.Fn realloc 197.Fn realloc
173function returns either a null pointer or a pointer 198function returns either a null pointer or a pointer
174to the possibly moved allocated space. 199to the possibly moved allocated space.
200.Sh MESSAGES
201If
202.Fn malloc ,
203.Fn free
204or
205.Fn realloc
206detects an error or warning condition,
207a message will be printed to filedescriptor
2082 (not using stdio).
209Errors will always result in the process being
210.Xr abort 2 'ed,
211If the ``A'' option has been specified, also warnings will
212.Xr abort 2
213the process.
214.Pp
215Here is a brief description of the error messages and what they mean:
216.Pp
217``(ES): mumble mumble mumble'':
218malloc have been compiled with -DEXTRA_SANITY and something looks
219fishy in there. Consult sources and or wizards.
220.Pp
221``allocation failed''
222if the ``A'' option is specified it is an error for
223.Fn malloc
224or
225.Fn realloc
226to return NULL.
227.Pp
228``mmap(2) failed, check limits.''
229This is a rather weird condition that is most likely to mean that
230the system is seriously overloaded or that your ulimits are sick.
231.Pp
232``freelist is destroyed.''
233mallocs internal freelist has been stomped on.
234.Pp
235Here is a brief description of the warning messages and what they mean:
236.Pp
237``chunk/page is already free.''
238A pointer to a free chunk is attempted freed again.
239.Pp
240``junk pointer, too high to make sense.''
241The pointer doesn't make sense. It's above the area of memory that
242malloc knows something about.
243This could be a pointer from some
244.Xr mmap 2 'ed
245memory.
246.Pp
247``junk pointer, too low to make sense.''
248The pointer doesn't make sense. It's below the area of memory that
249malloc knows something about.
250This pointer probably came from your data or bss segments.
251.Pp
252``malloc() has never been called.''
253Nothing has ever been allocated, yet something is being freed or
254realloc'ed.
255.Pp
256``modified (chunk-/page-) pointer.''
257The pointer passed to free or realloc has been modified.
258.Pp
259``pointer to wrong page.''
260The pointer that malloc is trying to free is not pointing to
261a sensible page.
262.Pp
263``recursive call.''
264You have tried to call recursively into these functions.
265I can only imagine this as happening if you call one of these
266functions from a signal function, which happens to be called
267while you're already in here.
268Well, sorry to say: that's not supported.
269If this is a problem for you I'd like to hear about it. It
270would be possible to add a sigblock() around this package,
271but it would have a performance penalty that is not acceptable
272as the default.
273.Pp
274``unknown char in MALLOC_OPTIONS''
275we 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
182The 284The
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)
11static char rcsid[] = "$OpenBSD: malloc.c,v 1.13 1996/09/19 20:38:48 tholo Exp $"; 11static 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
113static __inline int 116static __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;
165static unsigned malloc_pagesize; 168static 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
180static unsigned malloc_pageshift; 179static unsigned malloc_pageshift;
181#endif /* malloc_pageshift */ 180#endif /* malloc_pageshift */
@@ -197,85 +196,78 @@ static unsigned malloc_minsize;
197static unsigned malloc_maxsize; 196static 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. 200static unsigned malloc_cache = 16;
202 */
203#ifndef malloc_cache
204static 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 */
210static u_long malloc_origo; 203static 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 */
215static u_long last_index; 206static 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 */
221static struct pginfo **page_dir; 209static struct pginfo **page_dir;
222 210
223/* 211/* How many slots in the page directory */
224 * How many slots in the page directory
225 */
226static unsigned malloc_ninfo; 212static unsigned malloc_ninfo;
227 213
228/* 214/* Free pages line up here */
229 * Free pages line up here
230 */
231static struct pgfree free_list; 215static struct pgfree free_list;
232 216
233/* 217/* Abort(), user doesn't handle problems. */
234 * Abort() if we fail to get VM ?
235 */
236static int malloc_abort; 218static int malloc_abort;
237 219
238/* 220/* Are we trying to die ? */
239 * Are we trying to die ?
240 */
241static int suicide; 221static int suicide;
242 222
243#ifdef MALLOC_STATS 223#ifdef MALLOC_STATS
244/* 224/* dump statistics */
245 * dump statistics
246 */
247static int malloc_stats; 225static int malloc_stats;
248#endif /* MALLOC_STATS */ 226#endif /* MALLOC_STATS */
249 227
250/* 228/* always realloc ? */
251 * always realloc ?
252 */
253static int malloc_realloc; 229static int malloc_realloc;
254 230
255/* 231#ifdef __FreeBSD__
256 * zero fill ? 232/* pass the kernel a hint on free pages ? */
257 */ 233static int malloc_hint;
234#endif
235
236/* zero fill ? */
258static int malloc_zero; 237static int malloc_zero;
259 238
260/* 239/* junk fill ? */
261 * junk fill ?
262 */
263static int malloc_junk; 240static int malloc_junk;
264 241
265/* 242#ifdef __FreeBSD__
266 * my last break. 243/* utrace ? */
267 */ 244static int malloc_utrace;
245
246struct 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. */
268static void *malloc_brk; 256static void *malloc_brk;
269 257
270/* 258/* one location cache for free-list holders */
271 * one location cache for free-list holders
272 */
273static struct pgfree *px; 259static struct pgfree *px;
274 260
261/* compile-time options */
262char *malloc_options;
263
275/* 264/*
276 * Necessary function declarations 265 * Necessary function declarations
277 */ 266 */
278static int extend_pgdir(u_long index); 267static int extend_pgdir(u_long index);
268static void *imalloc(size_t size);
269static void ifree(void *ptr);
270static void *irealloc(void *ptr, size_t size);
279 271
280#ifdef MALLOC_STATS 272#ifdef MALLOC_STATS
281void 273void
@@ -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
331static char *malloc_func;
332
339static void 333static void
340wrterror(p) 334wrterror(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
366static void 362static void
367malloc_exit() 363malloc_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
384map_pages(pages) 380map_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
466extend_pgdir(index) 462extend_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)
520static void 516static void
521malloc_init () 517malloc_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 *
640malloc_pages(size) 663malloc_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 */
838void * 861static void *
839malloc(size) 862imalloc(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 */
876void * 893static void *
877realloc(ptr, size) 894irealloc(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
1205void 1189static void
1206free(ptr) 1190ifree(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"
1240static 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
1248static int malloc_active;
1249
1250void *
1251malloc(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
1269void
1270free(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
1286void *
1287realloc(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}