1 /* Version 1.83 for Linux.
2 * Compilation: gcc -shared -fPIC -O2 OpenBSD_malloc_Linux.c -o malloc.so
3 * Launching: LD_PRELOAD=/path/to/malloc.so firefox
6 /* $OpenBSD: malloc.c,v 1.83 2006/05/14 19:53:40 otto Exp $ */
9 * ----------------------------------------------------------------------------
10 * "THE BEER-WARE LICENSE" (Revision 42):
11 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
12 * can do whatever you want with this stuff. If we meet some day, and you think
13 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
14 * ----------------------------------------------------------------------------
18 * Defining MALLOC_EXTRA_SANITY will enable extra checks which are
19 * related to internal conditions and consistency in malloc.c. This has
20 * a noticeable runtime performance hit, and generally will not do you
21 * any good unless you fiddle with the internals of malloc or want
22 * to catch random pointer corruption as early as possible.
24 #ifndef MALLOC_EXTRA_SANITY
25 #undef MALLOC_EXTRA_SANITY
29 * Defining MALLOC_STATS will enable you to call malloc_dump() and set
30 * the [dD] options in the MALLOC_OPTIONS environment variable.
31 * It has no run-time performance hit, but does pull in stdio...
38 * What to use for Junk. This is the byte value we use to fill with
39 * when the 'J' option is enabled.
41 #define SOME_JUNK 0xd0 /* as in "Duh" :-) */
43 #include <sys/types.h>
45 #include <sys/resource.h>
46 #include <sys/param.h>
60 //#include "thread_private.h"
63 * The basic parameters you can tweak.
65 * malloc_pageshift pagesize = 1 << malloc_pageshift
66 * It's probably best if this is the native
67 * page size, but it shouldn't have to be.
69 * malloc_minsize minimum size of an allocation in bytes.
70 * If this is too small it's too much work
71 * to manage them. This is also the smallest
72 * unit of alignment used for the storage
73 * returned by malloc/realloc.
78 static size_t g_alignment
= 0;
80 extern int __libc_enable_secure
;
82 static int issetugid(void)
84 if (__libc_enable_secure
) return 1;
85 if (getuid() != geteuid()) return 1;
86 if (getgid() != getegid()) return 1;
91 #define MADV_FREE MADV_DONTNEED
93 static pthread_mutex_t gen_mutex
= PTHREAD_MUTEX_INITIALIZER
;
95 #define _MALLOC_LOCK_INIT() {;}
96 #define _MALLOC_LOCK() {pthread_mutex_lock(&gen_mutex);}
97 #define _MALLOC_UNLOCK() {pthread_mutex_unlock(&gen_mutex);}
99 #if defined(__sparc__) || defined(__alpha__)
100 #define malloc_pageshift 13U
102 #if defined(__ia64__)
103 #define malloc_pageshift 14U
106 #ifndef malloc_pageshift
107 #define malloc_pageshift (PGSHIFT)
111 * No user serviceable parts behind this point.
113 * This structure describes a page worth of chunks.
116 struct pginfo
*next
; /* next on the free list */
117 void *page
; /* Pointer to the page */
118 u_short size
; /* size of this page's chunks */
119 u_short shift
; /* How far to shift for this size chunks */
120 u_short free
; /* How many free chunks */
121 u_short total
; /* How many chunk */
122 u_long bits
[1];/* Which chunks are free */
125 /* How many bits per u_long in the bitmap */
126 #define MALLOC_BITS (int)((NBBY * sizeof(u_long)))
129 * This structure describes a number of free pages.
132 struct pgfree
*next
; /* next run of free pages */
133 struct pgfree
*prev
; /* prev run of free pages */
134 void *page
; /* pointer to free pages */
135 void *pdir
; /* pointer to the base page's dir */
136 size_t size
; /* number of bytes free */
140 * Magic values to put in the page_directory
142 #define MALLOC_NOT_MINE ((struct pginfo*) 0)
143 #define MALLOC_FREE ((struct pginfo*) 1)
144 #define MALLOC_FIRST ((struct pginfo*) 2)
145 #define MALLOC_FOLLOW ((struct pginfo*) 3)
146 #define MALLOC_MAGIC ((struct pginfo*) 4)
148 #ifndef malloc_minsize
149 #define malloc_minsize 16UL
152 #if !defined(malloc_pagesize)
153 #define malloc_pagesize (1UL<<malloc_pageshift)
156 #if ((1UL<<malloc_pageshift) != malloc_pagesize)
157 #error "(1UL<<malloc_pageshift) != malloc_pagesize"
160 #ifndef malloc_maxsize
161 #define malloc_maxsize ((malloc_pagesize)>>1)
164 /* A mask for the offset inside a page. */
165 #define malloc_pagemask ((malloc_pagesize)-1)
167 #define pageround(foo) (((foo) + (malloc_pagemask)) & ~malloc_pagemask)
168 #define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)+malloc_pageshift)
169 #define index2ptr(idx) ((void*)(((idx)-malloc_pageshift)<<malloc_pageshift))
171 /* Set when initialization has been done */
172 static unsigned int malloc_started
;
174 /* Number of free pages we cache */
175 static unsigned int malloc_cache
= 16;
177 /* Structure used for linking discrete directory pages. */
179 struct pginfo
**base
;
184 static struct pdinfo
*last_dir
; /* Caches to the last and previous */
185 static struct pdinfo
*prev_dir
; /* referenced directory pages. */
187 static size_t pdi_off
;
188 static u_long pdi_mod
;
189 #define PD_IDX(num) ((num) / (malloc_pagesize/sizeof(struct pginfo *)))
190 #define PD_OFF(num) ((num) & ((malloc_pagesize/sizeof(struct pginfo *))-1))
191 #define PI_IDX(index) ((index) / pdi_mod)
192 #define PI_OFF(index) ((index) % pdi_mod)
194 /* The last index in the page directory we care about */
195 static u_long last_index
;
197 /* Pointer to page directory. Allocated "as if with" malloc */
198 static struct pginfo
**page_dir
;
200 /* Free pages line up here */
201 static struct pgfree free_list
;
203 /* Abort(), user doesn't handle problems. */
204 static int malloc_abort
= 2;
206 /* Are we trying to die ? */
210 /* dump statistics */
211 static int malloc_stats
;
214 /* avoid outputting warnings? */
215 static int malloc_silent
;
217 /* always realloc ? */
218 static int malloc_realloc
;
220 /* mprotect free pages PROT_NONE? */
221 static int malloc_freeprot
;
223 /* use guard pages after allocations? */
224 static size_t malloc_guard
= 0;
225 static size_t malloc_guarded
;
226 /* align pointers to end of page? */
227 static int malloc_ptrguard
;
229 static int malloc_hint
= 1;
231 /* xmalloc behaviour ? */
232 static int malloc_xmalloc
;
235 static int malloc_zero
;
238 static int malloc_junk
;
242 static int malloc_utrace
;
250 void utrace(struct ut
*, int);
252 #define UTRACE(a, b, c) \
254 {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);}
255 #else /* !__FreeBSD__ */
256 #define UTRACE(a,b,c)
259 /* Status of malloc. */
260 static int malloc_active
;
262 /* Allocated memory. */
263 static size_t malloc_used
;
266 static caddr_t malloc_brk
;
268 /* One location cache for free-list holders. */
269 static struct pgfree
*px
;
271 /* Compile-time options. */
272 char *malloc_options
;
274 /* Name of the current public function. */
275 static const char *malloc_func
;
278 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
282 * Necessary function declarations.
284 static void *imalloc(size_t size
);
285 static void ifree(void *ptr
);
286 static void *irealloc(void *ptr
, size_t size
);
287 static void *malloc_bytes(size_t size
);
290 * Function for page directory lookup.
293 pdir_lookup(u_long index
, struct pdinfo
** pdi
)
296 u_long pidx
= PI_IDX(index
);
298 if (last_dir
!= NULL
&& PD_IDX(last_dir
->dirnum
) == pidx
)
300 else if (prev_dir
!= NULL
&& PD_IDX(prev_dir
->dirnum
) == pidx
)
302 else if (last_dir
!= NULL
&& prev_dir
!= NULL
) {
303 if ((PD_IDX(last_dir
->dirnum
) > pidx
) ?
304 (PD_IDX(last_dir
->dirnum
) - pidx
) :
305 (pidx
- PD_IDX(last_dir
->dirnum
))
306 < (PD_IDX(prev_dir
->dirnum
) > pidx
) ?
307 (PD_IDX(prev_dir
->dirnum
) - pidx
) :
308 (pidx
- PD_IDX(prev_dir
->dirnum
)))
313 if (PD_IDX((*pdi
)->dirnum
) > pidx
) {
314 for (spi
= (*pdi
)->prev
;
315 spi
!= NULL
&& PD_IDX(spi
->dirnum
) > pidx
;
321 for (spi
= (*pdi
)->next
;
322 spi
!= NULL
&& PD_IDX(spi
->dirnum
) <= pidx
;
326 *pdi
= (struct pdinfo
*) ((caddr_t
) page_dir
+ pdi_off
);
328 spi
!= NULL
&& PD_IDX(spi
->dirnum
) <= pidx
;
333 return ((PD_IDX((*pdi
)->dirnum
) == pidx
) ? 0 :
334 (PD_IDX((*pdi
)->dirnum
) > pidx
) ? 1 : -1);
348 pi
= (struct pdinfo
*) ((caddr_t
) pd
+ pdi_off
);
350 /* print out all the pages */
351 for (j
= 0; j
<= last_index
;) {
352 snprintf(buf
, sizeof buf
, "%08lx %5lu ", j
<< malloc_pageshift
, j
);
353 write(fd
, buf
, strlen(buf
));
354 if (pd
[PI_OFF(j
)] == MALLOC_NOT_MINE
) {
355 for (j
++; j
<= last_index
&& pd
[PI_OFF(j
)] == MALLOC_NOT_MINE
;) {
357 if ((pi
= pi
->next
) == NULL
||
358 PD_IDX(pi
->dirnum
) != PI_IDX(j
))
365 snprintf(buf
, sizeof buf
, ".. %5lu not mine\n", j
);
366 write(fd
, buf
, strlen(buf
));
367 } else if (pd
[PI_OFF(j
)] == MALLOC_FREE
) {
368 for (j
++; j
<= last_index
&& pd
[PI_OFF(j
)] == MALLOC_FREE
;) {
370 if ((pi
= pi
->next
) == NULL
||
371 PD_IDX(pi
->dirnum
) != PI_IDX(j
))
378 snprintf(buf
, sizeof buf
, ".. %5lu free\n", j
);
379 write(fd
, buf
, strlen(buf
));
380 } else if (pd
[PI_OFF(j
)] == MALLOC_FIRST
) {
381 for (j
++; j
<= last_index
&& pd
[PI_OFF(j
)] == MALLOC_FOLLOW
;) {
383 if ((pi
= pi
->next
) == NULL
||
384 PD_IDX(pi
->dirnum
) != PI_IDX(j
))
391 snprintf(buf
, sizeof buf
, ".. %5lu in use\n", j
);
392 write(fd
, buf
, strlen(buf
));
393 } else if (pd
[PI_OFF(j
)] < MALLOC_MAGIC
) {
394 snprintf(buf
, sizeof buf
, "(%p)\n", pd
[PI_OFF(j
)]);
395 write(fd
, buf
, strlen(buf
));
397 snprintf(buf
, sizeof buf
, "%p %d (of %d) x %d @ %p --> %p\n",
398 pd
[PI_OFF(j
)], pd
[PI_OFF(j
)]->free
,
399 pd
[PI_OFF(j
)]->total
, pd
[PI_OFF(j
)]->size
,
400 pd
[PI_OFF(j
)]->page
, pd
[PI_OFF(j
)]->next
);
401 write(fd
, buf
, strlen(buf
));
404 if ((pi
= pi
->next
) == NULL
)
407 j
+= (1 + PD_IDX(pi
->dirnum
) - PI_IDX(j
)) * pdi_mod
;
411 for (pf
= free_list
.next
; pf
; pf
= pf
->next
) {
412 snprintf(buf
, sizeof buf
, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
413 pf
, pf
->page
, (char *)pf
->page
+ pf
->size
,
414 pf
->size
, pf
->prev
, pf
->next
);
415 write(fd
, buf
, strlen(buf
));
416 if (pf
== pf
->next
) {
417 snprintf(buf
, sizeof buf
, "Free_list loops\n");
418 write(fd
, buf
, strlen(buf
));
423 /* print out various info */
424 snprintf(buf
, sizeof buf
, "Minsize\t%lu\n", malloc_minsize
);
425 write(fd
, buf
, strlen(buf
));
426 snprintf(buf
, sizeof buf
, "Maxsize\t%lu\n", malloc_maxsize
);
427 write(fd
, buf
, strlen(buf
));
428 snprintf(buf
, sizeof buf
, "Pagesize\t%lu\n", malloc_pagesize
);
429 write(fd
, buf
, strlen(buf
));
430 snprintf(buf
, sizeof buf
, "Pageshift\t%u\n", malloc_pageshift
);
431 write(fd
, buf
, strlen(buf
));
432 snprintf(buf
, sizeof buf
, "In use\t%lu\n", (u_long
) malloc_used
);
433 write(fd
, buf
, strlen(buf
));
434 snprintf(buf
, sizeof buf
, "Guarded\t%lu\n", (u_long
) malloc_guarded
);
435 write(fd
, buf
, strlen(buf
));
437 #endif /* MALLOC_STATS */
439 extern char *__progname
;
442 wrterror(const char *p
)
444 const char *q
= " error: ";
447 iov
[0].iov_base
= __progname
;
448 iov
[0].iov_len
= strlen(__progname
);
449 iov
[1].iov_base
= (char*)malloc_func
;
450 iov
[1].iov_len
= strlen(malloc_func
);
451 iov
[2].iov_base
= (char*)q
;
452 iov
[2].iov_len
= strlen(q
);
453 iov
[3].iov_base
= (char*)p
;
454 iov
[3].iov_len
= strlen(p
);
455 iov
[4].iov_base
= (char*)"\n";
457 writev(STDERR_FILENO
, iov
, 5);
462 malloc_dump(STDERR_FILENO
);
463 #endif /* MALLOC_STATS */
470 wrtwarning(const char *p
)
472 const char *q
= " warning: ";
477 else if (malloc_silent
)
480 iov
[0].iov_base
= __progname
;
481 iov
[0].iov_len
= strlen(__progname
);
482 iov
[1].iov_base
= (char*)malloc_func
;
483 iov
[1].iov_len
= strlen(malloc_func
);
484 iov
[2].iov_base
= (char*)q
;
485 iov
[2].iov_len
= strlen(q
);
486 iov
[3].iov_base
= (char*)p
;
487 iov
[3].iov_len
= strlen(p
);
488 iov
[4].iov_base
= (char*)"\n";
491 writev(STDERR_FILENO
, iov
, 5);
498 char *q
= "malloc() warning: Couldn't dump stats\n";
499 int save_errno
= errno
, fd
;
501 fd
= open("malloc.out", O_RDWR
|O_APPEND
);
506 write(STDERR_FILENO
, q
, strlen(q
));
509 #endif /* MALLOC_STATS */
512 * Allocate aligned mmaped chunk
515 static void *MMAP_A(size_t pages
, size_t alignment
)
518 size_t first_size
, rest
, begin
, end
;
519 if (pages
%malloc_pagesize
!= 0)
520 pages
= pages
- pages
%malloc_pagesize
+ malloc_pagesize
;
521 first_size
= pages
+ alignment
- malloc_pagesize
;
522 p
= MMAP(first_size
);
523 rest
= ((size_t)p
) % alignment
;
524 j
= (rest
== 0) ? p
: (void*) ((size_t)p
+ alignment
- rest
);
525 begin
= (size_t)j
- (size_t)p
;
526 if (begin
!= 0) munmap(p
, begin
);
527 end
= (size_t)p
+ first_size
- ((size_t)j
+ pages
);
528 if(end
!= 0) munmap( (void*) ((size_t)j
+ pages
), end
);
535 * Allocate a number of pages from the OS
538 map_pages(size_t pages
)
540 struct pdinfo
*pi
, *spi
;
542 u_long idx
, pidx
, lidx
;
543 caddr_t result
, tail
;
544 u_long index
, lindex
;
545 void *pdregion
= NULL
;
548 pages
<<= malloc_pageshift
;
550 result
= MMAP(pages
+ malloc_guard
);
552 result
= MMAP_A(pages
+ malloc_guard
, g_alignment
);
554 if (result
== MAP_FAILED
) {
555 #ifdef MALLOC_EXTRA_SANITY
556 wrtwarning("(ES): map_pages fails");
557 #endif /* MALLOC_EXTRA_SANITY */
561 index
= ptr2index(result
);
562 tail
= result
+ pages
+ malloc_guard
;
563 lindex
= ptr2index(tail
) - 1;
565 mprotect(result
+ pages
, malloc_guard
, PROT_NONE
);
567 pidx
= PI_IDX(index
);
568 lidx
= PI_IDX(lindex
);
570 if (tail
> malloc_brk
) {
577 /* Insert directory pages, if needed. */
578 if (pdir_lookup(index
, &pi
) != 0)
582 pdregion
= MMAP(malloc_pagesize
* dirs
);
583 if (pdregion
== MAP_FAILED
) {
584 munmap(result
, tail
- result
);
585 #ifdef MALLOC_EXTRA_SANITY
586 wrtwarning("(ES): map_pages fails");
594 for (idx
= pidx
, spi
= pi
; idx
<= lidx
; idx
++) {
595 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != idx
) {
596 pd
= (struct pginfo
**)((char *)pdregion
+
597 cnt
* malloc_pagesize
);
599 memset(pd
, 0, malloc_pagesize
);
600 pi
= (struct pdinfo
*) ((caddr_t
) pd
+ pdi_off
);
603 pi
->next
= spi
->next
;
604 pi
->dirnum
= idx
* (malloc_pagesize
/
605 sizeof(struct pginfo
*));
607 if (spi
->next
!= NULL
)
608 spi
->next
->prev
= pi
;
611 if (idx
> pidx
&& idx
< lidx
) {
612 pi
->dirnum
+= pdi_mod
;
613 } else if (idx
== pidx
) {
615 pi
->dirnum
+= (u_long
)(tail
- result
) >>
618 pi
->dirnum
+= pdi_mod
- PI_OFF(index
);
621 pi
->dirnum
+= PI_OFF(ptr2index(tail
- 1)) + 1;
623 #ifdef MALLOC_EXTRA_SANITY
624 if (PD_OFF(pi
->dirnum
) > pdi_mod
|| PD_IDX(pi
->dirnum
) > idx
) {
625 wrterror("(ES): pages directory overflow");
629 #endif /* MALLOC_EXTRA_SANITY */
630 if (idx
== pidx
&& pi
!= last_dir
) {
637 #ifdef MALLOC_EXTRA_SANITY
639 wrtwarning("(ES): cnt > dirs");
640 #endif /* MALLOC_EXTRA_SANITY */
642 munmap((char *)pdregion
+ cnt
* malloc_pagesize
,
643 (dirs
- cnt
) * malloc_pagesize
);
649 * Initialize the world
655 int i
, j
, save_errno
= errno
;
659 #ifdef MALLOC_EXTRA_SANITY
661 #endif /* MALLOC_EXTRA_SANITY */
663 for (i
= 0; i
< 3; i
++) {
666 j
= readlink("/etc/malloc.conf", b
, sizeof b
- 1);
673 if (issetugid() == 0)
674 p
= getenv("MALLOC_OPTIONS");
685 for (; p
!= NULL
&& *p
!= '\0'; p
++) {
706 #endif /* MALLOC_STATS */
717 malloc_guard
= malloc_pagesize
;
756 #endif /* __FreeBSD__ */
772 wrtwarning("unknown char in MALLOC_OPTIONS");
782 * We want junk in the entire allocation, and zero only in the part
783 * the user asked for.
789 if (malloc_stats
&& (atexit(malloc_exit
) == -1))
790 wrtwarning("atexit(2) failed."
791 " Will not be able to dump malloc stats on exit");
792 #endif /* MALLOC_STATS */
794 if (malloc_pagesize
!= getpagesize()) {
795 wrterror("malloc() replacement compiled with a different "
796 "page size from what we're running with. Failing.");
801 /* Allocate one page for the page directory. */
802 page_dir
= (struct pginfo
**)MMAP(malloc_pagesize
);
804 if (page_dir
== MAP_FAILED
) {
805 wrterror("mmap(2) failed, check limits");
809 pdi_off
= (malloc_pagesize
- sizeof(struct pdinfo
)) & ~(malloc_minsize
- 1);
810 pdi_mod
= pdi_off
/ sizeof(struct pginfo
*);
812 last_dir
= (struct pdinfo
*) ((caddr_t
) page_dir
+ pdi_off
);
813 last_dir
->base
= page_dir
;
814 last_dir
->prev
= last_dir
->next
= NULL
;
815 last_dir
->dirnum
= malloc_pageshift
;
817 /* Been here, done that. */
820 /* Recalculate the cache size in bytes, and make sure it's nonzero. */
823 malloc_cache
<<= malloc_pageshift
;
828 * Allocate a number of complete pages
831 malloc_pages(size_t size
)
833 void *p
, *delay_free
= NULL
, *tp
;
840 size
= pageround(size
) + malloc_guard
;
843 /* Look for free pages before asking for more */
845 for (pf
= free_list
.next
; pf
; pf
= pf
->next
) {
847 #ifdef MALLOC_EXTRA_SANITY
848 if (pf
->size
& malloc_pagemask
) {
849 wrterror("(ES): junk length entry on free_list");
854 wrterror("(ES): zero length entry on free_list");
858 if (pf
->page
> (pf
->page
+ pf
->size
)) {
859 wrterror("(ES): sick entry on free_list");
863 if ((pi
= pf
->pdir
) == NULL
) {
864 wrterror("(ES): invalid page directory on free-list");
868 if ((pidx
= PI_IDX(ptr2index(pf
->page
))) != PD_IDX(pi
->dirnum
)) {
869 wrterror("(ES): directory index mismatch on free-list");
874 if (pd
[PI_OFF(ptr2index(pf
->page
))] != MALLOC_FREE
) {
875 wrterror("(ES): non-free first page on free-list");
879 pidx
= PI_IDX(ptr2index((pf
->page
) + (pf
->size
)) - 1);
880 for (pi
= pf
->pdir
; pi
!= NULL
&& PD_IDX(pi
->dirnum
) < pidx
;
883 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
884 wrterror("(ES): last page not referenced in page directory");
889 if (pd
[PI_OFF(ptr2index((pf
->page
) + (pf
->size
)) - 1)] != MALLOC_FREE
) {
890 wrterror("(ES): non-free last page on free-list");
894 #endif /* MALLOC_EXTRA_SANITY */
899 if (pf
->size
== size
) {
902 if (pf
->next
!= NULL
)
903 pf
->next
->prev
= pf
->prev
;
904 pf
->prev
->next
= pf
->next
;
909 pf
->page
= (char *) pf
->page
+ size
;
911 pidx
= PI_IDX(ptr2index(pf
->page
));
912 for (pi
= pf
->pdir
; pi
!= NULL
&& PD_IDX(pi
->dirnum
) < pidx
;
915 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
916 wrterror("(ES): hole in directories");
926 size
-= malloc_guard
;
928 #ifdef MALLOC_EXTRA_SANITY
929 if (p
!= NULL
&& pi
!= NULL
) {
930 pidx
= PD_IDX(pi
->dirnum
);
933 if (p
!= NULL
&& pd
[PI_OFF(ptr2index(p
))] != MALLOC_FREE
) {
934 wrterror("(ES): allocated non-free page on free-list");
938 #endif /* MALLOC_EXTRA_SANITY */
940 if (p
!= NULL
&& (malloc_guard
|| malloc_freeprot
))
941 mprotect(p
, size
, PROT_READ
| PROT_WRITE
);
943 size
>>= malloc_pageshift
;
950 index
= ptr2index(p
);
951 pidx
= PI_IDX(index
);
952 pdir_lookup(index
, &pi
);
953 #ifdef MALLOC_EXTRA_SANITY
954 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
955 wrterror("(ES): mapped pages not found in directory");
959 #endif /* MALLOC_EXTRA_SANITY */
960 if (pi
!= last_dir
) {
965 pd
[PI_OFF(index
)] = MALLOC_FIRST
;
967 for (i
= 1; i
< size
; i
++) {
968 if (!PI_OFF(index
+ i
)) {
971 #ifdef MALLOC_EXTRA_SANITY
972 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
973 wrterror("(ES): hole in mapped pages directory");
977 #endif /* MALLOC_EXTRA_SANITY */
980 pd
[PI_OFF(index
+ i
)] = MALLOC_FOLLOW
;
983 if (!PI_OFF(index
+ i
)) {
986 #ifdef MALLOC_EXTRA_SANITY
987 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
988 wrterror("(ES): hole in mapped pages directory");
992 #endif /* MALLOC_EXTRA_SANITY */
995 pd
[PI_OFF(index
+ i
)] = MALLOC_FIRST
;
998 malloc_used
+= size
<< malloc_pageshift
;
999 malloc_guarded
+= malloc_guard
;
1002 memset(p
, SOME_JUNK
, size
<< malloc_pageshift
);
1014 * Allocate a page of fragments
1017 static __inline__
int
1018 malloc_make_chunks(int bits
)
1020 struct pginfo
*bp
, **pd
;
1022 #ifdef MALLOC_EXTRA_SANITY
1024 #endif /* MALLOC_EXTRA_SANITY */
1029 /* Allocate a new bucket */
1030 pp
= malloc_pages((size_t) malloc_pagesize
);
1034 /* Find length of admin structure */
1035 l
= sizeof *bp
- sizeof(u_long
);
1036 l
+= sizeof(u_long
) *
1037 (((malloc_pagesize
>> bits
) + MALLOC_BITS
- 1) / MALLOC_BITS
);
1039 /* Don't waste more than two chunks on this */
1042 * If we are to allocate a memory protected page for the malloc(0)
1043 * case (when bits=0), it must be from a different page than the
1045 * --> Treat it like the big chunk alloc, get a second data page.
1047 if (bits
!= 0 && (1UL << (bits
)) <= l
+ l
) {
1048 bp
= (struct pginfo
*) pp
;
1050 bp
= (struct pginfo
*) imalloc(l
);
1057 /* memory protect the page allocated in the malloc(0) case */
1061 i
= malloc_minsize
- 1;
1064 bp
->total
= bp
->free
= malloc_pagesize
>> bp
->shift
;
1067 k
= mprotect(pp
, malloc_pagesize
, PROT_NONE
);
1074 bp
->size
= (1UL << bits
);
1076 bp
->total
= bp
->free
= malloc_pagesize
>> bits
;
1080 /* set all valid bits in the bitmap */
1084 /* Do a bunch at a time */
1085 for (; (k
- i
) >= MALLOC_BITS
; i
+= MALLOC_BITS
)
1086 bp
->bits
[i
/ MALLOC_BITS
] = ~0UL;
1089 bp
->bits
[i
/ MALLOC_BITS
] |= 1UL << (i
% MALLOC_BITS
);
1092 if (bp
== bp
->page
) {
1093 /* Mark the ones we stole for ourselves */
1094 for (i
= 0; k
> 0; i
++) {
1095 bp
->bits
[i
/ MALLOC_BITS
] &= ~(1UL << (i
% MALLOC_BITS
));
1103 pdir_lookup(ptr2index(pp
), &pi
);
1104 #ifdef MALLOC_EXTRA_SANITY
1105 pidx
= PI_IDX(ptr2index(pp
));
1106 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
1107 wrterror("(ES): mapped pages not found in directory");
1111 #endif /* MALLOC_EXTRA_SANITY */
1112 if (pi
!= last_dir
) {
1113 prev_dir
= last_dir
;
1117 pd
[PI_OFF(ptr2index(pp
))] = bp
;
1119 bp
->next
= page_dir
[bits
];
1120 page_dir
[bits
] = bp
;
1127 * Allocate a fragment
1130 malloc_bytes(size_t size
)
1137 /* Don't bother with anything less than this */
1138 /* unless we have a malloc(0) requests */
1139 if (size
!= 0 && size
< malloc_minsize
)
1140 size
= malloc_minsize
;
1142 /* Find the right bucket */
1152 /* If it's empty, make a page more of that size chunks */
1153 if (page_dir
[j
] == NULL
&& !malloc_make_chunks(j
))
1158 /* Find first word of bitmap which isn't empty */
1159 for (lp
= bp
->bits
; !*lp
; lp
++);
1161 /* Find that bit, and tweak it */
1164 while (!(*lp
& u
)) {
1170 /* Walk to a random position. */
1171 // i = arc4random() % bp->free;
1172 i
= rand() % bp
->free
;
1176 if (k
>= MALLOC_BITS
) {
1181 #ifdef MALLOC_EXTRA_SANITY
1182 if (lp
- bp
->bits
> (bp
->total
- 1) / MALLOC_BITS
) {
1183 wrterror("chunk overflow");
1187 #endif /* MALLOC_EXTRA_SANITY */
1194 /* If there are no more free, remove from free-list */
1196 page_dir
[j
] = bp
->next
;
1199 /* Adjust to the real offset of that chunk */
1200 k
+= (lp
- bp
->bits
) * MALLOC_BITS
;
1203 if (malloc_junk
&& bp
->size
!= 0)
1204 memset((char *)bp
->page
+ k
, SOME_JUNK
, (size_t)bp
->size
);
1206 return ((u_char
*) bp
->page
+ k
);
1210 * Magic so that malloc(sizeof(ptr)) is near the end of the page.
1212 #define PTR_GAP (malloc_pagesize - sizeof(void *))
1213 #define PTR_SIZE (sizeof(void *))
1214 #define PTR_ALIGNED(p) (((unsigned long)p & malloc_pagemask) == PTR_GAP)
1217 * Allocate a piece of memory
1220 imalloc(size_t size
)
1225 if (!malloc_started
)
1231 /* does not matter if malloc_bytes fails */
1233 px
= malloc_bytes(sizeof *px
);
1235 if (malloc_ptrguard
&& size
== PTR_SIZE
) {
1237 size
= malloc_pagesize
;
1239 if ((size
+ malloc_pagesize
) < size
) { /* Check for overflow */
1242 } else if (size
<= malloc_maxsize
)
1243 result
= malloc_bytes(size
);
1245 result
= malloc_pages(size
);
1247 if (malloc_abort
== 1 && result
== NULL
)
1248 wrterror("allocation failed");
1250 if (malloc_zero
&& result
!= NULL
)
1251 memset(result
, 0, size
);
1253 if (result
&& ptralloc
)
1254 return ((char *) result
+ PTR_GAP
);
1259 * Change the size of an allocation.
1262 irealloc(void *ptr
, size_t size
)
1270 #ifdef MALLOC_EXTRA_SANITY
1272 #endif /* MALLOC_EXTRA_SANITY */
1277 if (!malloc_started
) {
1278 wrtwarning("malloc() has never been called");
1281 if (malloc_ptrguard
&& PTR_ALIGNED(ptr
)) {
1282 if (size
<= PTR_SIZE
)
1287 memcpy(p
, ptr
, PTR_SIZE
);
1291 index
= ptr2index(ptr
);
1293 if (index
< malloc_pageshift
) {
1294 wrtwarning("junk pointer, too low to make sense");
1297 if (index
> last_index
) {
1298 wrtwarning("junk pointer, too high to make sense");
1301 pdir_lookup(index
, &pi
);
1302 #ifdef MALLOC_EXTRA_SANITY
1303 pidx
= PI_IDX(index
);
1304 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
1305 wrterror("(ES): mapped pages not found in directory");
1309 #endif /* MALLOC_EXTRA_SANITY */
1310 if (pi
!= last_dir
) {
1311 prev_dir
= last_dir
;
1315 mp
= &pd
[PI_OFF(index
)];
1317 if (*mp
== MALLOC_FIRST
) { /* Page allocation */
1319 /* Check the pointer */
1320 if ((u_long
) ptr
& malloc_pagemask
) {
1321 wrtwarning("modified (page-) pointer");
1324 /* Find the size in bytes */
1328 if (pi
!= NULL
&& PD_IDX(pi
->dirnum
) != PI_IDX(i
))
1333 for (osize
= malloc_pagesize
;
1334 pi
!= NULL
&& pd
[PI_OFF(i
)] == MALLOC_FOLLOW
;) {
1335 osize
+= malloc_pagesize
;
1338 if (pi
!= NULL
&& PD_IDX(pi
->dirnum
) != PI_IDX(i
))
1345 if (!malloc_realloc
&& size
<= osize
&&
1346 size
> osize
- malloc_pagesize
) {
1348 memset((char *)ptr
+ size
, SOME_JUNK
, osize
- size
);
1349 return (ptr
); /* ..don't do anything else. */
1351 } else if (*mp
>= MALLOC_MAGIC
) { /* Chunk allocation */
1353 /* Check the pointer for sane values */
1354 if ((u_long
) ptr
& ((1UL << ((*mp
)->shift
)) - 1)) {
1355 wrtwarning("modified (chunk-) pointer");
1358 /* Find the chunk index in the page */
1359 i
= ((u_long
) ptr
& malloc_pagemask
) >> (*mp
)->shift
;
1361 /* Verify that it isn't a free chunk already */
1362 if ((*mp
)->bits
[i
/ MALLOC_BITS
] & (1UL << (i
% MALLOC_BITS
))) {
1363 wrtwarning("chunk is already free");
1366 osize
= (*mp
)->size
;
1368 if (!malloc_realloc
&& size
<= osize
&&
1369 (size
> osize
/ 2 || osize
== malloc_minsize
)) {
1371 memset((char *) ptr
+ size
, SOME_JUNK
, osize
- size
);
1372 return (ptr
); /* ..don't do anything else. */
1375 wrtwarning("irealloc: pointer to wrong page");
1382 /* copy the lesser of the two sizes, and free the old one */
1383 /* Don't move from/to 0 sized region !!! */
1384 if (osize
!= 0 && size
!= 0) {
1386 memcpy(p
, ptr
, osize
);
1388 memcpy(p
, ptr
, size
);
1396 * Free a sequence of pages
1398 static __inline__
void
1399 free_pages(void *ptr
, u_long index
, struct pginfo
* info
)
1401 u_long i
, pidx
, lidx
;
1402 size_t l
, cachesize
= 0;
1404 struct pdinfo
*pi
, *spi
;
1405 struct pgfree
*pf
, *pt
= NULL
;
1408 if (info
== MALLOC_FREE
) {
1409 wrtwarning("page is already free");
1412 if (info
!= MALLOC_FIRST
) {
1413 wrtwarning("free_pages: pointer to wrong page");
1416 if ((u_long
) ptr
& malloc_pagemask
) {
1417 wrtwarning("modified (page-) pointer");
1420 /* Count how many pages and mark them free at the same time */
1421 pidx
= PI_IDX(index
);
1422 pdir_lookup(index
, &pi
);
1423 #ifdef MALLOC_EXTRA_SANITY
1424 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
1425 wrterror("(ES): mapped pages not found in directory");
1429 #endif /* MALLOC_EXTRA_SANITY */
1431 spi
= pi
; /* Save page index for start of region. */
1434 pd
[PI_OFF(index
)] = MALLOC_FREE
;
1436 if (!PI_OFF(index
+ i
)) {
1438 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != PI_IDX(index
+ i
))
1443 while (pi
!= NULL
&& pd
[PI_OFF(index
+ i
)] == MALLOC_FOLLOW
) {
1444 pd
[PI_OFF(index
+ i
)] = MALLOC_FREE
;
1446 if (!PI_OFF(index
+ i
)) {
1447 if ((pi
= pi
->next
) == NULL
||
1448 PD_IDX(pi
->dirnum
) != PI_IDX(index
+ i
))
1455 l
= i
<< malloc_pageshift
;
1458 memset(ptr
, SOME_JUNK
, l
);
1461 malloc_guarded
-= malloc_guard
;
1463 #ifdef MALLOC_EXTRA_SANITY
1464 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != PI_IDX(index
+ i
)) {
1465 wrterror("(ES): hole in mapped pages directory");
1469 #endif /* MALLOC_EXTRA_SANITY */
1470 pd
[PI_OFF(index
+ i
)] = MALLOC_FREE
;
1473 tail
= (caddr_t
)ptr
+ l
;
1476 madvise(ptr
, l
, MADV_FREE
);
1478 if (malloc_freeprot
)
1479 mprotect(ptr
, l
, PROT_NONE
);
1481 /* Add to free-list. */
1482 if (px
== NULL
&& (px
= malloc_bytes(sizeof *px
)) == NULL
)
1488 if (free_list
.next
== NULL
) {
1489 /* Nothing on free list, put this at head. */
1491 px
->prev
= &free_list
;
1492 free_list
.next
= px
;
1497 * Find the right spot, leave pf pointing to the modified
1501 /* Race ahead here, while calculating cache size. */
1502 for (pf
= free_list
.next
;
1503 (caddr_t
)ptr
> ((caddr_t
)pf
->page
+ pf
->size
)
1504 && pf
->next
!= NULL
;
1506 cachesize
+= pf
->size
;
1508 /* Finish cache size calculation. */
1511 cachesize
+= pt
->size
;
1515 if ((caddr_t
)pf
->page
> tail
) {
1516 /* Insert before entry */
1518 px
->prev
= pf
->prev
;
1520 px
->prev
->next
= px
;
1523 } else if (((caddr_t
)pf
->page
+ pf
->size
) == ptr
) {
1524 /* Append to the previous entry. */
1525 cachesize
-= pf
->size
;
1527 if (pf
->next
!= NULL
&&
1528 pf
->next
->page
== ((caddr_t
)pf
->page
+ pf
->size
)) {
1529 /* And collapse the next too. */
1531 pf
->size
+= pt
->size
;
1532 pf
->next
= pt
->next
;
1533 if (pf
->next
!= NULL
)
1534 pf
->next
->prev
= pf
;
1536 } else if (pf
->page
== tail
) {
1537 /* Prepend to entry. */
1538 cachesize
-= pf
->size
;
1542 } else if (pf
->next
== NULL
) {
1543 /* Append at tail of chain. */
1550 wrterror("freelist is destroyed");
1556 if (pf
->pdir
!= last_dir
) {
1557 prev_dir
= last_dir
;
1558 last_dir
= pf
->pdir
;
1561 /* Return something to OS ? */
1562 if (pf
->size
> (malloc_cache
- cachesize
)) {
1565 * Keep the cache intact. Notice that the '>' above guarantees that
1566 * the pf will always have at least one page afterwards.
1568 if (munmap((char *) pf
->page
+ (malloc_cache
- cachesize
),
1569 pf
->size
- (malloc_cache
- cachesize
)) != 0)
1571 tail
= (caddr_t
)pf
->page
+ pf
->size
;
1572 lidx
= ptr2index(tail
) - 1;
1573 pf
->size
= malloc_cache
- cachesize
;
1575 index
= ptr2index((caddr_t
)pf
->page
+ pf
->size
);
1577 pidx
= PI_IDX(index
);
1578 if (prev_dir
!= NULL
&& PD_IDX(prev_dir
->dirnum
) >= pidx
)
1579 prev_dir
= NULL
; /* Will be wiped out below ! */
1581 for (pi
= pf
->pdir
; pi
!= NULL
&& PD_IDX(pi
->dirnum
) < pidx
;
1586 if (pi
!= NULL
&& PD_IDX(pi
->dirnum
) == pidx
) {
1589 for (i
= index
; i
<= lidx
;) {
1590 if (pd
[PI_OFF(i
)] != MALLOC_NOT_MINE
) {
1591 pd
[PI_OFF(i
)] = MALLOC_NOT_MINE
;
1592 #ifdef MALLOC_EXTRA_SANITY
1593 if (!PD_OFF(pi
->dirnum
)) {
1594 wrterror("(ES): pages directory underflow");
1598 #endif /* MALLOC_EXTRA_SANITY */
1601 #ifdef MALLOC_EXTRA_SANITY
1603 wrtwarning("(ES): page already unmapped");
1604 #endif /* MALLOC_EXTRA_SANITY */
1608 * If no page in that dir, free
1611 if (!PD_OFF(pi
->dirnum
)) {
1612 /* Remove from list. */
1615 if (pi
->prev
!= NULL
)
1616 pi
->prev
->next
= pi
->next
;
1617 if (pi
->next
!= NULL
)
1618 pi
->next
->prev
= pi
->prev
;
1620 munmap(pd
, malloc_pagesize
);
1624 PD_IDX(pi
->dirnum
) != PI_IDX(i
))
1629 if (pi
&& !PD_OFF(pi
->dirnum
)) {
1630 /* Resulting page dir is now empty. */
1631 /* Remove from list. */
1632 if (spi
== pi
) /* Update spi only if first. */
1634 if (pi
->prev
!= NULL
)
1635 pi
->prev
->next
= pi
->next
;
1636 if (pi
->next
!= NULL
)
1637 pi
->next
->prev
= pi
->prev
;
1639 munmap(pd
, malloc_pagesize
);
1642 if (pi
== NULL
&& malloc_brk
== tail
) {
1643 /* Resize down the malloc upper boundary. */
1644 last_index
= index
- 1;
1645 malloc_brk
= index2ptr(index
);
1648 /* XXX: We could realloc/shrink the pagedir here I guess. */
1649 if (pf
->size
== 0) { /* Remove from free-list as well. */
1652 if ((px
= pf
->prev
) != &free_list
) {
1653 if (pi
== NULL
&& last_index
== (index
- 1)) {
1659 if (PD_IDX(spi
->dirnum
) < pidx
)
1661 ((PD_IDX(spi
->dirnum
) + 1) *
1663 for (pi
= spi
, i
= index
;
1664 pd
[PI_OFF(i
)] == MALLOC_NOT_MINE
;
1666 #ifdef MALLOC_EXTRA_SANITY
1669 if (pi
== NULL
|| i
== 0)
1672 i
= (PD_IDX(pi
->dirnum
) + 1) * pdi_mod
;
1674 #else /* !MALLOC_EXTRA_SANITY */
1677 #endif /* MALLOC_EXTRA_SANITY */
1678 malloc_brk
= index2ptr(i
+ 1);
1682 if ((px
->next
= pf
->next
) != NULL
)
1683 px
->next
->prev
= px
;
1685 if ((free_list
.next
= pf
->next
) != NULL
)
1686 free_list
.next
->prev
= &free_list
;
1689 last_dir
= prev_dir
;
1699 * Free a chunk, and possibly the page it's on, if the page becomes empty.
1703 static __inline__
void
1704 free_bytes(void *ptr
, u_long index
, struct pginfo
* info
)
1706 struct pginfo
**mp
, **pd
;
1708 #ifdef MALLOC_EXTRA_SANITY
1710 #endif /* MALLOC_EXTRA_SANITY */
1715 /* Find the chunk number on the page */
1716 i
= ((u_long
) ptr
& malloc_pagemask
) >> info
->shift
;
1718 if ((u_long
) ptr
& ((1UL << (info
->shift
)) - 1)) {
1719 wrtwarning("modified (chunk-) pointer");
1722 if (info
->bits
[i
/ MALLOC_BITS
] & (1UL << (i
% MALLOC_BITS
))) {
1723 wrtwarning("chunk is already free");
1726 if (malloc_junk
&& info
->size
!= 0)
1727 memset(ptr
, SOME_JUNK
, (size_t)info
->size
);
1729 info
->bits
[i
/ MALLOC_BITS
] |= 1UL << (i
% MALLOC_BITS
);
1732 if (info
->size
!= 0)
1733 mp
= page_dir
+ info
->shift
;
1737 if (info
->free
== 1) {
1738 /* Page became non-full */
1740 /* Insert in address order */
1741 while (*mp
!= NULL
&& (*mp
)->next
!= NULL
&&
1742 (*mp
)->next
->page
< info
->page
)
1748 if (info
->free
!= info
->total
)
1751 /* Find & remove this page in the queue */
1752 while (*mp
!= info
) {
1753 mp
= &((*mp
)->next
);
1754 #ifdef MALLOC_EXTRA_SANITY
1756 wrterror("(ES): Not on queue");
1760 #endif /* MALLOC_EXTRA_SANITY */
1764 /* Free the page & the info structure if need be */
1765 pdir_lookup(ptr2index(info
->page
), &pi
);
1766 #ifdef MALLOC_EXTRA_SANITY
1767 pidx
= PI_IDX(ptr2index(info
->page
));
1768 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
1769 wrterror("(ES): mapped pages not found in directory");
1773 #endif /* MALLOC_EXTRA_SANITY */
1774 if (pi
!= last_dir
) {
1775 prev_dir
= last_dir
;
1779 pd
[PI_OFF(ptr2index(info
->page
))] = MALLOC_FIRST
;
1781 /* If the page was mprotected, unprotect it before releasing it */
1782 if (info
->size
== 0)
1783 mprotect(info
->page
, malloc_pagesize
, PROT_READ
| PROT_WRITE
);
1785 vp
= info
->page
; /* Order is important ! */
1786 if (vp
!= (void *) info
)
1794 struct pginfo
*info
, **pd
;
1796 #ifdef MALLOC_EXTRA_SANITY
1798 #endif /* MALLOC_EXTRA_SANITY */
1801 if (!malloc_started
) {
1802 wrtwarning("malloc() has never been called");
1805 /* If we're already sinking, don't make matters any worse. */
1809 if (malloc_ptrguard
&& PTR_ALIGNED(ptr
))
1810 ptr
= (char *) ptr
- PTR_GAP
;
1812 index
= ptr2index(ptr
);
1814 if (index
< malloc_pageshift
) {
1816 wrtwarning("ifree: junk pointer, too low to make sense");
1819 if (index
> last_index
) {
1821 wrtwarning("ifree: junk pointer, too high to make sense");
1824 pdir_lookup(index
, &pi
);
1825 #ifdef MALLOC_EXTRA_SANITY
1826 pidx
= PI_IDX(index
);
1827 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
1828 wrterror("(ES): mapped pages not found in directory");
1832 #endif /* MALLOC_EXTRA_SANITY */
1833 if (pi
!= last_dir
) {
1834 prev_dir
= last_dir
;
1838 info
= pd
[PI_OFF(index
)];
1840 if (info
< MALLOC_MAGIC
)
1841 free_pages(ptr
, index
, info
);
1843 free_bytes(ptr
, index
, info
);
1845 /* does not matter if malloc_bytes fails */
1847 px
= malloc_bytes(sizeof *px
);
1853 * Common function for handling recursion. Only
1854 * print the error message once, to avoid making the problem
1855 * potentially worse.
1858 malloc_recurse(void)
1864 wrtwarning("recursive call");
1872 * These are the public exported interface routines.
1881 malloc_func
= " in malloc():";
1882 if (malloc_active
++) {
1891 if (malloc_xmalloc
&& r
== NULL
) {
1892 wrterror("out of memory");
1901 /* This is legal. XXX quick path */
1906 malloc_func
= " in free():";
1907 if (malloc_active
++) {
1919 realloc(void *ptr
, size_t size
)
1924 malloc_func
= " in realloc():";
1925 if (malloc_active
++) {
1933 r
= irealloc(ptr
, size
);
1935 UTRACE(ptr
, size
, r
);
1938 if (malloc_xmalloc
&& r
== NULL
) {
1939 wrterror("out of memory");
1946 //#if defined(__i386__)||defined(__arm__)||defined(__powerpc__)
1947 //#define SIZE_MAX 0xffffffff
1949 //#if defined(__x86_64__)
1950 //#define SIZE_MAX 0xffffffffffffffff
1952 #define SIZE_MAX SIZE_T_MAX
1956 calloc(size_t num
, size_t size
)
1960 if (num
&& SIZE_MAX
/ num
< size
) {
1961 fprintf(stderr
,"OOOOPS");
1972 static int ispowerof2 (size_t a
) {
1974 for (b
= 1ULL << (sizeof(size_t)*NBBY
- 1); b
> 1; b
>>= 1)
1980 int posix_memalign(void **memptr
, size_t alignment
, size_t size
)
1983 if ((alignment
< PTR_SIZE
) || (alignment
%PTR_SIZE
!= 0)) return EINVAL
;
1984 if (!ispowerof2(alignment
)) return EINVAL
;
1985 if (alignment
< malloc_minsize
) alignment
= malloc_minsize
;
1986 size_t max
= alignment
> size
? alignment
: size
;
1987 if (alignment
<= malloc_pagesize
)
1992 g_alignment
= alignment
;
1998 if (!r
) return ENOMEM
;
2002 void *memalign(size_t boundary
, size_t size
)
2005 posix_memalign(&r
, boundary
, size
);
2009 void *valloc(size_t size
)
2012 posix_memalign(&r
, malloc_pagesize
, size
);
2016 size_t malloc_good_size(size_t size
)
2020 } else if (size
<= malloc_maxsize
) {
2022 /* round up to the nearest power of 2, with same approach
2023 * as malloc_bytes() uses. */
2028 return ((size_t)1) << j
;
2030 return pageround(size
);