ACK: [PATCH] lib: fwts_alloc: fix low 32 bit memory allocator (LP: #1295849)

Alex Hung alex.hung at canonical.com
Tue Mar 25 03:18:25 UTC 2014


On 03/22/2014 05:53 AM, Colin King wrote:
> From: Colin Ian King <colin.king at canonical.com>
> 
> The original mmap allocator made x86 specific assumptions about
> memory mappings.  Re-work the low memory allocator to try to find
> a free mapping under the 2GB 32 bit threshold by always examining
> the first mapping for the procss and either using this if it is below
> 2GB or chosing 2GB less the mapping size.  This is also more efficient
> too.
> 
> Signed-off-by: Colin Ian King <colin.king at canonical.com>
> ---
>  src/lib/src/fwts_alloc.c | 40 +++++++++++++++++++++++++++++++++++++---
>  1 file changed, 37 insertions(+), 3 deletions(-)
> 
> diff --git a/src/lib/src/fwts_alloc.c b/src/lib/src/fwts_alloc.c
> index 57ece72..9610159 100644
> --- a/src/lib/src/fwts_alloc.c
> +++ b/src/lib/src/fwts_alloc.c
> @@ -46,7 +46,9 @@ typedef struct {
>  	unsigned int magic;
>  } fwts_mmap_header;
>  
> -#define LIMIT_2GB	0x80000000ULL
> +#define CHUNK_SIZE	(8192)		/* page plus loads of slack */
> +#define LIMIT_2GB	(0x80000000ULL)
> +#define LIMIT_START	(0x00010000ULL)
>  
>  #ifndef MAP_32BIT
>  /*
> @@ -62,6 +64,7 @@ static void *fwts_low_mmap(const size_t requested_size)
>  	void *addr_start;
>  	void *addr_end;
>  	void *last_addr_end = NULL;
> +	void *first_addr_start = NULL;
>  	void *ret = MAP_FAILED;
>  
>  	if (requested_size == 0)	/* Illegal */
> @@ -74,6 +77,35 @@ static void *fwts_low_mmap(const size_t requested_size)
>  		sscanf(buffer, "%p-%p %*s %*x %*s %*u %s",
>  			&addr_start, &addr_end, pathname);
>  
> +		/*
> +		 *  Try and allocate under first mmap'd address space
> +		 */
> +		if ((first_addr_start == NULL) &&
> +		    (addr_start > (void*)LIMIT_START)) {
> +			size_t sz = (requested_size + CHUNK_SIZE) & ~(CHUNK_SIZE - 1);
> +			void *addr = addr_start - sz;
> +
> +			/*
> +			 * If addr is over the 2GB limit and we know
> +			 * that this is the first mapping then we should
> +			 * be able to map a region below the 2GB limit as
> +			 * nothing is already mapped there
> +			 */
> +			if (addr > (void*)LIMIT_2GB)
> +				addr = (void*)LIMIT_2GB - sz;
> +
> +			ret = mmap(addr, requested_size, PROT_READ | PROT_WRITE,
> +				MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
> +			if (ret != MAP_FAILED)
> +				break;	/* Success! */
> +
> +			first_addr_start = addr_start;
> +		}
> +
> +		/*
> +		 *  No allocation yet, so try now to squeeze one
> +		 *  in between already mapped regions
> +		 */
>  		if ((last_addr_end != NULL) &&
>  		    (last_addr_end < (void*)LIMIT_2GB)) {
>  			if ((addr_start - last_addr_end) > (ptrdiff_t)requested_size) {
> @@ -85,9 +117,11 @@ static void *fwts_low_mmap(const size_t requested_size)
>  			}
>  		}
>  
> -		/* We really don't want to mmap at the end of the heap
> +		/*
> +		 * We really don't want to mmap at the end of the heap
>  		 * and if we've reached the stack we've gone too far so
> -		 * abort */
> +		 * abort
> +		 */
>  		if ((strncmp("[heap]", pathname, 6) == 0) ||
>  		    (strncmp("[stack]", pathname, 7) == 0)) {
>  			ret = MAP_FAILED;
> 

Acked-by: Alex Hung <alex.hung at canonical.com>



More information about the fwts-devel mailing list