diff options
Diffstat (limited to 'libc/stdlib')
| -rw-r--r-- | libc/stdlib/malloc-simple/alloc.c | 40 | 
1 files changed, 31 insertions, 9 deletions
| diff --git a/libc/stdlib/malloc-simple/alloc.c b/libc/stdlib/malloc-simple/alloc.c index 79ea17794..b6a3cfcb6 100644 --- a/libc/stdlib/malloc-simple/alloc.c +++ b/libc/stdlib/malloc-simple/alloc.c @@ -1,3 +1,9 @@ + +/* + *	For MMU hosts we need to track the size of the allocations otherwise + *	munmap will fail to free the memory (EINVAL). + */ +  #include <features.h>  #include <unistd.h>  #include <stdio.h> @@ -68,23 +74,28 @@ void *calloc(size_t num, size_t size)  void *malloc(size_t size)  {  	void *result; -#if 1 +      /* Some programs will call malloc (0).  Lets be strict and return NULL */      if (size == 0) -	return NULL; -#endif -	result = mmap((void *) 0, size, PROT_READ | PROT_WRITE, +		return NULL; +  #ifdef __UCLIBC_HAS_MMU__ -						MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 +	result = mmap((void *) 0, size + sizeof(size_t), PROT_READ | PROT_WRITE, +						MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);  #else -						MAP_SHARED | MAP_ANONYMOUS, 0, 0 +	result = mmap((void *) 0, size, PROT_READ | PROT_WRITE, +						MAP_SHARED | MAP_ANONYMOUS, 0, 0);  #endif -						    );  	if (result == MAP_FAILED)  		return 0; - -	return result; +	 +#ifdef __UCLIBC_HAS_MMU__ +	* (size_t *) result = size; +	return(result + sizeof(size_t)); +#else +	return(result); +#endif  }  #endif @@ -93,7 +104,14 @@ void *malloc(size_t size)  void free(void *ptr)  { +#ifdef __UCLIBC_HAS_MMU__ +	if (ptr) { +		ptr -= sizeof(size_t); +		munmap(ptr, * (size_t *) ptr); +	} +#else  	munmap(ptr, 0); +#endif  }  #endif @@ -107,7 +125,11 @@ void *realloc(void *ptr, size_t size)  	if (size > 0) {  		newptr = malloc(size);  		if (newptr && ptr) { +#ifdef __UCLIBC_HAS_MMU__ +			memcpy(newptr, ptr, * ((size_t *) (ptr - sizeof(size_t)))); +#else  			memcpy(newptr, ptr, size); +#endif  			free(ptr);  		}  	} | 
