|  | @@ -52,6 +52,9 @@ static userptr_t top = UNULL;
 | 
		
	
		
			
			| 52 | 52 |  /** Bottom of heap (current lowest allocated block) */
 | 
		
	
		
			
			| 53 | 53 |  static userptr_t bottom = UNULL;
 | 
		
	
		
			
			| 54 | 54 |  
 | 
		
	
		
			
			|  | 55 | +/** Remaining space on heap */
 | 
		
	
		
			
			|  | 56 | +static size_t heap_size;
 | 
		
	
		
			
			|  | 57 | +
 | 
		
	
		
			
			| 55 | 58 |  /**
 | 
		
	
		
			
			| 56 | 59 |   * Initialise external heap
 | 
		
	
		
			
			| 57 | 60 |   *
 | 
		
	
	
		
			
			|  | @@ -59,12 +62,12 @@ static userptr_t bottom = UNULL;
 | 
		
	
		
			
			| 59 | 62 |   */
 | 
		
	
		
			
			| 60 | 63 |  static int init_eheap ( void ) {
 | 
		
	
		
			
			| 61 | 64 |  	struct memory_map memmap;
 | 
		
	
		
			
			| 62 |  | -	unsigned long heap_size = 0;
 | 
		
	
		
			
			| 63 | 65 |  	unsigned int i;
 | 
		
	
		
			
			| 64 | 66 |  
 | 
		
	
		
			
			| 65 | 67 |  	DBG ( "Allocating external heap\n" );
 | 
		
	
		
			
			| 66 | 68 |  
 | 
		
	
		
			
			| 67 | 69 |  	get_memmap ( &memmap );
 | 
		
	
		
			
			|  | 70 | +	heap_size = 0;
 | 
		
	
		
			
			| 68 | 71 |  	for ( i = 0 ; i < memmap.count ; i++ ) {
 | 
		
	
		
			
			| 69 | 72 |  		struct memory_region *region = &memmap.regions[i];
 | 
		
	
		
			
			| 70 | 73 |  		unsigned long r_start, r_end;
 | 
		
	
	
		
			
			|  | @@ -99,8 +102,8 @@ static int init_eheap ( void ) {
 | 
		
	
		
			
			| 99 | 102 |  		return -ENOMEM;
 | 
		
	
		
			
			| 100 | 103 |  	}
 | 
		
	
		
			
			| 101 | 104 |  
 | 
		
	
		
			
			| 102 |  | -	DBG ( "External heap grows downwards from %lx\n",
 | 
		
	
		
			
			| 103 |  | -	      user_to_phys ( top, 0 ) );
 | 
		
	
		
			
			|  | 105 | +	DBG ( "External heap grows downwards from %lx (size %zx)\n",
 | 
		
	
		
			
			|  | 106 | +	      user_to_phys ( top, 0 ), heap_size );
 | 
		
	
		
			
			| 104 | 107 |  	return 0;
 | 
		
	
		
			
			| 105 | 108 |  }
 | 
		
	
		
			
			| 106 | 109 |  
 | 
		
	
	
		
			
			|  | @@ -110,6 +113,7 @@ static int init_eheap ( void ) {
 | 
		
	
		
			
			| 110 | 113 |   */
 | 
		
	
		
			
			| 111 | 114 |  static void ecollect_free ( void ) {
 | 
		
	
		
			
			| 112 | 115 |  	struct external_memory extmem;
 | 
		
	
		
			
			|  | 116 | +	size_t len;
 | 
		
	
		
			
			| 113 | 117 |  
 | 
		
	
		
			
			| 114 | 118 |  	/* Walk the free list and collect empty blocks */
 | 
		
	
		
			
			| 115 | 119 |  	while ( bottom != top ) {
 | 
		
	
	
		
			
			|  | @@ -119,8 +123,9 @@ static void ecollect_free ( void ) {
 | 
		
	
		
			
			| 119 | 123 |  			break;
 | 
		
	
		
			
			| 120 | 124 |  		DBG ( "EXTMEM freeing [%lx,%lx)\n", user_to_phys ( bottom, 0 ),
 | 
		
	
		
			
			| 121 | 125 |  		      user_to_phys ( bottom, extmem.size ) );
 | 
		
	
		
			
			| 122 |  | -		bottom = userptr_add ( bottom,
 | 
		
	
		
			
			| 123 |  | -				       ( extmem.size + sizeof ( extmem ) ) );
 | 
		
	
		
			
			|  | 126 | +		len = ( extmem.size + sizeof ( extmem ) );
 | 
		
	
		
			
			|  | 127 | +		bottom = userptr_add ( bottom, len );
 | 
		
	
		
			
			|  | 128 | +		heap_size += len;
 | 
		
	
		
			
			| 124 | 129 |  	}
 | 
		
	
		
			
			| 125 | 130 |  }
 | 
		
	
		
			
			| 126 | 131 |  
 | 
		
	
	
		
			
			|  | @@ -153,7 +158,12 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
 | 
		
	
		
			
			| 153 | 158 |  				 sizeof ( extmem ) );
 | 
		
	
		
			
			| 154 | 159 |  	} else {
 | 
		
	
		
			
			| 155 | 160 |  		/* Create a zero-length block */
 | 
		
	
		
			
			|  | 161 | +		if ( heap_size < sizeof ( extmem ) ) {
 | 
		
	
		
			
			|  | 162 | +			DBG ( "EXTMEM out of space\n" );
 | 
		
	
		
			
			|  | 163 | +			return UNULL;
 | 
		
	
		
			
			|  | 164 | +		}
 | 
		
	
		
			
			| 156 | 165 |  		ptr = bottom = userptr_add ( bottom, -sizeof ( extmem ) );
 | 
		
	
		
			
			|  | 166 | +		heap_size -= sizeof ( extmem );
 | 
		
	
		
			
			| 157 | 167 |  		DBG ( "EXTMEM allocating [%lx,%lx)\n",
 | 
		
	
		
			
			| 158 | 168 |  		      user_to_phys ( ptr, 0 ), user_to_phys ( ptr, 0 ) );
 | 
		
	
		
			
			| 159 | 169 |  		extmem.size = 0;
 | 
		
	
	
		
			
			|  | @@ -163,6 +173,10 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
 | 
		
	
		
			
			| 163 | 173 |  	/* Expand/shrink block if possible */
 | 
		
	
		
			
			| 164 | 174 |  	if ( ptr == bottom ) {
 | 
		
	
		
			
			| 165 | 175 |  		/* Update block */
 | 
		
	
		
			
			|  | 176 | +		if ( new_size > ( heap_size - extmem.size ) ) {
 | 
		
	
		
			
			|  | 177 | +			DBG ( "EXTMEM out of space\n" );
 | 
		
	
		
			
			|  | 178 | +			return UNULL;
 | 
		
	
		
			
			|  | 179 | +		}
 | 
		
	
		
			
			| 166 | 180 |  		new = userptr_add ( ptr, - ( new_size - extmem.size ) );
 | 
		
	
		
			
			| 167 | 181 |  		align = ( user_to_phys ( new, 0 ) & ( EM_ALIGN - 1 ) );
 | 
		
	
		
			
			| 168 | 182 |  		new_size += align;
 | 
		
	
	
		
			
			|  | @@ -174,8 +188,9 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
 | 
		
	
		
			
			| 174 | 188 |  		      user_to_phys ( new, new_size ));
 | 
		
	
		
			
			| 175 | 189 |  		memmove_user ( new, 0, ptr, 0, ( ( extmem.size < new_size ) ?
 | 
		
	
		
			
			| 176 | 190 |  						 extmem.size : new_size ) );
 | 
		
	
		
			
			| 177 |  | -		extmem.size = new_size;
 | 
		
	
		
			
			| 178 | 191 |  		bottom = new;
 | 
		
	
		
			
			|  | 192 | +		heap_size -= ( new_size - extmem.size );
 | 
		
	
		
			
			|  | 193 | +		extmem.size = new_size;
 | 
		
	
		
			
			| 179 | 194 |  	} else {
 | 
		
	
		
			
			| 180 | 195 |  		/* Cannot expand; can only pretend to shrink */
 | 
		
	
		
			
			| 181 | 196 |  		if ( new_size > extmem.size ) {
 | 
		
	
	
		
			
			|  | @@ -193,7 +208,7 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
 | 
		
	
		
			
			| 193 | 208 |  
 | 
		
	
		
			
			| 194 | 209 |  	/* Collect any free blocks and update hidden memory region */
 | 
		
	
		
			
			| 195 | 210 |  	ecollect_free();
 | 
		
	
		
			
			| 196 |  | -	hide_umalloc ( user_to_phys ( bottom, -sizeof ( extmem ) ),
 | 
		
	
		
			
			|  | 211 | +	hide_umalloc ( user_to_phys ( bottom, 0 ),
 | 
		
	
		
			
			| 197 | 212 |  		       user_to_phys ( top, 0 ) );
 | 
		
	
		
			
			| 198 | 213 |  
 | 
		
	
		
			
			| 199 | 214 |  	return ( new_size ? new : UNOWHERE );
 |