github.com/afumu/libc@v0.0.6/musl/src/malloc/lite_malloc.c (about)

     1  #include <stdlib.h>
     2  #include <stdint.h>
     3  #include <limits.h>
     4  #include <errno.h>
     5  #include <sys/mman.h>
     6  #include "libc.h"
     7  #include "lock.h"
     8  #include "syscall.h"
     9  
    10  #define ALIGN 16
    11  
    12  /* This function returns true if the interval [old,new]
    13   * intersects the 'len'-sized interval below &libc.auxv
    14   * (interpreted as the main-thread stack) or below &b
    15   * (the current stack). It is used to defend against
    16   * buggy brk implementations that can cross the stack. */
    17  
    18  static int traverses_stack_p(uintptr_t old, uintptr_t new)
    19  {
    20  	const uintptr_t len = 8<<20;
    21  	uintptr_t a, b;
    22  
    23  	b = (uintptr_t)libc.auxv;
    24  	a = b > len ? b-len : 0;
    25  	if (new>a && old<b) return 1;
    26  
    27  	b = (uintptr_t)&b;
    28  	a = b > len ? b-len : 0;
    29  	if (new>a && old<b) return 1;
    30  
    31  	return 0;
    32  }
    33  
    34  static void *__simple_malloc(size_t n)
    35  {
    36  	static uintptr_t brk, cur, end;
    37  	static volatile int lock[1];
    38  	static unsigned mmap_step;
    39  	size_t align=1;
    40  	void *p;
    41  
    42  	if (n > SIZE_MAX/2) {
    43  		errno = ENOMEM;
    44  		return 0;
    45  	}
    46  
    47  	if (!n) n++;
    48  	while (align<n && align<ALIGN)
    49  		align += align;
    50  
    51  	LOCK(lock);
    52  
    53  	cur += -cur & align-1;
    54  
    55  	if (n > end-cur) {
    56  		size_t req = n - (end-cur) + PAGE_SIZE-1 & -PAGE_SIZE;
    57  
    58  		if (!cur) {
    59  			brk = __syscall(SYS_brk, 0);
    60  			brk += -brk & PAGE_SIZE-1;
    61  			cur = end = brk;
    62  		}
    63  
    64  		if (brk == end && req < SIZE_MAX-brk
    65  		    && !traverses_stack_p(brk, brk+req)
    66  		    && __syscall(SYS_brk, brk+req)==brk+req) {
    67  			brk = end += req;
    68  		} else {
    69  			int new_area = 0;
    70  			req = n + PAGE_SIZE-1 & -PAGE_SIZE;
    71  			/* Only make a new area rather than individual mmap
    72  			 * if wasted space would be over 1/8 of the map. */
    73  			if (req-n > req/8) {
    74  				/* Geometric area size growth up to 64 pages,
    75  				 * bounding waste by 1/8 of the area. */
    76  				size_t min = PAGE_SIZE<<(mmap_step/2);
    77  				if (min-n > end-cur) {
    78  					if (req < min) {
    79  						req = min;
    80  						if (mmap_step < 12)
    81  							mmap_step++;
    82  					}
    83  					new_area = 1;
    84  				}
    85  			}
    86  			void *mem = __mmap(0, req, PROT_READ|PROT_WRITE,
    87  				MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    88  			if (mem == MAP_FAILED || !new_area) {
    89  				UNLOCK(lock);
    90  				return mem==MAP_FAILED ? 0 : mem;
    91  			}
    92  			cur = (uintptr_t)mem;
    93  			end = cur + req;
    94  		}
    95  	}
    96  
    97  	p = (void *)cur;
    98  	cur += n;
    99  	UNLOCK(lock);
   100  	return p;
   101  }
   102  
   103  weak_alias(__simple_malloc, malloc);