|  | @@ -275,7 +275,7 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
 | 
		
	
		
			
			| 275 | 275 |  	size_t align_mask;
 | 
		
	
		
			
			| 276 | 276 |  	size_t actual_size;
 | 
		
	
		
			
			| 277 | 277 |  	size_t pre_size;
 | 
		
	
		
			
			| 278 |  | -	ssize_t post_size;
 | 
		
	
		
			
			|  | 278 | +	size_t post_size;
 | 
		
	
		
			
			| 279 | 279 |  	struct memory_block *pre;
 | 
		
	
		
			
			| 280 | 280 |  	struct memory_block *post;
 | 
		
	
		
			
			| 281 | 281 |  	void *ptr;
 | 
		
	
	
		
			
			|  | @@ -291,7 +291,9 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
 | 
		
	
		
			
			| 291 | 291 |  	 */
 | 
		
	
		
			
			| 292 | 292 |  	actual_size = ( ( size + MIN_MEMBLOCK_SIZE - 1 ) &
 | 
		
	
		
			
			| 293 | 293 |  			~( MIN_MEMBLOCK_SIZE - 1 ) );
 | 
		
	
		
			
			|  | 294 | +	assert ( actual_size >= size );
 | 
		
	
		
			
			| 294 | 295 |  	align_mask = ( ( align - 1 ) | ( MIN_MEMBLOCK_SIZE - 1 ) );
 | 
		
	
		
			
			|  | 296 | +	assert ( ( actual_size + align_mask ) > actual_size );
 | 
		
	
		
			
			| 295 | 297 |  
 | 
		
	
		
			
			| 296 | 298 |  	DBGC2 ( &heap, "Allocating %#zx (aligned %#zx+%zx)\n",
 | 
		
	
		
			
			| 297 | 299 |  		size, align, offset );
 | 
		
	
	
		
			
			|  | @@ -300,55 +302,54 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
 | 
		
	
		
			
			| 300 | 302 |  		list_for_each_entry ( block, &free_blocks, list ) {
 | 
		
	
		
			
			| 301 | 303 |  			pre_size = ( ( offset - virt_to_phys ( block ) )
 | 
		
	
		
			
			| 302 | 304 |  				     & align_mask );
 | 
		
	
		
			
			|  | 305 | +			if ( block->size < ( pre_size + actual_size ) )
 | 
		
	
		
			
			|  | 306 | +				continue;
 | 
		
	
		
			
			| 303 | 307 |  			post_size = ( block->size - pre_size - actual_size );
 | 
		
	
		
			
			| 304 |  | -			if ( post_size >= 0 ) {
 | 
		
	
		
			
			| 305 |  | -				/* Split block into pre-block, block, and
 | 
		
	
		
			
			| 306 |  | -				 * post-block.  After this split, the "pre"
 | 
		
	
		
			
			| 307 |  | -				 * block is the one currently linked into the
 | 
		
	
		
			
			| 308 |  | -				 * free list.
 | 
		
	
		
			
			| 309 |  | -				 */
 | 
		
	
		
			
			| 310 |  | -				pre   = block;
 | 
		
	
		
			
			| 311 |  | -				block = ( ( ( void * ) pre   ) + pre_size );
 | 
		
	
		
			
			| 312 |  | -				post  = ( ( ( void * ) block ) + actual_size );
 | 
		
	
		
			
			| 313 |  | -				DBGC2 ( &heap, "[%p,%p) -> [%p,%p) + [%p,%p)\n",
 | 
		
	
		
			
			| 314 |  | -					pre, ( ( ( void * ) pre ) + pre->size ),
 | 
		
	
		
			
			| 315 |  | -					pre, block, post,
 | 
		
	
		
			
			| 316 |  | -					( ( ( void * ) pre ) + pre->size ) );
 | 
		
	
		
			
			| 317 |  | -				/* If there is a "post" block, add it in to
 | 
		
	
		
			
			| 318 |  | -				 * the free list.  Leak it if it is too small
 | 
		
	
		
			
			| 319 |  | -				 * (which can happen only at the very end of
 | 
		
	
		
			
			| 320 |  | -				 * the heap).
 | 
		
	
		
			
			| 321 |  | -				 */
 | 
		
	
		
			
			| 322 |  | -				if ( (size_t) post_size >= MIN_MEMBLOCK_SIZE ) {
 | 
		
	
		
			
			| 323 |  | -					VALGRIND_MAKE_MEM_UNDEFINED
 | 
		
	
		
			
			| 324 |  | -						( post, sizeof ( *post ) );
 | 
		
	
		
			
			| 325 |  | -					post->size = post_size;
 | 
		
	
		
			
			| 326 |  | -					list_add ( &post->list, &pre->list );
 | 
		
	
		
			
			| 327 |  | -				}
 | 
		
	
		
			
			| 328 |  | -				/* Shrink "pre" block, leaving the main block
 | 
		
	
		
			
			| 329 |  | -				 * isolated and no longer part of the free
 | 
		
	
		
			
			| 330 |  | -				 * list.
 | 
		
	
		
			
			| 331 |  | -				 */
 | 
		
	
		
			
			| 332 |  | -				pre->size = pre_size;
 | 
		
	
		
			
			| 333 |  | -				/* If there is no "pre" block, remove it from
 | 
		
	
		
			
			| 334 |  | -				 * the list.  Also remove it (i.e. leak it) if
 | 
		
	
		
			
			| 335 |  | -				 * it is too small, which can happen only at
 | 
		
	
		
			
			| 336 |  | -				 * the very start of the heap.
 | 
		
	
		
			
			| 337 |  | -				 */
 | 
		
	
		
			
			| 338 |  | -				if ( pre_size < MIN_MEMBLOCK_SIZE ) {
 | 
		
	
		
			
			| 339 |  | -					list_del ( &pre->list );
 | 
		
	
		
			
			| 340 |  | -					VALGRIND_MAKE_MEM_NOACCESS
 | 
		
	
		
			
			| 341 |  | -						( pre, sizeof ( *pre ) );
 | 
		
	
		
			
			| 342 |  | -				}
 | 
		
	
		
			
			| 343 |  | -				/* Update total free memory */
 | 
		
	
		
			
			| 344 |  | -				freemem -= actual_size;
 | 
		
	
		
			
			| 345 |  | -				/* Return allocated block */
 | 
		
	
		
			
			| 346 |  | -				DBGC2 ( &heap, "Allocated [%p,%p)\n", block,
 | 
		
	
		
			
			| 347 |  | -					( ( ( void * ) block ) + size ) );
 | 
		
	
		
			
			| 348 |  | -				ptr = block;
 | 
		
	
		
			
			| 349 |  | -				VALGRIND_MAKE_MEM_UNDEFINED ( ptr, size );
 | 
		
	
		
			
			| 350 |  | -				goto done;
 | 
		
	
		
			
			|  | 308 | +			/* Split block into pre-block, block, and
 | 
		
	
		
			
			|  | 309 | +			 * post-block.  After this split, the "pre"
 | 
		
	
		
			
			|  | 310 | +			 * block is the one currently linked into the
 | 
		
	
		
			
			|  | 311 | +			 * free list.
 | 
		
	
		
			
			|  | 312 | +			 */
 | 
		
	
		
			
			|  | 313 | +			pre   = block;
 | 
		
	
		
			
			|  | 314 | +			block = ( ( ( void * ) pre   ) + pre_size );
 | 
		
	
		
			
			|  | 315 | +			post  = ( ( ( void * ) block ) + actual_size );
 | 
		
	
		
			
			|  | 316 | +			DBGC2 ( &heap, "[%p,%p) -> [%p,%p) + [%p,%p)\n", pre,
 | 
		
	
		
			
			|  | 317 | +				( ( ( void * ) pre ) + pre->size ), pre, block,
 | 
		
	
		
			
			|  | 318 | +				post, ( ( ( void * ) pre ) + pre->size ) );
 | 
		
	
		
			
			|  | 319 | +			/* If there is a "post" block, add it in to
 | 
		
	
		
			
			|  | 320 | +			 * the free list.  Leak it if it is too small
 | 
		
	
		
			
			|  | 321 | +			 * (which can happen only at the very end of
 | 
		
	
		
			
			|  | 322 | +			 * the heap).
 | 
		
	
		
			
			|  | 323 | +			 */
 | 
		
	
		
			
			|  | 324 | +			if ( post_size >= MIN_MEMBLOCK_SIZE ) {
 | 
		
	
		
			
			|  | 325 | +				VALGRIND_MAKE_MEM_UNDEFINED ( post,
 | 
		
	
		
			
			|  | 326 | +							      sizeof ( *post ));
 | 
		
	
		
			
			|  | 327 | +				post->size = post_size;
 | 
		
	
		
			
			|  | 328 | +				list_add ( &post->list, &pre->list );
 | 
		
	
		
			
			| 351 | 329 |  			}
 | 
		
	
		
			
			|  | 330 | +			/* Shrink "pre" block, leaving the main block
 | 
		
	
		
			
			|  | 331 | +			 * isolated and no longer part of the free
 | 
		
	
		
			
			|  | 332 | +			 * list.
 | 
		
	
		
			
			|  | 333 | +			 */
 | 
		
	
		
			
			|  | 334 | +			pre->size = pre_size;
 | 
		
	
		
			
			|  | 335 | +			/* If there is no "pre" block, remove it from
 | 
		
	
		
			
			|  | 336 | +			 * the list.  Also remove it (i.e. leak it) if
 | 
		
	
		
			
			|  | 337 | +			 * it is too small, which can happen only at
 | 
		
	
		
			
			|  | 338 | +			 * the very start of the heap.
 | 
		
	
		
			
			|  | 339 | +			 */
 | 
		
	
		
			
			|  | 340 | +			if ( pre_size < MIN_MEMBLOCK_SIZE ) {
 | 
		
	
		
			
			|  | 341 | +				list_del ( &pre->list );
 | 
		
	
		
			
			|  | 342 | +				VALGRIND_MAKE_MEM_NOACCESS ( pre,
 | 
		
	
		
			
			|  | 343 | +							     sizeof ( *pre ) );
 | 
		
	
		
			
			|  | 344 | +			}
 | 
		
	
		
			
			|  | 345 | +			/* Update total free memory */
 | 
		
	
		
			
			|  | 346 | +			freemem -= actual_size;
 | 
		
	
		
			
			|  | 347 | +			/* Return allocated block */
 | 
		
	
		
			
			|  | 348 | +			DBGC2 ( &heap, "Allocated [%p,%p)\n", block,
 | 
		
	
		
			
			|  | 349 | +				( ( ( void * ) block ) + size ) );
 | 
		
	
		
			
			|  | 350 | +			ptr = block;
 | 
		
	
		
			
			|  | 351 | +			VALGRIND_MAKE_MEM_UNDEFINED ( ptr, size );
 | 
		
	
		
			
			|  | 352 | +			goto done;
 | 
		
	
		
			
			| 352 | 353 |  		}
 | 
		
	
		
			
			| 353 | 354 |  
 | 
		
	
		
			
			| 354 | 355 |  		/* Try discarding some cached data to free up memory */
 |