xref: /minix3/lib/libc/stdlib/malloc.c (revision 2fe8fb192fe7e8720e3e7a77f928da545e872a6a)
1 /*	$NetBSD: malloc.c,v 1.52 2008/02/03 22:56:53 christos Exp $	*/
2 
3 /*
4  * ----------------------------------------------------------------------------
5  * "THE BEER-WARE LICENSE" (Revision 42):
6  * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
7  * can do whatever you want with this stuff. If we meet some day, and you think
8  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
9  * ----------------------------------------------------------------------------
10  *
11  * From FreeBSD: malloc.c,v 1.91 2006/01/12 07:28:20 jasone
12  *
13  */
14 
15 #ifdef __minix
16 #define mmap minix_mmap
17 #define munmap minix_munmap
18 #endif
19 
20 /*
21  * Defining MALLOC_EXTRA_SANITY will enable extra checks which are related
22  * to internal conditions and consistency in malloc.c. This has a
23  * noticeable runtime performance hit, and generally will not do you
24  * any good unless you fiddle with the internals of malloc or want
25  * to catch random pointer corruption as early as possible.
26  */
27 #ifndef MALLOC_EXTRA_SANITY
28 #undef MALLOC_EXTRA_SANITY
29 #endif
30 
31 /*
32  * What to use for Junk.  This is the byte value we use to fill with
33  * when the 'J' option is enabled.
34  */
35 #define SOME_JUNK	0xd0		/* as in "Duh" :-) */
36 
37 /*
38  * The basic parameters you can tweak.
39  *
40  * malloc_minsize	minimum size of an allocation in bytes.
41  *			If this is too small it's too much work
42  *			to manage them.  This is also the smallest
43  *			unit of alignment used for the storage
44  *			returned by malloc/realloc.
45  *
46  */
47 
48 #include "namespace.h"
49 #if defined(__FreeBSD__)
50 #   if defined(__i386__)
51 #       define malloc_minsize		16U
52 #   endif
53 #   if defined(__ia64__)
54 #	define malloc_pageshift		13U
55 #	define malloc_minsize		16U
56 #   endif
57 #   if defined(__alpha__)
58 #       define malloc_pageshift		13U
59 #       define malloc_minsize		16U
60 #   endif
61 #   if defined(__sparc64__)
62 #       define malloc_pageshift		13U
63 #       define malloc_minsize		16U
64 #   endif
65 #   if defined(__amd64__)
66 #       define malloc_pageshift		12U
67 #       define malloc_minsize		16U
68 #   endif
69 #   if defined(__arm__)
70 #       define malloc_pageshift         12U
71 #       define malloc_minsize           16U
72 #   endif
73 #ifndef __minix
74 #   define HAS_UTRACE
75 #   define UTRACE_LABEL
76 #endif /* __minix */
77 
78 #include <sys/cdefs.h>
79 void utrace(struct ut *, int);
80 
81     /*
82      * Make malloc/free/realloc thread-safe in libc for use with
83      * kernel threads.
84      */
85 #   include "libc_private.h"
86 #   include "spinlock.h"
87     static spinlock_t thread_lock	= _SPINLOCK_INITIALIZER;
88 #   define _MALLOC_LOCK()		if (__isthreaded) _SPINLOCK(&thread_lock);
89 #   define _MALLOC_UNLOCK()		if (__isthreaded) _SPINUNLOCK(&thread_lock);
90 #endif /* __FreeBSD__ */
91 
92 #include <sys/types.h>
93 #if defined(__NetBSD__)
94 #   define malloc_minsize               16U
95 #   define HAS_UTRACE
96 #   define UTRACE_LABEL "malloc",
97 #include <sys/cdefs.h>
98 #include "extern.h"
99 #if defined(LIBC_SCCS) && !defined(lint)
100 __RCSID("$NetBSD: malloc.c,v 1.52 2008/02/03 22:56:53 christos Exp $");
101 #endif /* LIBC_SCCS and not lint */
102 int utrace(const char *, void *, size_t);
103 
104 #include <reentrant.h>
105 extern int __isthreaded;
106 static mutex_t thread_lock = MUTEX_INITIALIZER;
107 #define _MALLOC_LOCK()	if (__isthreaded) mutex_lock(&thread_lock);
108 #define _MALLOC_UNLOCK()	if (__isthreaded) mutex_unlock(&thread_lock);
109 #endif /* __NetBSD__ */
110 
111 #if defined(__sparc__) && defined(sun)
112 #   define malloc_minsize		16U
113 #   define MAP_ANON			(0)
114     static int fdzero;
115 #   define MMAP_FD	fdzero
116 #   define INIT_MMAP() \
117 	{ if ((fdzero = open(_PATH_DEVZERO, O_RDWR, 0000)) == -1) \
118 	    wrterror("open of /dev/zero"); }
119 #endif /* __sparc__ */
120 
121 /* Insert your combination here... */
122 #if defined(__FOOCPU__) && defined(__BAROS__)
123 #   define malloc_minsize		16U
124 #endif /* __FOOCPU__ && __BAROS__ */
125 
126 #ifndef ZEROSIZEPTR
127 #define ZEROSIZEPTR	((void *)(uintptr_t)(1UL << (malloc_pageshift - 1)))
128 #endif
129 
130 /*
131  * No user serviceable parts behind this point.
132  */
133 #include <sys/types.h>
134 #include <sys/mman.h>
135 #include <errno.h>
136 #include <fcntl.h>
137 #include <paths.h>
138 #include <stddef.h>
139 #include <stdio.h>
140 #include <stdlib.h>
141 #include <string.h>
142 #include <unistd.h>
143 
144 /*
145  * This structure describes a page worth of chunks.
146  */
147 
148 struct pginfo {
149     struct pginfo	*next;	/* next on the free list */
150     void		*page;	/* Pointer to the page */
151     u_short		size;	/* size of this page's chunks */
152     u_short		shift;	/* How far to shift for this size chunks */
153     u_short		free;	/* How many free chunks */
154     u_short		total;	/* How many chunk */
155     u_int		bits[1]; /* Which chunks are free */
156 };
157 
158 /*
159  * This structure describes a number of free pages.
160  */
161 
162 struct pgfree {
163     struct pgfree	*next;	/* next run of free pages */
164     struct pgfree	*prev;	/* prev run of free pages */
165     void		*page;	/* pointer to free pages */
166     void		*end;	/* pointer to end of free pages */
167     size_t		size;	/* number of bytes free */
168 };
169 
170 /*
171  * How many bits per u_int in the bitmap.
172  * Change only if not 8 bits/byte
173  */
174 #define	MALLOC_BITS	((int)(8*sizeof(u_int)))
175 
176 /*
177  * Magic values to put in the page_directory
178  */
179 #define MALLOC_NOT_MINE	((struct pginfo*) 0)
180 #define MALLOC_FREE 	((struct pginfo*) 1)
181 #define MALLOC_FIRST	((struct pginfo*) 2)
182 #define MALLOC_FOLLOW	((struct pginfo*) 3)
183 #define MALLOC_MAGIC	((struct pginfo*) 4)
184 
185 /*
186  * Page size related parameters, computed at run-time.
187  */
188 static size_t malloc_pagesize;
189 static size_t malloc_pageshift;
190 static size_t malloc_pagemask;
191 
192 #ifndef malloc_minsize
193 #define malloc_minsize			16U
194 #endif
195 
196 #ifndef malloc_maxsize
197 #define malloc_maxsize			((malloc_pagesize)>>1)
198 #endif
199 
200 #define pageround(foo) (((foo) + (malloc_pagemask))&(~(malloc_pagemask)))
201 #define ptr2idx(foo) \
202     (((size_t)(uintptr_t)(foo) >> malloc_pageshift)-malloc_origo)
203 
204 #ifndef _MALLOC_LOCK
205 #define _MALLOC_LOCK()
206 #endif
207 
208 #ifndef _MALLOC_UNLOCK
209 #define _MALLOC_UNLOCK()
210 #endif
211 
212 #ifndef MMAP_FD
213 #define MMAP_FD (-1)
214 #endif
215 
216 #ifndef INIT_MMAP
217 #define INIT_MMAP()
218 #endif
219 
220 #ifndef __minix
221 #ifndef MADV_FREE
222 #define MADV_FREE MADV_DONTNEED
223 #endif
224 #endif /* !__minix */
225 
226 /* Number of free pages we cache */
227 static size_t malloc_cache = 16;
228 
229 /* The offset from pagenumber to index into the page directory */
230 static size_t malloc_origo;
231 
232 /* The last index in the page directory we care about */
233 static size_t last_idx;
234 
235 /* Pointer to page directory. Allocated "as if with" malloc */
236 static struct	pginfo **page_dir;
237 
238 /* How many slots in the page directory */
239 static size_t	malloc_ninfo;
240 
241 /* Free pages line up here */
242 static struct pgfree free_list;
243 
244 /* Abort(), user doesn't handle problems.  */
245 static int malloc_abort;
246 
247 /* Are we trying to die ?  */
248 static int suicide;
249 
250 /* always realloc ?  */
251 static int malloc_realloc;
252 
253 /* pass the kernel a hint on free pages ?  */
254 #if defined(MADV_FREE)
255 static int malloc_hint = 0;
256 #endif
257 
258 /* xmalloc behaviour ?  */
259 static int malloc_xmalloc;
260 
261 /* sysv behaviour for malloc(0) ?  */
262 static int malloc_sysv;
263 
264 /* zero fill ?  */
265 static int malloc_zero;
266 
267 /* junk fill ?  */
268 static int malloc_junk;
269 
270 #ifdef HAS_UTRACE
271 
272 /* utrace ?  */
273 static int malloc_utrace;
274 
275 struct ut { void *p; size_t s; void *r; };
276 
277 #define UTRACE(a, b, c) \
278 	if (malloc_utrace) {			\
279 		struct ut u;			\
280 		u.p=a; u.s = b; u.r=c;		\
281 		utrace(UTRACE_LABEL (void *) &u, sizeof u);	\
282 	}
283 #else /* !HAS_UTRACE */
284 #define UTRACE(a,b,c)
285 #endif /* HAS_UTRACE */
286 
287 /* my last break. */
288 static void *malloc_brk;
289 
290 /* one location cache for free-list holders */
291 static struct pgfree *px;
292 
293 /* compile-time options */
294 const char *_malloc_options;
295 
296 /* Name of the current public function */
297 static const char *malloc_func;
298 
299 /* Macro for mmap */
300 #define MMAP(size) \
301 	mmap(NULL, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
302 	    MMAP_FD, (off_t)0);
303 
304 /*
305  * Necessary function declarations
306  */
307 static int extend_pgdir(size_t idx);
308 static void *imalloc(size_t size);
309 static void ifree(void *ptr);
310 static void *irealloc(void *ptr, size_t size);
311 
312 static void
313 wrtmessage(const char *p1, const char *p2, const char *p3, const char *p4)
314 {
315 
316     write(STDERR_FILENO, p1, strlen(p1));
317     write(STDERR_FILENO, p2, strlen(p2));
318     write(STDERR_FILENO, p3, strlen(p3));
319     write(STDERR_FILENO, p4, strlen(p4));
320 }
321 
322 void (*_malloc_message)(const char *p1, const char *p2, const char *p3,
323 	    const char *p4) = wrtmessage;
324 static void
325 wrterror(const char *p)
326 {
327 
328     suicide = 1;
329     _malloc_message(getprogname(), malloc_func, " error: ", p);
330     abort();
331 }
332 
333 static void
334 wrtwarning(const char *p)
335 {
336 
337     /*
338      * Sensitive processes, somewhat arbitrarily defined here as setuid,
339      * setgid, root and wheel cannot afford to have malloc mistakes.
340      */
341     if (malloc_abort || issetugid() || getuid() == 0 || getgid() == 0)
342 	wrterror(p);
343 }
344 
345 /*
346  * Allocate a number of pages from the OS
347  */
348 static void *
349 map_pages(size_t pages)
350 {
351     caddr_t result, rresult, tail;
352     intptr_t bytes = pages << malloc_pageshift;
353 
354     if (bytes < 0 || (size_t)bytes < pages) {
355 	errno = ENOMEM;
356 	return NULL;
357     }
358 
359     if ((result = sbrk(bytes)) == (void *)-1)
360 	return NULL;
361 
362     /*
363      * Round to a page, in case sbrk(2) did not do this for us
364      */
365     rresult = (caddr_t)pageround((size_t)(uintptr_t)result);
366     if (result < rresult) {
367 	/* make sure we have enough space to fit bytes */
368 	if (sbrk((intptr_t)(rresult - result)) == (void *) -1) {
369 	    /* we failed, put everything back */
370 	    if (brk(result)) {
371 		wrterror("brk(2) failed [internal error]\n");
372 	    }
373 	}
374     }
375     tail = rresult + (size_t)bytes;
376 
377     last_idx = ptr2idx(tail) - 1;
378     malloc_brk = tail;
379 
380     if ((last_idx+1) >= malloc_ninfo && !extend_pgdir(last_idx)) {
381 	malloc_brk = result;
382 	last_idx = ptr2idx(malloc_brk) - 1;
383 	/* Put back break point since we failed. */
384 	if (brk(malloc_brk))
385 	    wrterror("brk(2) failed [internal error]\n");
386 	return 0;
387     }
388 
389     return rresult;
390 }
391 
392 /*
393  * Extend page directory
394  */
395 static int
396 extend_pgdir(size_t idx)
397 {
398     struct  pginfo **new, **old;
399     size_t newlen, oldlen;
400 
401     /* check for overflow */
402     if ((((~(1UL << ((sizeof(size_t) * NBBY) - 1)) / sizeof(*page_dir)) + 1)
403 	+ (malloc_pagesize / sizeof *page_dir)) < idx) {
404 	errno = ENOMEM;
405 	return 0;
406     }
407 
408     /* Make it this many pages */
409     newlen = pageround(idx * sizeof *page_dir) + malloc_pagesize;
410 
411     /* remember the old mapping size */
412     oldlen = malloc_ninfo * sizeof *page_dir;
413 
414     /*
415      * NOTE: we allocate new pages and copy the directory rather than tempt
416      * fate by trying to "grow" the region.. There is nothing to prevent
417      * us from accidentally re-mapping space that's been allocated by our caller
418      * via dlopen() or other mmap().
419      *
420      * The copy problem is not too bad, as there is 4K of page index per
421      * 4MB of malloc arena.
422      *
423      * We can totally avoid the copy if we open a file descriptor to associate
424      * the anon mappings with.  Then, when we remap the pages at the new
425      * address, the old pages will be "magically" remapped..  But this means
426      * keeping open a "secret" file descriptor.....
427      */
428 
429     /* Get new pages */
430     new = MMAP(newlen);
431     if (new == MAP_FAILED)
432 	return 0;
433 
434     /* Copy the old stuff */
435     memcpy(new, page_dir, oldlen);
436 
437     /* register the new size */
438     malloc_ninfo = newlen / sizeof *page_dir;
439 
440     /* swap the pointers */
441     old = page_dir;
442     page_dir = new;
443 
444     /* Now free the old stuff */
445     munmap(old, oldlen);
446     return 1;
447 }
448 
449 /*
450  * Initialize the world
451  */
452 static void
453 malloc_init(void)
454 {
455     const char *p;
456     char b[64];
457     size_t i;
458     ssize_t j;
459     int save_errno = errno;
460 
461     /*
462      * Compute page-size related variables.
463      */
464     malloc_pagesize = (size_t)sysconf(_SC_PAGESIZE);
465     malloc_pagemask = malloc_pagesize - 1;
466     for (malloc_pageshift = 0;
467 	 (1UL << malloc_pageshift) != malloc_pagesize;
468 	 malloc_pageshift++)
469 	/* nothing */ ;
470 
471     INIT_MMAP();
472 
473 #ifdef MALLOC_EXTRA_SANITY
474     malloc_junk = 1;
475 #endif /* MALLOC_EXTRA_SANITY */
476 
477     for (i = 0; i < 3; i++) {
478 	if (i == 0) {
479 	    j = readlink("/etc/malloc.conf", b, sizeof b - 1);
480 	    if (j <= 0)
481 		continue;
482 	    b[j] = '\0';
483 	    p = b;
484 	} else if (i == 1 && issetugid() == 0) {
485 	    p = getenv("MALLOC_OPTIONS");
486 	} else if (i == 1) {
487 	    continue;
488 	} else {
489 	    p = _malloc_options;
490 	}
491 	for (; p != NULL && *p != '\0'; p++) {
492 	    switch (*p) {
493 		case '>': malloc_cache   <<= 1; break;
494 		case '<': malloc_cache   >>= 1; break;
495 		case 'a': malloc_abort   = 0; break;
496 		case 'A': malloc_abort   = 1; break;
497 #ifndef __minix
498 		case 'h': malloc_hint    = 0; break;
499 		case 'H': malloc_hint    = 1; break;
500 #endif /* !__minix */
501 		case 'r': malloc_realloc = 0; break;
502 		case 'R': malloc_realloc = 1; break;
503 		case 'j': malloc_junk    = 0; break;
504 		case 'J': malloc_junk    = 1; break;
505 #ifdef HAS_UTRACE
506 		case 'u': malloc_utrace  = 0; break;
507 		case 'U': malloc_utrace  = 1; break;
508 #endif
509 		case 'v': malloc_sysv    = 0; break;
510 		case 'V': malloc_sysv    = 1; break;
511 		case 'x': malloc_xmalloc = 0; break;
512 		case 'X': malloc_xmalloc = 1; break;
513 		case 'z': malloc_zero    = 0; break;
514 		case 'Z': malloc_zero    = 1; break;
515 		default:
516 		    _malloc_message(getprogname(), malloc_func,
517 			 " warning: ", "unknown char in MALLOC_OPTIONS\n");
518 		    break;
519 	    }
520 	}
521     }
522 
523     UTRACE(0, 0, 0);
524 
525     /*
526      * We want junk in the entire allocation, and zero only in the part
527      * the user asked for.
528      */
529     if (malloc_zero)
530 	malloc_junk = 1;
531 
532     /* Allocate one page for the page directory */
533     page_dir = MMAP(malloc_pagesize);
534 
535     if (page_dir == MAP_FAILED)
536 	wrterror("mmap(2) failed, check limits.\n");
537 
538     /*
539      * We need a maximum of malloc_pageshift buckets, steal these from the
540      * front of the page_directory;
541      */
542     malloc_origo = pageround((size_t)(uintptr_t)sbrk((intptr_t)0))
543 	>> malloc_pageshift;
544     malloc_origo -= malloc_pageshift;
545 
546     malloc_ninfo = malloc_pagesize / sizeof *page_dir;
547 
548     /* Recalculate the cache size in bytes, and make sure it's nonzero */
549 
550     if (!malloc_cache)
551 	malloc_cache++;
552 
553     malloc_cache <<= malloc_pageshift;
554 
555     /*
556      * This is a nice hack from Kaleb Keithly (kaleb@x.org).
557      * We can sbrk(2) further back when we keep this on a low address.
558      */
559     px = imalloc(sizeof *px);
560 
561     errno = save_errno;
562 }
563 
564 /*
565  * Allocate a number of complete pages
566  */
567 static void *
568 malloc_pages(size_t size)
569 {
570     void *p, *delay_free = NULL;
571     size_t i;
572     struct pgfree *pf;
573     size_t idx;
574 
575     idx = pageround(size);
576     if (idx < size) {
577 	errno = ENOMEM;
578 	return NULL;
579     } else
580 	size = idx;
581 
582     p = NULL;
583 
584     /* Look for free pages before asking for more */
585     for(pf = free_list.next; pf; pf = pf->next) {
586 
587 #ifdef MALLOC_EXTRA_SANITY
588 	if (pf->size & malloc_pagemask)
589 	    wrterror("(ES): junk length entry on free_list.\n");
590 	if (!pf->size)
591 	    wrterror("(ES): zero length entry on free_list.\n");
592 	if (pf->page == pf->end)
593 	    wrterror("(ES): zero entry on free_list.\n");
594 	if (pf->page > pf->end)
595 	    wrterror("(ES): sick entry on free_list.\n");
596 	if ((void*)pf->page >= (void*)sbrk(0))
597 	    wrterror("(ES): entry on free_list past brk.\n");
598 	if (page_dir[ptr2idx(pf->page)] != MALLOC_FREE)
599 	    wrterror("(ES): non-free first page on free-list.\n");
600 	if (page_dir[ptr2idx(pf->end)-1] != MALLOC_FREE)
601 	    wrterror("(ES): non-free last page on free-list.\n");
602 #endif /* MALLOC_EXTRA_SANITY */
603 
604 	if (pf->size < size)
605 	    continue;
606 
607 	if (pf->size == size) {
608 	    p = pf->page;
609 	    if (pf->next != NULL)
610 		    pf->next->prev = pf->prev;
611 	    pf->prev->next = pf->next;
612 	    delay_free = pf;
613 	    break;
614 	}
615 
616 	p = pf->page;
617 	pf->page = (char *)pf->page + size;
618 	pf->size -= size;
619 	break;
620     }
621 
622 #ifdef MALLOC_EXTRA_SANITY
623     if (p != NULL && page_dir[ptr2idx(p)] != MALLOC_FREE)
624 	wrterror("(ES): allocated non-free page on free-list.\n");
625 #endif /* MALLOC_EXTRA_SANITY */
626 
627     size >>= malloc_pageshift;
628 
629     /* Map new pages */
630     if (p == NULL)
631 	p = map_pages(size);
632 
633     if (p != NULL) {
634 
635 	idx = ptr2idx(p);
636 	page_dir[idx] = MALLOC_FIRST;
637 	for (i=1;i<size;i++)
638 	    page_dir[idx+i] = MALLOC_FOLLOW;
639 
640 	if (malloc_junk)
641 	    memset(p, SOME_JUNK, size << malloc_pageshift);
642     }
643 
644     if (delay_free) {
645 	if (px == NULL)
646 	    px = delay_free;
647 	else
648 	    ifree(delay_free);
649     }
650 
651     return p;
652 }
653 
654 /*
655  * Allocate a page of fragments
656  */
657 
658 static inline int
659 malloc_make_chunks(int bits)
660 {
661     struct  pginfo *bp;
662     void *pp;
663     int i, k;
664     long l;
665 
666     /* Allocate a new bucket */
667     pp = malloc_pages(malloc_pagesize);
668     if (pp == NULL)
669 	return 0;
670 
671     /* Find length of admin structure */
672     l = (long)offsetof(struct pginfo, bits[0]);
673     l += (long)sizeof bp->bits[0] *
674 	(((malloc_pagesize >> bits)+MALLOC_BITS-1) / MALLOC_BITS);
675 
676     /* Don't waste more than two chunks on this */
677     if ((1<<(bits)) <= l+l) {
678 	bp = (struct  pginfo *)pp;
679     } else {
680 	bp = imalloc((size_t)l);
681 	if (bp == NULL) {
682 	    ifree(pp);
683 	    return 0;
684 	}
685     }
686 
687     bp->size = (1<<bits);
688     bp->shift = bits;
689     bp->total = bp->free = (u_short)(malloc_pagesize >> bits);
690     bp->page = pp;
691 
692     /* set all valid bits in the bitmap */
693     k = bp->total;
694     i = 0;
695 
696     /* Do a bunch at a time */
697     for(;k-i >= MALLOC_BITS; i += MALLOC_BITS)
698 	bp->bits[i / MALLOC_BITS] = ~0U;
699 
700     for(; i < k; i++)
701         bp->bits[i/MALLOC_BITS] |= 1<<(i%MALLOC_BITS);
702 
703     if (bp == bp->page) {
704 	/* Mark the ones we stole for ourselves */
705 	for(i = 0; l > 0; i++) {
706 	    bp->bits[i / MALLOC_BITS] &= ~(1 << (i % MALLOC_BITS));
707 	    bp->free--;
708 	    bp->total--;
709 	    l -= (long)(1 << bits);
710 	}
711     }
712 
713     /* MALLOC_LOCK */
714 
715     page_dir[ptr2idx(pp)] = bp;
716 
717     bp->next = page_dir[bits];
718     page_dir[bits] = bp;
719 
720     /* MALLOC_UNLOCK */
721 
722     return 1;
723 }
724 
725 /*
726  * Allocate a fragment
727  */
728 static void *
729 malloc_bytes(size_t size)
730 {
731     size_t i;
732     int j;
733     u_int u;
734     struct  pginfo *bp;
735     size_t k;
736     u_int *lp;
737 
738     /* Don't bother with anything less than this */
739     if (size < malloc_minsize)
740 	size = malloc_minsize;
741 
742 
743     /* Find the right bucket */
744     j = 1;
745     i = size-1;
746     while (i >>= 1)
747 	j++;
748 
749     /* If it's empty, make a page more of that size chunks */
750     if (page_dir[j] == NULL && !malloc_make_chunks(j))
751 	return NULL;
752 
753     bp = page_dir[j];
754 
755     /* Find first word of bitmap which isn't empty */
756     for (lp = bp->bits; !*lp; lp++)
757 	;
758 
759     /* Find that bit, and tweak it */
760     u = 1;
761     k = 0;
762     while (!(*lp & u)) {
763 	u += u;
764 	k++;
765     }
766     *lp ^= u;
767 
768     /* If there are no more free, remove from free-list */
769     if (!--bp->free) {
770 	page_dir[j] = bp->next;
771 	bp->next = NULL;
772     }
773 
774     /* Adjust to the real offset of that chunk */
775     k += (lp-bp->bits)*MALLOC_BITS;
776     k <<= bp->shift;
777 
778     if (malloc_junk)
779 	memset((u_char*)bp->page + k, SOME_JUNK, (size_t)bp->size);
780 
781     return (u_char *)bp->page + k;
782 }
783 
784 /*
785  * Allocate a piece of memory
786  */
787 static void *
788 imalloc(size_t size)
789 {
790     void *result;
791 
792     if (suicide)
793 	abort();
794 
795     if ((size + malloc_pagesize) < size)	/* Check for overflow */
796 	result = NULL;
797     else if ((size + malloc_pagesize) >= (uintptr_t)page_dir)
798 	result = NULL;
799     else if (size <= malloc_maxsize)
800 	result = malloc_bytes(size);
801     else
802 	result = malloc_pages(size);
803 
804     if (malloc_abort && result == NULL)
805 	wrterror("allocation failed.\n");
806 
807     if (malloc_zero && result != NULL)
808 	memset(result, 0, size);
809 
810     return result;
811 }
812 
813 /*
814  * Change the size of an allocation.
815  */
816 static void *
817 irealloc(void *ptr, size_t size)
818 {
819     void *p;
820     size_t osize, idx;
821     struct pginfo **mp;
822     size_t i;
823 
824     if (suicide)
825 	abort();
826 
827     idx = ptr2idx(ptr);
828 
829     if (idx < malloc_pageshift) {
830 	wrtwarning("junk pointer, too low to make sense.\n");
831 	return 0;
832     }
833 
834     if (idx > last_idx) {
835 	wrtwarning("junk pointer, too high to make sense.\n");
836 	return 0;
837     }
838 
839     mp = &page_dir[idx];
840 
841     if (*mp == MALLOC_FIRST) {			/* Page allocation */
842 
843 	/* Check the pointer */
844 	if ((size_t)(uintptr_t)ptr & malloc_pagemask) {
845 	    wrtwarning("modified (page-) pointer.\n");
846 	    return NULL;
847 	}
848 
849 	/* Find the size in bytes */
850 	for (osize = malloc_pagesize; *++mp == MALLOC_FOLLOW;)
851 	    osize += malloc_pagesize;
852 
853         if (!malloc_realloc && 			/* unless we have to, */
854 	  size <= osize && 			/* .. or are too small, */
855 	  size > (osize - malloc_pagesize)) {	/* .. or can free a page, */
856 	    if (malloc_junk)
857 		memset((u_char *)ptr + size, SOME_JUNK, osize-size);
858 	    return ptr;				/* don't do anything. */
859 	}
860 
861     } else if (*mp >= MALLOC_MAGIC) {		/* Chunk allocation */
862 
863 	/* Check the pointer for sane values */
864 	if (((size_t)(uintptr_t)ptr & ((*mp)->size-1))) {
865 	    wrtwarning("modified (chunk-) pointer.\n");
866 	    return NULL;
867 	}
868 
869 	/* Find the chunk index in the page */
870 	i = ((size_t)(uintptr_t)ptr & malloc_pagemask) >> (*mp)->shift;
871 
872 	/* Verify that it isn't a free chunk already */
873         if ((*mp)->bits[i/MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) {
874 	    wrtwarning("chunk is already free.\n");
875 	    return NULL;
876 	}
877 
878 	osize = (*mp)->size;
879 
880 	if (!malloc_realloc &&		/* Unless we have to, */
881 	  size <= osize && 		/* ..or are too small, */
882 	  (size > osize / 2 ||	 	/* ..or could use a smaller size, */
883 	  osize == malloc_minsize)) {	/* ..(if there is one) */
884 	    if (malloc_junk)
885 		memset((u_char *)ptr + size, SOME_JUNK, osize-size);
886 	    return ptr;			/* ..Don't do anything */
887 	}
888 
889     } else {
890 	wrtwarning("pointer to wrong page.\n");
891 	return NULL;
892     }
893 
894     p = imalloc(size);
895 
896     if (p != NULL) {
897 	/* copy the lesser of the two sizes, and free the old one */
898 	if (!size || !osize)
899 	    ;
900 	else if (osize < size)
901 	    memcpy(p, ptr, osize);
902 	else
903 	    memcpy(p, ptr, size);
904 	ifree(ptr);
905     }
906     return p;
907 }
908 
909 /*
910  * Free a sequence of pages
911  */
912 
913 static inline void
914 free_pages(void *ptr, size_t idx, struct pginfo *info)
915 {
916     size_t i;
917     struct pgfree *pf, *pt=NULL;
918     size_t l;
919     void *tail;
920 
921     if (info == MALLOC_FREE) {
922 	wrtwarning("page is already free.\n");
923 	return;
924     }
925 
926     if (info != MALLOC_FIRST) {
927 	wrtwarning("pointer to wrong page.\n");
928 	return;
929     }
930 
931     if ((size_t)(uintptr_t)ptr & malloc_pagemask) {
932 	wrtwarning("modified (page-) pointer.\n");
933 	return;
934     }
935 
936     /* Count how many pages and mark them free at the same time */
937     page_dir[idx] = MALLOC_FREE;
938     for (i = 1; page_dir[idx+i] == MALLOC_FOLLOW; i++)
939 	page_dir[idx + i] = MALLOC_FREE;
940 
941     l = i << malloc_pageshift;
942 
943     if (malloc_junk)
944 	memset(ptr, SOME_JUNK, l);
945 
946 #ifndef __minix
947     if (malloc_hint)
948 	madvise(ptr, l, MADV_FREE);
949 #endif /* !__minix */
950 
951     tail = (char *)ptr+l;
952 
953     /* add to free-list */
954     if (px == NULL)
955 	px = imalloc(sizeof *px);	/* This cannot fail... */
956     px->page = ptr;
957     px->end =  tail;
958     px->size = l;
959     if (free_list.next == NULL) {
960 
961 	/* Nothing on free list, put this at head */
962 	px->next = free_list.next;
963 	px->prev = &free_list;
964 	free_list.next = px;
965 	pf = px;
966 	px = NULL;
967 
968     } else {
969 
970 	/* Find the right spot, leave pf pointing to the modified entry. */
971 	tail = (char *)ptr+l;
972 
973 	for(pf = free_list.next; pf->end < ptr && pf->next != NULL;
974 	    pf = pf->next)
975 	    ; /* Race ahead here */
976 
977 	if (pf->page > tail) {
978 	    /* Insert before entry */
979 	    px->next = pf;
980 	    px->prev = pf->prev;
981 	    pf->prev = px;
982 	    px->prev->next = px;
983 	    pf = px;
984 	    px = NULL;
985 	} else if (pf->end == ptr ) {
986 	    /* Append to the previous entry */
987 	    pf->end = (char *)pf->end + l;
988 	    pf->size += l;
989 	    if (pf->next != NULL && pf->end == pf->next->page ) {
990 		/* And collapse the next too. */
991 		pt = pf->next;
992 		pf->end = pt->end;
993 		pf->size += pt->size;
994 		pf->next = pt->next;
995 		if (pf->next != NULL)
996 		    pf->next->prev = pf;
997 	    }
998 	} else if (pf->page == tail) {
999 	    /* Prepend to entry */
1000 	    pf->size += l;
1001 	    pf->page = ptr;
1002 	} else if (pf->next == NULL) {
1003 	    /* Append at tail of chain */
1004 	    px->next = NULL;
1005 	    px->prev = pf;
1006 	    pf->next = px;
1007 	    pf = px;
1008 	    px = NULL;
1009 	} else {
1010 	    wrterror("freelist is destroyed.\n");
1011 	}
1012     }
1013 
1014     /* Return something to OS ? */
1015     if (pf->next == NULL &&			/* If we're the last one, */
1016       pf->size > malloc_cache &&		/* ..and the cache is full, */
1017       pf->end == malloc_brk &&			/* ..and none behind us, */
1018       malloc_brk == sbrk((intptr_t)0)) {	/* ..and it's OK to do... */
1019 
1020 	/*
1021 	 * Keep the cache intact.  Notice that the '>' above guarantees that
1022 	 * the pf will always have at least one page afterwards.
1023 	 */
1024 	pf->end = (char *)pf->page + malloc_cache;
1025 	pf->size = malloc_cache;
1026 
1027 	brk(pf->end);
1028 	malloc_brk = pf->end;
1029 
1030 	idx = ptr2idx(pf->end);
1031 
1032 	for(i=idx;i <= last_idx;)
1033 	    page_dir[i++] = MALLOC_NOT_MINE;
1034 
1035 	last_idx = idx - 1;
1036 
1037 	/* XXX: We could realloc/shrink the pagedir here I guess. */
1038     }
1039     if (pt != NULL)
1040 	ifree(pt);
1041 }
1042 
1043 /*
1044  * Free a chunk, and possibly the page it's on, if the page becomes empty.
1045  */
1046 
1047 static inline void
1048 free_bytes(void *ptr, size_t idx, struct pginfo *info)
1049 {
1050     size_t i;
1051     struct pginfo **mp;
1052     void *vp;
1053 
1054     /* Find the chunk number on the page */
1055     i = ((size_t)(uintptr_t)ptr & malloc_pagemask) >> info->shift;
1056 
1057     if (((size_t)(uintptr_t)ptr & (info->size-1))) {
1058 	wrtwarning("modified (chunk-) pointer.\n");
1059 	return;
1060     }
1061 
1062     if (info->bits[i/MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) {
1063 	wrtwarning("chunk is already free.\n");
1064 	return;
1065     }
1066 
1067     if (malloc_junk)
1068 	memset(ptr, SOME_JUNK, (size_t)info->size);
1069 
1070     info->bits[i/MALLOC_BITS] |= (u_int)(1UL << (i % MALLOC_BITS));
1071     info->free++;
1072 
1073     mp = page_dir + info->shift;
1074 
1075     if (info->free == 1) {
1076 
1077 	/* Page became non-full */
1078 
1079 	mp = page_dir + info->shift;
1080 	/* Insert in address order */
1081 	while (*mp && (*mp)->next && (*mp)->next->page < info->page)
1082 	    mp = &(*mp)->next;
1083 	info->next = *mp;
1084 	*mp = info;
1085 	return;
1086     }
1087 
1088     if (info->free != info->total)
1089 	return;
1090 
1091     /* Find & remove this page in the queue */
1092     while (*mp != info) {
1093 	mp = &((*mp)->next);
1094 #ifdef MALLOC_EXTRA_SANITY
1095 	if (!*mp)
1096 		wrterror("(ES): Not on queue.\n");
1097 #endif /* MALLOC_EXTRA_SANITY */
1098     }
1099     *mp = info->next;
1100 
1101     /* Free the page & the info structure if need be */
1102     page_dir[idx] = MALLOC_FIRST;
1103     vp = info->page;		/* Order is important ! */
1104     if(vp != (void*)info)
1105 	ifree(info);
1106     ifree(vp);
1107 }
1108 
1109 static void
1110 ifree(void *ptr)
1111 {
1112     struct pginfo *info;
1113     size_t idx;
1114 
1115     /* This is legal */
1116     if (ptr == NULL)
1117 	return;
1118 
1119     /* If we're already sinking, don't make matters any worse. */
1120     if (suicide)
1121 	return;
1122 
1123     idx = ptr2idx(ptr);
1124 
1125     if (idx < malloc_pageshift) {
1126 	wrtwarning("junk pointer, too low to make sense.\n");
1127 	return;
1128     }
1129 
1130     if (idx > last_idx) {
1131 	wrtwarning("junk pointer, too high to make sense.\n");
1132 	return;
1133     }
1134 
1135     info = page_dir[idx];
1136 
1137     if (info < MALLOC_MAGIC)
1138         free_pages(ptr, idx, info);
1139     else
1140 	free_bytes(ptr, idx, info);
1141     return;
1142 }
1143 
1144 static int malloc_active; /* Recusion flag for public interface. */
1145 static unsigned malloc_started; /* Set when initialization has been done */
1146 
1147 static void *
1148 pubrealloc(void *ptr, size_t size, const char *func)
1149 {
1150     void *r;
1151     int err = 0;
1152 
1153     /*
1154      * If a thread is inside our code with a functional lock held, and then
1155      * catches a signal which calls us again, we would get a deadlock if the
1156      * lock is not of a recursive type.
1157      */
1158     _MALLOC_LOCK();
1159     malloc_func = func;
1160     if (malloc_active > 0) {
1161 	if (malloc_active == 1) {
1162 	    wrtwarning("recursive call\n");
1163 	    malloc_active = 2;
1164 	}
1165         _MALLOC_UNLOCK();
1166 	errno = EINVAL;
1167 	return (NULL);
1168     }
1169     malloc_active = 1;
1170 
1171     if (!malloc_started) {
1172         if (ptr != NULL) {
1173 	    wrtwarning("malloc() has never been called\n");
1174 	    malloc_active = 0;
1175             _MALLOC_UNLOCK();
1176 	    errno = EINVAL;
1177 	    return (NULL);
1178 	}
1179 	malloc_init();
1180 	malloc_started = 1;
1181     }
1182 
1183     if (ptr == ZEROSIZEPTR)
1184 	ptr = NULL;
1185     if (malloc_sysv && !size) {
1186 	if (ptr != NULL)
1187 	    ifree(ptr);
1188 	r = NULL;
1189     } else if (!size) {
1190 	if (ptr != NULL)
1191 	    ifree(ptr);
1192 	r = ZEROSIZEPTR;
1193     } else if (ptr == NULL) {
1194 	r = imalloc(size);
1195 	err = (r == NULL);
1196     } else {
1197         r = irealloc(ptr, size);
1198 	err = (r == NULL);
1199     }
1200     UTRACE(ptr, size, r);
1201     malloc_active = 0;
1202     _MALLOC_UNLOCK();
1203     if (malloc_xmalloc && err)
1204 	wrterror("out of memory\n");
1205     if (err)
1206 	errno = ENOMEM;
1207     return (r);
1208 }
1209 
1210 /*
1211  * These are the public exported interface routines.
1212  */
1213 
1214 void *
1215 malloc(size_t size)
1216 {
1217 
1218     return pubrealloc(NULL, size, " in malloc():");
1219 }
1220 
1221 int
1222 posix_memalign(void **memptr, size_t alignment, size_t size)
1223 {
1224     int err;
1225     void *result;
1226 
1227     if (!malloc_started) {
1228 	    malloc_init();
1229 	    malloc_started = 1;
1230     }
1231     /* Make sure that alignment is a large enough power of 2. */
1232     if (((alignment - 1) & alignment) != 0 || alignment < sizeof(void *) ||
1233 	alignment > malloc_pagesize)
1234 	    return EINVAL;
1235 
1236     /*
1237      * (size | alignment) is enough to assure the requested alignment, since
1238      * the allocator always allocates power-of-two blocks.
1239      */
1240     err = errno; /* Protect errno against changes in pubrealloc(). */
1241     result = pubrealloc(NULL, (size | alignment), " in posix_memalign()");
1242     errno = err;
1243 
1244     if (result == NULL)
1245 	return ENOMEM;
1246 
1247     *memptr = result;
1248     return 0;
1249 }
1250 
1251 void *
1252 calloc(size_t num, size_t size)
1253 {
1254     void *ret;
1255 
1256     if (size != 0 && (num * size) / size != num) {
1257 	/* size_t overflow. */
1258 	errno = ENOMEM;
1259 	return (NULL);
1260     }
1261 
1262     ret = pubrealloc(NULL, num * size, " in calloc():");
1263 
1264     if (ret != NULL)
1265 	memset(ret, 0, num * size);
1266 
1267     return ret;
1268 }
1269 
1270 void
1271 free(void *ptr)
1272 {
1273 
1274     pubrealloc(ptr, 0, " in free():");
1275 }
1276 
1277 void *
1278 realloc(void *ptr, size_t size)
1279 {
1280 
1281     return pubrealloc(ptr, size, " in realloc():");
1282 }
1283 
1284 /*
1285  * Begin library-private functions, used by threading libraries for protection
1286  * of malloc during fork().  These functions are only called if the program is
1287  * running in threaded mode, so there is no need to check whether the program
1288  * is threaded here.
1289  */
1290 
1291 void
1292 _malloc_prefork(void)
1293 {
1294 
1295 	_MALLOC_LOCK();
1296 }
1297 
1298 void
1299 _malloc_postfork(void)
1300 {
1301 
1302 	_MALLOC_UNLOCK();
1303 }
1304