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 * ----------------------------------------------------------------------------
17 /* We use this macro to remove some code that we don't actually want,
18 * rather than to fix its warnings. */
19 #define BUILDING_FOR_TOR
22 * Defining MALLOC_EXTRA_SANITY will enable extra checks which are
23 * related to internal conditions and consistency in malloc.c. This has
24 * a noticeable runtime performance hit, and generally will not do you
25 * any good unless you fiddle with the internals of malloc or want
26 * to catch random pointer corruption as early as possible.
28 #ifndef MALLOC_EXTRA_SANITY
29 #undef MALLOC_EXTRA_SANITY
33 * Defining MALLOC_STATS will enable you to call malloc_dump() and set
34 * the [dD] options in the MALLOC_OPTIONS environment variable.
35 * It has no run-time performance hit, but does pull in stdio...
42 * What to use for Junk. This is the byte value we use to fill with
43 * when the 'J' option is enabled.
45 #define SOME_JUNK 0xd0 /* as in "Duh" :-) */
47 #include <sys/types.h>
49 #include <sys/resource.h>
50 #include <sys/param.h>
62 #include "lib/cc/torint.h"
64 //#include "thread_private.h"
67 * The basic parameters you can tweak.
69 * malloc_pageshift pagesize = 1 << malloc_pageshift
70 * It's probably best if this is the native
71 * page size, but it shouldn't have to be.
73 * malloc_minsize minimum size of an allocation in bytes.
74 * If this is too small it's too much work
75 * to manage them. This is also the smallest
76 * unit of alignment used for the storage
77 * returned by malloc/realloc.
82 static size_t g_alignment
= 0;
84 extern int __libc_enable_secure
;
86 #ifndef HAVE_ISSETUGID
87 static int issetugid(void)
89 if (__libc_enable_secure
) return 1;
90 if (getuid() != geteuid()) return 1;
91 if (getgid() != getegid()) return 1;
98 #define MADV_FREE MADV_DONTNEED
100 static pthread_mutex_t gen_mutex
= PTHREAD_MUTEX_INITIALIZER
;
102 #define _MALLOC_LOCK_INIT() {;}
103 #define _MALLOC_LOCK() {pthread_mutex_lock(&gen_mutex);}
104 #define _MALLOC_UNLOCK() {pthread_mutex_unlock(&gen_mutex);}
106 #if defined(__sparc__) || defined(__alpha__)
107 #define malloc_pageshift 13U
109 #if defined(__ia64__)
110 #define malloc_pageshift 14U
113 #ifndef malloc_pageshift
114 #define malloc_pageshift (PGSHIFT)
118 * No user serviceable parts behind this point.
120 * This structure describes a page worth of chunks.
123 struct pginfo
*next
; /* next on the free list */
124 void *page
; /* Pointer to the page */
125 u_short size
; /* size of this page's chunks */
126 u_short shift
; /* How far to shift for this size chunks */
127 u_short free
; /* How many free chunks */
128 u_short total
; /* How many chunk */
129 u_long bits
[1];/* Which chunks are free */
132 /* How many bits per u_long in the bitmap */
133 #define MALLOC_BITS (int)((NBBY * sizeof(u_long)))
136 * This structure describes a number of free pages.
139 struct pgfree
*next
; /* next run of free pages */
140 struct pgfree
*prev
; /* prev run of free pages */
141 void *page
; /* pointer to free pages */
142 void *pdir
; /* pointer to the base page's dir */
143 size_t size
; /* number of bytes free */
147 * Magic values to put in the page_directory
149 #define MALLOC_NOT_MINE ((struct pginfo*) 0)
150 #define MALLOC_FREE ((struct pginfo*) 1)
151 #define MALLOC_FIRST ((struct pginfo*) 2)
152 #define MALLOC_FOLLOW ((struct pginfo*) 3)
153 #define MALLOC_MAGIC ((struct pginfo*) 4)
155 #ifndef malloc_minsize
156 #define malloc_minsize 16UL
159 #if !defined(malloc_pagesize)
160 #define malloc_pagesize (1UL<<malloc_pageshift)
163 #if ((1UL<<malloc_pageshift) != malloc_pagesize)
164 #error "(1UL<<malloc_pageshift) != malloc_pagesize"
167 #ifndef malloc_maxsize
168 #define malloc_maxsize ((malloc_pagesize)>>1)
171 /* A mask for the offset inside a page. */
172 #define malloc_pagemask ((malloc_pagesize)-1)
174 #define pageround(foo) (((foo) + (malloc_pagemask)) & ~malloc_pagemask)
175 #define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)+malloc_pageshift)
176 #define index2ptr(idx) ((void*)(((idx)-malloc_pageshift)<<malloc_pageshift))
178 /* Set when initialization has been done */
179 static unsigned int malloc_started
;
181 /* Number of free pages we cache */
182 static unsigned int malloc_cache
= 16;
184 /* Structure used for linking discrete directory pages. */
186 struct pginfo
**base
;
191 static struct pdinfo
*last_dir
; /* Caches to the last and previous */
192 static struct pdinfo
*prev_dir
; /* referenced directory pages. */
194 static size_t pdi_off
;
195 static u_long pdi_mod
;
196 #define PD_IDX(num) ((num) / (malloc_pagesize/sizeof(struct pginfo *)))
197 #define PD_OFF(num) ((num) & ((malloc_pagesize/sizeof(struct pginfo *))-1))
198 #define PI_IDX(index) ((index) / pdi_mod)
199 #define PI_OFF(index) ((index) % pdi_mod)
201 /* The last index in the page directory we care about */
202 static u_long last_index
;
204 /* Pointer to page directory. Allocated "as if with" malloc */
205 static struct pginfo
**page_dir
;
207 /* Free pages line up here */
208 static struct pgfree free_list
;
210 /* Abort(), user doesn't handle problems. */
211 static int malloc_abort
= 2;
213 /* Are we trying to die ? */
217 /* dump statistics */
218 static int malloc_stats
;
221 /* avoid outputting warnings? */
222 static int malloc_silent
;
224 /* always realloc ? */
225 static int malloc_realloc
;
227 /* mprotect free pages PROT_NONE? */
228 static int malloc_freeprot
;
230 /* use guard pages after allocations? */
231 static size_t malloc_guard
= 0;
232 static size_t malloc_guarded
;
233 /* align pointers to end of page? */
234 static int malloc_ptrguard
;
236 static int malloc_hint
= 1;
238 /* xmalloc behaviour ? */
239 static int malloc_xmalloc
;
242 static int malloc_zero
;
245 static int malloc_junk
;
249 static int malloc_utrace
;
257 void utrace(struct ut
*, int);
259 #define UTRACE(a, b, c) \
261 {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);}
262 #else /* !__FreeBSD__ */
263 #define UTRACE(a,b,c)
266 /* Status of malloc. */
267 static int malloc_active
;
269 /* Allocated memory. */
270 static size_t malloc_used
;
273 static caddr_t malloc_brk
;
275 /* One location cache for free-list holders. */
276 static struct pgfree
*px
;
278 /* Compile-time options. */
279 char *malloc_options
;
281 /* Name of the current public function. */
282 static const char *malloc_func
;
285 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
289 * Necessary function declarations.
291 static void *imalloc(size_t size
);
292 static void ifree(void *ptr
);
293 static void *irealloc(void *ptr
, size_t size
);
294 static void *malloc_bytes(size_t size
);
295 void *memalign(size_t boundary
, size_t size
);
296 size_t malloc_good_size(size_t size
);
299 * Function for page directory lookup.
302 pdir_lookup(u_long index
, struct pdinfo
** pdi
)
305 u_long pidx
= PI_IDX(index
);
307 if (last_dir
!= NULL
&& PD_IDX(last_dir
->dirnum
) == pidx
)
309 else if (prev_dir
!= NULL
&& PD_IDX(prev_dir
->dirnum
) == pidx
)
311 else if (last_dir
!= NULL
&& prev_dir
!= NULL
) {
312 if ((PD_IDX(last_dir
->dirnum
) > pidx
) ?
313 (PD_IDX(last_dir
->dirnum
) - pidx
) :
314 (pidx
- PD_IDX(last_dir
->dirnum
))
315 < (PD_IDX(prev_dir
->dirnum
) > pidx
) ?
316 (PD_IDX(prev_dir
->dirnum
) - pidx
) :
317 (pidx
- PD_IDX(prev_dir
->dirnum
)))
322 if (PD_IDX((*pdi
)->dirnum
) > pidx
) {
323 for (spi
= (*pdi
)->prev
;
324 spi
!= NULL
&& PD_IDX(spi
->dirnum
) > pidx
;
330 for (spi
= (*pdi
)->next
;
331 spi
!= NULL
&& PD_IDX(spi
->dirnum
) <= pidx
;
335 *pdi
= (struct pdinfo
*) ((caddr_t
) page_dir
+ pdi_off
);
337 spi
!= NULL
&& PD_IDX(spi
->dirnum
) <= pidx
;
342 return ((PD_IDX((*pdi
)->dirnum
) == pidx
) ? 0 :
343 (PD_IDX((*pdi
)->dirnum
) > pidx
) ? 1 : -1);
357 pi
= (struct pdinfo
*) ((caddr_t
) pd
+ pdi_off
);
359 /* print out all the pages */
360 for (j
= 0; j
<= last_index
;) {
361 snprintf(buf
, sizeof buf
, "%08lx %5lu ", j
<< malloc_pageshift
, j
);
362 write(fd
, buf
, strlen(buf
));
363 if (pd
[PI_OFF(j
)] == MALLOC_NOT_MINE
) {
364 for (j
++; j
<= last_index
&& pd
[PI_OFF(j
)] == MALLOC_NOT_MINE
;) {
366 if ((pi
= pi
->next
) == NULL
||
367 PD_IDX(pi
->dirnum
) != PI_IDX(j
))
374 snprintf(buf
, sizeof buf
, ".. %5lu not mine\n", j
);
375 write(fd
, buf
, strlen(buf
));
376 } else if (pd
[PI_OFF(j
)] == MALLOC_FREE
) {
377 for (j
++; j
<= last_index
&& pd
[PI_OFF(j
)] == MALLOC_FREE
;) {
379 if ((pi
= pi
->next
) == NULL
||
380 PD_IDX(pi
->dirnum
) != PI_IDX(j
))
387 snprintf(buf
, sizeof buf
, ".. %5lu free\n", j
);
388 write(fd
, buf
, strlen(buf
));
389 } else if (pd
[PI_OFF(j
)] == MALLOC_FIRST
) {
390 for (j
++; j
<= last_index
&& pd
[PI_OFF(j
)] == MALLOC_FOLLOW
;) {
392 if ((pi
= pi
->next
) == NULL
||
393 PD_IDX(pi
->dirnum
) != PI_IDX(j
))
400 snprintf(buf
, sizeof buf
, ".. %5lu in use\n", j
);
401 write(fd
, buf
, strlen(buf
));
402 } else if (pd
[PI_OFF(j
)] < MALLOC_MAGIC
) {
403 snprintf(buf
, sizeof buf
, "(%p)\n", pd
[PI_OFF(j
)]);
404 write(fd
, buf
, strlen(buf
));
406 snprintf(buf
, sizeof buf
, "%p %d (of %d) x %d @ %p --> %p\n",
407 pd
[PI_OFF(j
)], pd
[PI_OFF(j
)]->free
,
408 pd
[PI_OFF(j
)]->total
, pd
[PI_OFF(j
)]->size
,
409 pd
[PI_OFF(j
)]->page
, pd
[PI_OFF(j
)]->next
);
410 write(fd
, buf
, strlen(buf
));
413 if ((pi
= pi
->next
) == NULL
)
416 j
+= (1 + PD_IDX(pi
->dirnum
) - PI_IDX(j
)) * pdi_mod
;
420 for (pf
= free_list
.next
; pf
; pf
= pf
->next
) {
421 snprintf(buf
, sizeof buf
, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
422 pf
, pf
->page
, (char *)pf
->page
+ pf
->size
,
423 pf
->size
, pf
->prev
, pf
->next
);
424 write(fd
, buf
, strlen(buf
));
425 if (pf
== pf
->next
) {
426 snprintf(buf
, sizeof buf
, "Free_list loops\n");
427 write(fd
, buf
, strlen(buf
));
432 /* print out various info */
433 snprintf(buf
, sizeof buf
, "Minsize\t%lu\n", malloc_minsize
);
434 write(fd
, buf
, strlen(buf
));
435 snprintf(buf
, sizeof buf
, "Maxsize\t%lu\n", malloc_maxsize
);
436 write(fd
, buf
, strlen(buf
));
437 snprintf(buf
, sizeof buf
, "Pagesize\t%lu\n", malloc_pagesize
);
438 write(fd
, buf
, strlen(buf
));
439 snprintf(buf
, sizeof buf
, "Pageshift\t%u\n", malloc_pageshift
);
440 write(fd
, buf
, strlen(buf
));
441 snprintf(buf
, sizeof buf
, "In use\t%lu\n", (u_long
) malloc_used
);
442 write(fd
, buf
, strlen(buf
));
443 snprintf(buf
, sizeof buf
, "Guarded\t%lu\n", (u_long
) malloc_guarded
);
444 write(fd
, buf
, strlen(buf
));
446 #endif /* MALLOC_STATS */
448 extern char *__progname
;
451 wrterror(const char *p
)
453 #ifndef BUILDING_FOR_TOR
454 const char *q
= " error: ";
457 iov
[0].iov_base
= __progname
;
458 iov
[0].iov_len
= strlen(__progname
);
459 iov
[1].iov_base
= (char*)malloc_func
;
460 iov
[1].iov_len
= strlen(malloc_func
);
461 iov
[2].iov_base
= (char*)q
;
462 iov
[2].iov_len
= strlen(q
);
463 iov
[3].iov_base
= (char*)p
;
464 iov
[3].iov_len
= strlen(p
);
465 iov
[4].iov_base
= (char*)"\n";
467 writev(STDERR_FILENO
, iov
, 5);
474 malloc_dump(STDERR_FILENO
);
475 #endif /* MALLOC_STATS */
482 wrtwarning(const char *p
)
484 #ifndef BUILDING_FOR_TOR
485 const char *q
= " warning: ";
491 else if (malloc_silent
)
494 #ifndef BUILDING_FOR_TOR
495 iov
[0].iov_base
= __progname
;
496 iov
[0].iov_len
= strlen(__progname
);
497 iov
[1].iov_base
= (char*)malloc_func
;
498 iov
[1].iov_len
= strlen(malloc_func
);
499 iov
[2].iov_base
= (char*)q
;
500 iov
[2].iov_len
= strlen(q
);
501 iov
[3].iov_base
= (char*)p
;
502 iov
[3].iov_len
= strlen(p
);
503 iov
[4].iov_base
= (char*)"\n";
506 (void) writev(STDERR_FILENO
, iov
, 5);
516 char *q
= "malloc() warning: Couldn't dump stats\n";
517 int save_errno
= errno
, fd
;
519 fd
= open("malloc.out", O_RDWR
|O_APPEND
);
524 write(STDERR_FILENO
, q
, strlen(q
));
527 #endif /* MALLOC_STATS */
530 * Allocate aligned mmaped chunk
533 static void *MMAP_A(size_t pages
, size_t alignment
)
536 size_t first_size
, rest
, begin
, end
;
537 if (pages
%malloc_pagesize
!= 0)
538 pages
= pages
- pages
%malloc_pagesize
+ malloc_pagesize
;
539 first_size
= pages
+ alignment
- malloc_pagesize
;
540 p
= MMAP(first_size
);
541 rest
= ((size_t)p
) % alignment
;
542 j
= (rest
== 0) ? p
: (void*) ((size_t)p
+ alignment
- rest
);
543 begin
= (size_t)j
- (size_t)p
;
544 if (begin
!= 0) munmap(p
, begin
);
545 end
= (size_t)p
+ first_size
- ((size_t)j
+ pages
);
546 if(end
!= 0) munmap( (void*) ((size_t)j
+ pages
), end
);
553 * Allocate a number of pages from the OS
556 map_pages(size_t pages
)
558 struct pdinfo
*pi
, *spi
;
560 u_long idx
, pidx
, lidx
;
561 caddr_t result
, tail
;
562 u_long index
, lindex
;
563 void *pdregion
= NULL
;
566 pages
<<= malloc_pageshift
;
568 result
= MMAP(pages
+ malloc_guard
);
570 result
= MMAP_A(pages
+ malloc_guard
, g_alignment
);
572 if (result
== MAP_FAILED
) {
573 #ifdef MALLOC_EXTRA_SANITY
574 wrtwarning("(ES): map_pages fails");
575 #endif /* MALLOC_EXTRA_SANITY */
579 index
= ptr2index(result
);
580 tail
= result
+ pages
+ malloc_guard
;
581 lindex
= ptr2index(tail
) - 1;
583 mprotect(result
+ pages
, malloc_guard
, PROT_NONE
);
585 pidx
= PI_IDX(index
);
586 lidx
= PI_IDX(lindex
);
588 if (tail
> malloc_brk
) {
595 /* Insert directory pages, if needed. */
596 if (pdir_lookup(index
, &pi
) != 0)
600 pdregion
= MMAP(malloc_pagesize
* dirs
);
601 if (pdregion
== MAP_FAILED
) {
602 munmap(result
, tail
- result
);
603 #ifdef MALLOC_EXTRA_SANITY
604 wrtwarning("(ES): map_pages fails");
612 for (idx
= pidx
, spi
= pi
; idx
<= lidx
; idx
++) {
613 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != idx
) {
614 pd
= (struct pginfo
**)((char *)pdregion
+
615 cnt
* malloc_pagesize
);
617 memset(pd
, 0, malloc_pagesize
);
618 pi
= (struct pdinfo
*) ((caddr_t
) pd
+ pdi_off
);
621 pi
->next
= spi
->next
;
622 pi
->dirnum
= idx
* (malloc_pagesize
/
623 sizeof(struct pginfo
*));
625 if (spi
->next
!= NULL
)
626 spi
->next
->prev
= pi
;
629 if (idx
> pidx
&& idx
< lidx
) {
630 pi
->dirnum
+= pdi_mod
;
631 } else if (idx
== pidx
) {
633 pi
->dirnum
+= (u_long
)(tail
- result
) >>
636 pi
->dirnum
+= pdi_mod
- PI_OFF(index
);
639 pi
->dirnum
+= PI_OFF(ptr2index(tail
- 1)) + 1;
641 #ifdef MALLOC_EXTRA_SANITY
642 if (PD_OFF(pi
->dirnum
) > pdi_mod
|| PD_IDX(pi
->dirnum
) > idx
) {
643 wrterror("(ES): pages directory overflow");
647 #endif /* MALLOC_EXTRA_SANITY */
648 if (idx
== pidx
&& pi
!= last_dir
) {
655 #ifdef MALLOC_EXTRA_SANITY
657 wrtwarning("(ES): cnt > dirs");
658 #endif /* MALLOC_EXTRA_SANITY */
660 munmap((char *)pdregion
+ cnt
* malloc_pagesize
,
661 (dirs
- cnt
) * malloc_pagesize
);
667 * Initialize the world
673 int i
, j
, save_errno
= errno
;
677 #ifdef MALLOC_EXTRA_SANITY
679 #endif /* MALLOC_EXTRA_SANITY */
681 for (i
= 0; i
< 3; i
++) {
684 j
= (int) readlink("/etc/malloc.conf", b
, sizeof b
- 1);
691 if (issetugid() == 0)
692 p
= getenv("MALLOC_OPTIONS");
703 for (; p
!= NULL
&& *p
!= '\0'; p
++) {
724 #endif /* MALLOC_STATS */
735 malloc_guard
= malloc_pagesize
;
774 #endif /* __FreeBSD__ */
790 wrtwarning("unknown char in MALLOC_OPTIONS");
800 * We want junk in the entire allocation, and zero only in the part
801 * the user asked for.
807 if (malloc_stats
&& (atexit(malloc_exit
) == -1))
808 wrtwarning("atexit(2) failed."
809 " Will not be able to dump malloc stats on exit");
810 #endif /* MALLOC_STATS */
812 if (malloc_pagesize
!= getpagesize()) {
813 wrterror("malloc() replacement compiled with a different "
814 "page size from what we're running with. Failing.");
819 /* Allocate one page for the page directory. */
820 page_dir
= (struct pginfo
**)MMAP(malloc_pagesize
);
822 if (page_dir
== MAP_FAILED
) {
823 wrterror("mmap(2) failed, check limits");
827 pdi_off
= (malloc_pagesize
- sizeof(struct pdinfo
)) & ~(malloc_minsize
- 1);
828 pdi_mod
= pdi_off
/ sizeof(struct pginfo
*);
830 last_dir
= (struct pdinfo
*) ((caddr_t
) page_dir
+ pdi_off
);
831 last_dir
->base
= page_dir
;
832 last_dir
->prev
= last_dir
->next
= NULL
;
833 last_dir
->dirnum
= malloc_pageshift
;
835 /* Been here, done that. */
838 /* Recalculate the cache size in bytes, and make sure it's nonzero. */
841 malloc_cache
<<= malloc_pageshift
;
846 * Allocate a number of complete pages
849 malloc_pages(size_t size
)
851 void *p
, *delay_free
= NULL
, *tp
;
858 size
= pageround(size
) + malloc_guard
;
861 /* Look for free pages before asking for more */
863 for (pf
= free_list
.next
; pf
; pf
= pf
->next
) {
865 #ifdef MALLOC_EXTRA_SANITY
866 if (pf
->size
& malloc_pagemask
) {
867 wrterror("(ES): junk length entry on free_list");
872 wrterror("(ES): zero length entry on free_list");
876 if (pf
->page
> (pf
->page
+ pf
->size
)) {
877 wrterror("(ES): sick entry on free_list");
881 if ((pi
= pf
->pdir
) == NULL
) {
882 wrterror("(ES): invalid page directory on free-list");
886 if ((pidx
= PI_IDX(ptr2index(pf
->page
))) != PD_IDX(pi
->dirnum
)) {
887 wrterror("(ES): directory index mismatch on free-list");
892 if (pd
[PI_OFF(ptr2index(pf
->page
))] != MALLOC_FREE
) {
893 wrterror("(ES): non-free first page on free-list");
897 pidx
= PI_IDX(ptr2index((pf
->page
) + (pf
->size
)) - 1);
898 for (pi
= pf
->pdir
; pi
!= NULL
&& PD_IDX(pi
->dirnum
) < pidx
;
901 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
902 wrterror("(ES): last page not referenced in page directory");
907 if (pd
[PI_OFF(ptr2index((pf
->page
) + (pf
->size
)) - 1)] != MALLOC_FREE
) {
908 wrterror("(ES): non-free last page on free-list");
912 #endif /* MALLOC_EXTRA_SANITY */
917 if (pf
->size
== size
) {
920 if (pf
->next
!= NULL
)
921 pf
->next
->prev
= pf
->prev
;
922 pf
->prev
->next
= pf
->next
;
927 pf
->page
= (char *) pf
->page
+ size
;
929 pidx
= PI_IDX(ptr2index(pf
->page
));
930 for (pi
= pf
->pdir
; pi
!= NULL
&& PD_IDX(pi
->dirnum
) < pidx
;
933 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
934 wrterror("(ES): hole in directories");
944 size
-= malloc_guard
;
946 #ifdef MALLOC_EXTRA_SANITY
947 if (p
!= NULL
&& pi
!= NULL
) {
948 pidx
= PD_IDX(pi
->dirnum
);
951 if (p
!= NULL
&& pd
[PI_OFF(ptr2index(p
))] != MALLOC_FREE
) {
952 wrterror("(ES): allocated non-free page on free-list");
956 #endif /* MALLOC_EXTRA_SANITY */
958 if (p
!= NULL
&& (malloc_guard
|| malloc_freeprot
))
959 mprotect(p
, size
, PROT_READ
| PROT_WRITE
);
961 size
>>= malloc_pageshift
;
968 index
= ptr2index(p
);
969 pidx
= PI_IDX(index
);
970 pdir_lookup(index
, &pi
);
971 #ifdef MALLOC_EXTRA_SANITY
972 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
973 wrterror("(ES): mapped pages not found in directory");
977 #endif /* MALLOC_EXTRA_SANITY */
978 if (pi
!= last_dir
) {
983 pd
[PI_OFF(index
)] = MALLOC_FIRST
;
985 for (i
= 1; i
< size
; i
++) {
986 if (!PI_OFF(index
+ i
)) {
989 #ifdef MALLOC_EXTRA_SANITY
990 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
991 wrterror("(ES): hole in mapped pages directory");
995 #endif /* MALLOC_EXTRA_SANITY */
998 pd
[PI_OFF(index
+ i
)] = MALLOC_FOLLOW
;
1001 if (!PI_OFF(index
+ i
)) {
1004 #ifdef MALLOC_EXTRA_SANITY
1005 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
1006 wrterror("(ES): hole in mapped pages directory");
1010 #endif /* MALLOC_EXTRA_SANITY */
1013 pd
[PI_OFF(index
+ i
)] = MALLOC_FIRST
;
1016 malloc_used
+= size
<< malloc_pageshift
;
1017 malloc_guarded
+= malloc_guard
;
1020 memset(p
, SOME_JUNK
, size
<< malloc_pageshift
);
1032 * Allocate a page of fragments
1035 static __inline__
int
1036 malloc_make_chunks(int bits
)
1038 struct pginfo
*bp
, **pd
;
1040 #ifdef MALLOC_EXTRA_SANITY
1042 #endif /* MALLOC_EXTRA_SANITY */
1047 /* Allocate a new bucket */
1048 pp
= malloc_pages((size_t) malloc_pagesize
);
1052 /* Find length of admin structure */
1053 l
= sizeof *bp
- sizeof(u_long
);
1054 l
+= sizeof(u_long
) *
1055 (((malloc_pagesize
>> bits
) + MALLOC_BITS
- 1) / MALLOC_BITS
);
1057 /* Don't waste more than two chunks on this */
1060 * If we are to allocate a memory protected page for the malloc(0)
1061 * case (when bits=0), it must be from a different page than the
1063 * --> Treat it like the big chunk alloc, get a second data page.
1065 if (bits
!= 0 && (1UL << (bits
)) <= l
+ l
) {
1066 bp
= (struct pginfo
*) pp
;
1068 bp
= (struct pginfo
*) imalloc(l
);
1075 /* memory protect the page allocated in the malloc(0) case */
1079 i
= malloc_minsize
- 1;
1082 bp
->total
= bp
->free
= malloc_pagesize
>> bp
->shift
;
1085 k
= mprotect(pp
, malloc_pagesize
, PROT_NONE
);
1092 bp
->size
= (1UL << bits
);
1094 bp
->total
= bp
->free
= malloc_pagesize
>> bits
;
1098 /* set all valid bits in the bitmap */
1102 /* Do a bunch at a time */
1103 for (; (k
- i
) >= MALLOC_BITS
; i
+= MALLOC_BITS
)
1104 bp
->bits
[i
/ MALLOC_BITS
] = ~0UL;
1107 bp
->bits
[i
/ MALLOC_BITS
] |= 1UL << (i
% MALLOC_BITS
);
1110 if (bp
== bp
->page
) {
1111 /* Mark the ones we stole for ourselves */
1112 for (i
= 0; k
> 0; i
++) {
1113 bp
->bits
[i
/ MALLOC_BITS
] &= ~(1UL << (i
% MALLOC_BITS
));
1121 pdir_lookup(ptr2index(pp
), &pi
);
1122 #ifdef MALLOC_EXTRA_SANITY
1123 pidx
= PI_IDX(ptr2index(pp
));
1124 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
1125 wrterror("(ES): mapped pages not found in directory");
1129 #endif /* MALLOC_EXTRA_SANITY */
1130 if (pi
!= last_dir
) {
1131 prev_dir
= last_dir
;
1135 pd
[PI_OFF(ptr2index(pp
))] = bp
;
1137 bp
->next
= page_dir
[bits
];
1138 page_dir
[bits
] = bp
;
1145 * Allocate a fragment
1148 malloc_bytes(size_t size
)
1155 /* Don't bother with anything less than this */
1156 /* unless we have a malloc(0) requests */
1157 if (size
!= 0 && size
< malloc_minsize
)
1158 size
= malloc_minsize
;
1160 /* Find the right bucket */
1171 /* If it's empty, make a page more of that size chunks */
1172 if (page_dir
[j
] == NULL
&& !malloc_make_chunks(j
))
1177 /* Find first word of bitmap which isn't empty */
1178 for (lp
= bp
->bits
; !*lp
; lp
++);
1180 /* Find that bit, and tweak it */
1183 while (!(*lp
& u
)) {
1189 /* Walk to a random position. */
1190 // i = arc4random() % bp->free;
1191 i
= rand() % bp
->free
;
1195 if (k
>= MALLOC_BITS
) {
1200 #ifdef MALLOC_EXTRA_SANITY
1201 if (lp
- bp
->bits
> (bp
->total
- 1) / MALLOC_BITS
) {
1202 wrterror("chunk overflow");
1206 #endif /* MALLOC_EXTRA_SANITY */
1213 /* If there are no more free, remove from free-list */
1215 page_dir
[j
] = bp
->next
;
1218 /* Adjust to the real offset of that chunk */
1219 k
+= (lp
- bp
->bits
) * MALLOC_BITS
;
1222 if (malloc_junk
&& bp
->size
!= 0)
1223 memset((char *)bp
->page
+ k
, SOME_JUNK
, (size_t)bp
->size
);
1225 return ((u_char
*) bp
->page
+ k
);
1229 * Magic so that malloc(sizeof(ptr)) is near the end of the page.
1231 #define PTR_GAP (malloc_pagesize - sizeof(void *))
1232 #define PTR_SIZE (sizeof(void *))
1233 #define PTR_ALIGNED(p) (((unsigned long)p & malloc_pagemask) == PTR_GAP)
1236 * Allocate a piece of memory
1239 imalloc(size_t size
)
1244 if (!malloc_started
)
1250 /* does not matter if malloc_bytes fails */
1252 px
= malloc_bytes(sizeof *px
);
1254 if (malloc_ptrguard
&& size
== PTR_SIZE
) {
1256 size
= malloc_pagesize
;
1258 if (size
> SIZE_MAX
- malloc_pagesize
) { /* Check for overflow */
1261 } else if (size
<= malloc_maxsize
)
1262 result
= malloc_bytes(size
);
1264 result
= malloc_pages(size
);
1266 if (malloc_abort
== 1 && result
== NULL
)
1267 wrterror("allocation failed");
1269 if (malloc_zero
&& result
!= NULL
)
1270 memset(result
, 0, size
);
1272 if (result
&& ptralloc
)
1273 return ((char *) result
+ PTR_GAP
);
1278 * Change the size of an allocation.
1281 irealloc(void *ptr
, size_t size
)
1289 #ifdef MALLOC_EXTRA_SANITY
1291 #endif /* MALLOC_EXTRA_SANITY */
1296 if (!malloc_started
) {
1297 wrtwarning("malloc() has never been called");
1300 if (malloc_ptrguard
&& PTR_ALIGNED(ptr
)) {
1301 if (size
<= PTR_SIZE
)
1306 memcpy(p
, ptr
, PTR_SIZE
);
1310 index
= ptr2index(ptr
);
1312 if (index
< malloc_pageshift
) {
1313 wrtwarning("junk pointer, too low to make sense");
1316 if (index
> last_index
) {
1317 wrtwarning("junk pointer, too high to make sense");
1320 pdir_lookup(index
, &pi
);
1321 #ifdef MALLOC_EXTRA_SANITY
1322 pidx
= PI_IDX(index
);
1323 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
1324 wrterror("(ES): mapped pages not found in directory");
1328 #endif /* MALLOC_EXTRA_SANITY */
1329 if (pi
!= last_dir
) {
1330 prev_dir
= last_dir
;
1334 mp
= &pd
[PI_OFF(index
)];
1336 if (*mp
== MALLOC_FIRST
) { /* Page allocation */
1338 /* Check the pointer */
1339 if ((u_long
) ptr
& malloc_pagemask
) {
1340 wrtwarning("modified (page-) pointer");
1343 /* Find the size in bytes */
1347 if (pi
!= NULL
&& PD_IDX(pi
->dirnum
) != PI_IDX(i
))
1352 for (osize
= malloc_pagesize
;
1353 pi
!= NULL
&& pd
[PI_OFF(i
)] == MALLOC_FOLLOW
;) {
1354 osize
+= malloc_pagesize
;
1357 if (pi
!= NULL
&& PD_IDX(pi
->dirnum
) != PI_IDX(i
))
1364 if (!malloc_realloc
&& size
<= osize
&&
1365 size
> osize
- malloc_pagesize
) {
1367 memset((char *)ptr
+ size
, SOME_JUNK
, osize
- size
);
1368 return (ptr
); /* ..don't do anything else. */
1370 } else if (*mp
>= MALLOC_MAGIC
) { /* Chunk allocation */
1372 /* Check the pointer for sane values */
1373 if ((u_long
) ptr
& ((1UL << ((*mp
)->shift
)) - 1)) {
1374 wrtwarning("modified (chunk-) pointer");
1377 /* Find the chunk index in the page */
1378 i
= ((u_long
) ptr
& malloc_pagemask
) >> (*mp
)->shift
;
1380 /* Verify that it isn't a free chunk already */
1381 if ((*mp
)->bits
[i
/ MALLOC_BITS
] & (1UL << (i
% MALLOC_BITS
))) {
1382 wrtwarning("chunk is already free");
1385 osize
= (*mp
)->size
;
1387 if (!malloc_realloc
&& size
<= osize
&&
1388 (size
> osize
/ 2 || osize
== malloc_minsize
)) {
1390 memset((char *) ptr
+ size
, SOME_JUNK
, osize
- size
);
1391 return (ptr
); /* ..don't do anything else. */
1394 wrtwarning("irealloc: pointer to wrong page");
1401 /* copy the lesser of the two sizes, and free the old one */
1402 /* Don't move from/to 0 sized region !!! */
1403 if (osize
!= 0 && size
!= 0) {
1405 memcpy(p
, ptr
, osize
);
1407 memcpy(p
, ptr
, size
);
1415 * Free a sequence of pages
1417 static __inline__
void
1418 free_pages(void *ptr
, u_long index
, struct pginfo
* info
)
1420 u_long i
, pidx
, lidx
;
1421 size_t l
, cachesize
= 0;
1423 struct pdinfo
*pi
, *spi
;
1424 struct pgfree
*pf
, *pt
= NULL
;
1427 if (info
== MALLOC_FREE
) {
1428 wrtwarning("page is already free");
1431 if (info
!= MALLOC_FIRST
) {
1432 wrtwarning("free_pages: pointer to wrong page");
1435 if ((u_long
) ptr
& malloc_pagemask
) {
1436 wrtwarning("modified (page-) pointer");
1439 /* Count how many pages and mark them free at the same time */
1440 pidx
= PI_IDX(index
);
1441 pdir_lookup(index
, &pi
);
1442 #ifdef MALLOC_EXTRA_SANITY
1443 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
1444 wrterror("(ES): mapped pages not found in directory");
1448 #endif /* MALLOC_EXTRA_SANITY */
1450 spi
= pi
; /* Save page index for start of region. */
1453 pd
[PI_OFF(index
)] = MALLOC_FREE
;
1455 if (!PI_OFF(index
+ i
)) {
1457 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != PI_IDX(index
+ i
))
1462 while (pi
!= NULL
&& pd
[PI_OFF(index
+ i
)] == MALLOC_FOLLOW
) {
1463 pd
[PI_OFF(index
+ i
)] = MALLOC_FREE
;
1465 if (!PI_OFF(index
+ i
)) {
1466 if ((pi
= pi
->next
) == NULL
||
1467 PD_IDX(pi
->dirnum
) != PI_IDX(index
+ i
))
1474 l
= i
<< malloc_pageshift
;
1477 memset(ptr
, SOME_JUNK
, l
);
1480 malloc_guarded
-= malloc_guard
;
1482 #ifdef MALLOC_EXTRA_SANITY
1483 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != PI_IDX(index
+ i
)) {
1484 wrterror("(ES): hole in mapped pages directory");
1488 #endif /* MALLOC_EXTRA_SANITY */
1489 pd
[PI_OFF(index
+ i
)] = MALLOC_FREE
;
1492 tail
= (caddr_t
)ptr
+ l
;
1495 madvise(ptr
, l
, MADV_FREE
);
1497 if (malloc_freeprot
)
1498 mprotect(ptr
, l
, PROT_NONE
);
1500 /* Add to free-list. */
1501 if (px
== NULL
&& (px
= malloc_bytes(sizeof *px
)) == NULL
)
1507 if (free_list
.next
== NULL
) {
1508 /* Nothing on free list, put this at head. */
1510 px
->prev
= &free_list
;
1511 free_list
.next
= px
;
1516 * Find the right spot, leave pf pointing to the modified
1520 /* Race ahead here, while calculating cache size. */
1521 for (pf
= free_list
.next
;
1522 (caddr_t
)ptr
> ((caddr_t
)pf
->page
+ pf
->size
)
1523 && pf
->next
!= NULL
;
1525 cachesize
+= pf
->size
;
1527 /* Finish cache size calculation. */
1530 cachesize
+= pt
->size
;
1534 if ((caddr_t
)pf
->page
> tail
) {
1535 /* Insert before entry */
1537 px
->prev
= pf
->prev
;
1539 px
->prev
->next
= px
;
1542 } else if (((caddr_t
)pf
->page
+ pf
->size
) == ptr
) {
1543 /* Append to the previous entry. */
1544 cachesize
-= pf
->size
;
1546 if (pf
->next
!= NULL
&&
1547 pf
->next
->page
== ((caddr_t
)pf
->page
+ pf
->size
)) {
1548 /* And collapse the next too. */
1550 pf
->size
+= pt
->size
;
1551 pf
->next
= pt
->next
;
1552 if (pf
->next
!= NULL
)
1553 pf
->next
->prev
= pf
;
1555 } else if (pf
->page
== tail
) {
1556 /* Prepend to entry. */
1557 cachesize
-= pf
->size
;
1561 } else if (pf
->next
== NULL
) {
1562 /* Append at tail of chain. */
1569 wrterror("freelist is destroyed");
1575 if (pf
->pdir
!= last_dir
) {
1576 prev_dir
= last_dir
;
1577 last_dir
= pf
->pdir
;
1580 /* Return something to OS ? */
1581 if (pf
->size
> (malloc_cache
- cachesize
)) {
1584 * Keep the cache intact. Notice that the '>' above guarantees that
1585 * the pf will always have at least one page afterwards.
1587 if (munmap((char *) pf
->page
+ (malloc_cache
- cachesize
),
1588 pf
->size
- (malloc_cache
- cachesize
)) != 0)
1590 tail
= (caddr_t
)pf
->page
+ pf
->size
;
1591 lidx
= ptr2index(tail
) - 1;
1592 pf
->size
= malloc_cache
- cachesize
;
1594 index
= ptr2index((caddr_t
)pf
->page
+ pf
->size
);
1596 pidx
= PI_IDX(index
);
1597 if (prev_dir
!= NULL
&& PD_IDX(prev_dir
->dirnum
) >= pidx
)
1598 prev_dir
= NULL
; /* Will be wiped out below ! */
1600 for (pi
= pf
->pdir
; pi
!= NULL
&& PD_IDX(pi
->dirnum
) < pidx
;
1605 if (pi
!= NULL
&& PD_IDX(pi
->dirnum
) == pidx
) {
1608 for (i
= index
; i
<= lidx
;) {
1609 if (pd
[PI_OFF(i
)] != MALLOC_NOT_MINE
) {
1610 pd
[PI_OFF(i
)] = MALLOC_NOT_MINE
;
1611 #ifdef MALLOC_EXTRA_SANITY
1612 if (!PD_OFF(pi
->dirnum
)) {
1613 wrterror("(ES): pages directory underflow");
1617 #endif /* MALLOC_EXTRA_SANITY */
1620 #ifdef MALLOC_EXTRA_SANITY
1622 wrtwarning("(ES): page already unmapped");
1623 #endif /* MALLOC_EXTRA_SANITY */
1627 * If no page in that dir, free
1630 if (!PD_OFF(pi
->dirnum
)) {
1631 /* Remove from list. */
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
);
1643 PD_IDX(pi
->dirnum
) != PI_IDX(i
))
1648 if (pi
&& !PD_OFF(pi
->dirnum
)) {
1649 /* Resulting page dir is now empty. */
1650 /* Remove from list. */
1651 if (spi
== pi
) /* Update spi only if first. */
1653 if (pi
->prev
!= NULL
)
1654 pi
->prev
->next
= pi
->next
;
1655 if (pi
->next
!= NULL
)
1656 pi
->next
->prev
= pi
->prev
;
1658 munmap(pd
, malloc_pagesize
);
1661 if (pi
== NULL
&& malloc_brk
== tail
) {
1662 /* Resize down the malloc upper boundary. */
1663 last_index
= index
- 1;
1664 malloc_brk
= index2ptr(index
);
1667 /* XXX: We could realloc/shrink the pagedir here I guess. */
1668 if (pf
->size
== 0) { /* Remove from free-list as well. */
1671 if ((px
= pf
->prev
) != &free_list
) {
1672 if (pi
== NULL
&& last_index
== (index
- 1)) {
1678 if (PD_IDX(spi
->dirnum
) < pidx
)
1680 ((PD_IDX(spi
->dirnum
) + 1) *
1682 for (pi
= spi
, i
= index
;
1683 pd
[PI_OFF(i
)] == MALLOC_NOT_MINE
;
1685 #ifdef MALLOC_EXTRA_SANITY
1688 if (pi
== NULL
|| i
== 0)
1691 i
= (PD_IDX(pi
->dirnum
) + 1) * pdi_mod
;
1693 #else /* !MALLOC_EXTRA_SANITY */
1696 #endif /* MALLOC_EXTRA_SANITY */
1697 malloc_brk
= index2ptr(i
+ 1);
1701 if ((px
->next
= pf
->next
) != NULL
)
1702 px
->next
->prev
= px
;
1704 if ((free_list
.next
= pf
->next
) != NULL
)
1705 free_list
.next
->prev
= &free_list
;
1708 last_dir
= prev_dir
;
1718 * Free a chunk, and possibly the page it's on, if the page becomes empty.
1722 static __inline__
void
1723 free_bytes(void *ptr
, u_long index
, struct pginfo
* info
)
1725 struct pginfo
**mp
, **pd
;
1727 #ifdef MALLOC_EXTRA_SANITY
1729 #endif /* MALLOC_EXTRA_SANITY */
1734 /* Find the chunk number on the page */
1735 i
= ((u_long
) ptr
& malloc_pagemask
) >> info
->shift
;
1737 if ((u_long
) ptr
& ((1UL << (info
->shift
)) - 1)) {
1738 wrtwarning("modified (chunk-) pointer");
1741 if (info
->bits
[i
/ MALLOC_BITS
] & (1UL << (i
% MALLOC_BITS
))) {
1742 wrtwarning("chunk is already free");
1745 if (malloc_junk
&& info
->size
!= 0)
1746 memset(ptr
, SOME_JUNK
, (size_t)info
->size
);
1748 info
->bits
[i
/ MALLOC_BITS
] |= 1UL << (i
% MALLOC_BITS
);
1751 if (info
->size
!= 0)
1752 mp
= page_dir
+ info
->shift
;
1756 if (info
->free
== 1) {
1757 /* Page became non-full */
1759 /* Insert in address order */
1760 while (*mp
!= NULL
&& (*mp
)->next
!= NULL
&&
1761 (*mp
)->next
->page
< info
->page
)
1767 if (info
->free
!= info
->total
)
1770 /* Find & remove this page in the queue */
1771 while (*mp
!= info
) {
1772 mp
= &((*mp
)->next
);
1773 #ifdef MALLOC_EXTRA_SANITY
1775 wrterror("(ES): Not on queue");
1779 #endif /* MALLOC_EXTRA_SANITY */
1783 /* Free the page & the info structure if need be */
1784 pdir_lookup(ptr2index(info
->page
), &pi
);
1785 #ifdef MALLOC_EXTRA_SANITY
1786 pidx
= PI_IDX(ptr2index(info
->page
));
1787 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
1788 wrterror("(ES): mapped pages not found in directory");
1792 #endif /* MALLOC_EXTRA_SANITY */
1793 if (pi
!= last_dir
) {
1794 prev_dir
= last_dir
;
1798 pd
[PI_OFF(ptr2index(info
->page
))] = MALLOC_FIRST
;
1800 /* If the page was mprotected, unprotect it before releasing it */
1801 if (info
->size
== 0)
1802 mprotect(info
->page
, malloc_pagesize
, PROT_READ
| PROT_WRITE
);
1804 vp
= info
->page
; /* Order is important ! */
1805 if (vp
!= (void *) info
)
1813 struct pginfo
*info
, **pd
;
1815 #ifdef MALLOC_EXTRA_SANITY
1817 #endif /* MALLOC_EXTRA_SANITY */
1820 if (!malloc_started
) {
1821 wrtwarning("malloc() has never been called");
1824 /* If we're already sinking, don't make matters any worse. */
1828 if (malloc_ptrguard
&& PTR_ALIGNED(ptr
))
1829 ptr
= (char *) ptr
- PTR_GAP
;
1831 index
= ptr2index(ptr
);
1833 if (index
< malloc_pageshift
) {
1835 wrtwarning("ifree: junk pointer, too low to make sense");
1838 if (index
> last_index
) {
1840 wrtwarning("ifree: junk pointer, too high to make sense");
1843 pdir_lookup(index
, &pi
);
1844 #ifdef MALLOC_EXTRA_SANITY
1845 pidx
= PI_IDX(index
);
1846 if (pi
== NULL
|| PD_IDX(pi
->dirnum
) != pidx
) {
1847 wrterror("(ES): mapped pages not found in directory");
1851 #endif /* MALLOC_EXTRA_SANITY */
1852 if (pi
!= last_dir
) {
1853 prev_dir
= last_dir
;
1857 info
= pd
[PI_OFF(index
)];
1859 if (info
< MALLOC_MAGIC
)
1860 free_pages(ptr
, index
, info
);
1862 free_bytes(ptr
, index
, info
);
1864 /* does not matter if malloc_bytes fails */
1866 px
= malloc_bytes(sizeof *px
);
1872 * Common function for handling recursion. Only
1873 * print the error message once, to avoid making the problem
1874 * potentially worse.
1877 malloc_recurse(void)
1883 wrtwarning("recursive call");
1891 * These are the public exported interface routines.
1900 malloc_func
= " in malloc():";
1901 if (malloc_active
++) {
1910 if (malloc_xmalloc
&& r
== NULL
) {
1911 wrterror("out of memory");
1920 /* This is legal. XXX quick path */
1925 malloc_func
= " in free():";
1926 if (malloc_active
++) {
1938 realloc(void *ptr
, size_t size
)
1943 malloc_func
= " in realloc():";
1944 if (malloc_active
++) {
1952 r
= irealloc(ptr
, size
);
1954 UTRACE(ptr
, size
, r
);
1957 if (malloc_xmalloc
&& r
== NULL
) {
1958 wrterror("out of memory");
1965 calloc(size_t num
, size_t size
)
1969 if (num
&& SIZE_MAX
/ num
< size
) {
1970 fprintf(stderr
,"OOOOPS");
1981 #ifndef BUILDING_FOR_TOR
1982 static int ispowerof2 (size_t a
) {
1984 for (b
= 1ULL << (sizeof(size_t)*NBBY
- 1); b
> 1; b
>>= 1)
1991 #ifndef BUILDING_FOR_TOR
1992 int posix_memalign(void **memptr
, size_t alignment
, size_t size
)
1996 if ((alignment
< PTR_SIZE
) || (alignment
%PTR_SIZE
!= 0)) return EINVAL
;
1997 if (!ispowerof2(alignment
)) return EINVAL
;
1998 if (alignment
< malloc_minsize
) alignment
= malloc_minsize
;
1999 max
= alignment
> size
? alignment
: size
;
2000 if (alignment
<= malloc_pagesize
)
2005 g_alignment
= alignment
;
2011 if (!r
) return ENOMEM
;
2015 void *memalign(size_t boundary
, size_t size
)
2018 posix_memalign(&r
, boundary
, size
);
2022 void *valloc(size_t size
)
2025 posix_memalign(&r
, malloc_pagesize
, size
);
2030 size_t malloc_good_size(size_t size
)
2034 } else if (size
<= malloc_maxsize
) {
2037 /* round up to the nearest power of 2, with same approach
2038 * as malloc_bytes() uses. */
2043 return ((size_t)1) << j
;
2045 return pageround(size
);