Browse Source

[malloc] Rewrite unrelicensable portions of malloc.c

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
b2f38da888
2 changed files with 43 additions and 24 deletions
  1. 41
    22
      src/core/malloc.c
  2. 2
    2
      src/include/ipxe/malloc.h

+ 41
- 22
src/core/malloc.c View File

@@ -15,9 +15,13 @@
15 15
  * along with this program; if not, write to the Free Software
16 16
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 17
  * 02110-1301, USA.
18
+ *
19
+ * You can also choose to distribute this program under the terms of
20
+ * the Unmodified Binary Distribution Licence (as given in the file
21
+ * COPYING.UBDL), provided that you have satisfied its requirements.
18 22
  */
19 23
 
20
-FILE_LICENCE ( GPL2_OR_LATER );
24
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
21 25
 
22 26
 #include <stddef.h>
23 27
 #include <stdint.h>
@@ -106,6 +110,7 @@ static char heap[HEAP_SIZE] __attribute__ (( aligned ( __alignof__(void *) )));
106 110
 static inline void valgrind_make_blocks_defined ( void ) {
107 111
 	struct memory_block *block;
108 112
 
113
+	/* Do nothing unless running under Valgrind */
109 114
 	if ( RUNNING_ON_VALGRIND <= 0 )
110 115
 		return;
111 116
 
@@ -147,6 +152,7 @@ static inline void valgrind_make_blocks_noaccess ( void ) {
147 152
 	struct memory_block *block;
148 153
 	struct memory_block *prev = NULL;
149 154
 
155
+	/* Do nothing unless running under Valgrind */
150 156
 	if ( RUNNING_ON_VALGRIND <= 0 )
151 157
 		return;
152 158
 
@@ -267,24 +273,25 @@ static void discard_all_cache ( void ) {
267 273
 void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
268 274
 	struct memory_block *block;
269 275
 	size_t align_mask;
276
+	size_t actual_size;
270 277
 	size_t pre_size;
271 278
 	ssize_t post_size;
272 279
 	struct memory_block *pre;
273 280
 	struct memory_block *post;
274
-	struct memory_block *ptr;
281
+	void *ptr;
275 282
 
276 283
 	/* Sanity checks */
277 284
 	assert ( size != 0 );
278 285
 	assert ( ( align == 0 ) || ( ( align & ( align - 1 ) ) == 0 ) );
279
-
280 286
 	valgrind_make_blocks_defined();
281 287
 	check_blocks();
282 288
 
283 289
 	/* Round up size to multiple of MIN_MEMBLOCK_SIZE and
284 290
 	 * calculate alignment mask.
285 291
 	 */
286
-	size = ( size + MIN_MEMBLOCK_SIZE - 1 ) & ~( MIN_MEMBLOCK_SIZE - 1 );
287
-	align_mask = ( align - 1 ) | ( MIN_MEMBLOCK_SIZE - 1 );
292
+	actual_size = ( ( size + MIN_MEMBLOCK_SIZE - 1 ) &
293
+			~( MIN_MEMBLOCK_SIZE - 1 ) );
294
+	align_mask = ( ( align - 1 ) | ( MIN_MEMBLOCK_SIZE - 1 ) );
288 295
 
289 296
 	DBGC2 ( &heap, "Allocating %#zx (aligned %#zx+%zx)\n",
290 297
 		size, align, offset );
@@ -293,7 +300,7 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
293 300
 		list_for_each_entry ( block, &free_blocks, list ) {
294 301
 			pre_size = ( ( offset - virt_to_phys ( block ) )
295 302
 				     & align_mask );
296
-			post_size = ( block->size - pre_size - size );
303
+			post_size = ( block->size - pre_size - actual_size );
297 304
 			if ( post_size >= 0 ) {
298 305
 				/* Split block into pre-block, block, and
299 306
 				 * post-block.  After this split, the "pre"
@@ -302,7 +309,7 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
302 309
 				 */
303 310
 				pre   = block;
304 311
 				block = ( ( ( void * ) pre   ) + pre_size );
305
-				post  = ( ( ( void * ) block ) + size     );
312
+				post  = ( ( ( void * ) block ) + actual_size );
306 313
 				DBGC2 ( &heap, "[%p,%p) -> [%p,%p) + [%p,%p)\n",
307 314
 					pre, ( ( ( void * ) pre ) + pre->size ),
308 315
 					pre, block, post,
@@ -313,8 +320,8 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
313 320
 				 * the heap).
314 321
 				 */
315 322
 				if ( (size_t) post_size >= MIN_MEMBLOCK_SIZE ) {
316
-					VALGRIND_MAKE_MEM_DEFINED ( post,
317
-							     sizeof ( *post ) );
323
+					VALGRIND_MAKE_MEM_UNDEFINED
324
+						( post, sizeof ( *post ) );
318 325
 					post->size = post_size;
319 326
 					list_add ( &post->list, &pre->list );
320 327
 				}
@@ -328,14 +335,18 @@ void * alloc_memblock ( size_t size, size_t align, size_t offset ) {
328 335
 				 * it is too small, which can happen only at
329 336
 				 * the very start of the heap.
330 337
 				 */
331
-				if ( pre_size < MIN_MEMBLOCK_SIZE )
338
+				if ( pre_size < MIN_MEMBLOCK_SIZE ) {
332 339
 					list_del ( &pre->list );
340
+					VALGRIND_MAKE_MEM_NOACCESS
341
+						( pre, sizeof ( *pre ) );
342
+				}
333 343
 				/* Update total free memory */
334
-				freemem -= size;
344
+				freemem -= actual_size;
335 345
 				/* Return allocated block */
336 346
 				DBGC2 ( &heap, "Allocated [%p,%p)\n", block,
337 347
 					( ( ( void * ) block ) + size ) );
338 348
 				ptr = block;
349
+				VALGRIND_MAKE_MEM_UNDEFINED ( ptr, size );
339 350
 				goto done;
340 351
 			}
341 352
 		}
@@ -368,13 +379,16 @@ void free_memblock ( void *ptr, size_t size ) {
368 379
 	struct memory_block *freeing;
369 380
 	struct memory_block *block;
370 381
 	struct memory_block *tmp;
382
+	size_t actual_size;
371 383
 	ssize_t gap_before;
372 384
 	ssize_t gap_after = -1;
373 385
 
374 386
 	/* Allow for ptr==NULL */
375 387
 	if ( ! ptr )
376 388
 		return;
389
+	VALGRIND_MAKE_MEM_NOACCESS ( ptr, size );
377 390
 
391
+	/* Sanity checks */
378 392
 	valgrind_make_blocks_defined();
379 393
 	check_blocks();
380 394
 
@@ -382,9 +396,10 @@ void free_memblock ( void *ptr, size_t size ) {
382 396
 	 * would have used.
383 397
 	 */
384 398
 	assert ( size != 0 );
385
-	size = ( size + MIN_MEMBLOCK_SIZE - 1 ) & ~( MIN_MEMBLOCK_SIZE - 1 );
399
+	actual_size = ( ( size + MIN_MEMBLOCK_SIZE - 1 ) &
400
+			~( MIN_MEMBLOCK_SIZE - 1 ) );
386 401
 	freeing = ptr;
387
-	VALGRIND_MAKE_MEM_DEFINED ( freeing, sizeof ( *freeing ) );
402
+	VALGRIND_MAKE_MEM_UNDEFINED ( freeing, sizeof ( *freeing ) );
388 403
 	DBGC2 ( &heap, "Freeing [%p,%p)\n",
389 404
 		freeing, ( ( ( void * ) freeing ) + size ) );
390 405
 
@@ -392,7 +407,7 @@ void free_memblock ( void *ptr, size_t size ) {
392 407
 	if ( ASSERTING ) {
393 408
 		list_for_each_entry ( block, &free_blocks, list ) {
394 409
 			if ( ( ( ( void * ) block ) <
395
-			       ( ( void * ) freeing + size ) ) &&
410
+			       ( ( void * ) freeing + actual_size ) ) &&
396 411
 			     ( ( void * ) freeing <
397 412
 			       ( ( void * ) block + block->size ) ) ) {
398 413
 				assert ( 0 );
@@ -407,7 +422,7 @@ void free_memblock ( void *ptr, size_t size ) {
407 422
 	}
408 423
 
409 424
 	/* Insert/merge into free list */
410
-	freeing->size = size;
425
+	freeing->size = actual_size;
411 426
 	list_for_each_entry_safe ( block, tmp, &free_blocks, list ) {
412 427
 		/* Calculate gaps before and after the "freeing" block */
413 428
 		gap_before = ( ( ( void * ) freeing ) - 
@@ -421,8 +436,10 @@ void free_memblock ( void *ptr, size_t size ) {
421 436
 				( ( ( void * ) freeing ) + freeing->size ),
422 437
 				block,
423 438
 				( ( ( void * ) freeing ) + freeing->size ) );
424
-			block->size += size;
439
+			block->size += actual_size;
425 440
 			list_del ( &block->list );
441
+			VALGRIND_MAKE_MEM_NOACCESS ( freeing,
442
+						     sizeof ( *freeing ) );
426 443
 			freeing = block;
427 444
 		}
428 445
 		/* Stop processing as soon as we reach a following block */
@@ -444,10 +461,11 @@ void free_memblock ( void *ptr, size_t size ) {
444 461
 			( ( ( void * ) block ) + block->size ) );
445 462
 		freeing->size += block->size;
446 463
 		list_del ( &block->list );
464
+		VALGRIND_MAKE_MEM_NOACCESS ( block, sizeof ( *block ) );
447 465
 	}
448 466
 
449 467
 	/* Update free memory counter */
450
-	freemem += size;
468
+	freemem += actual_size;
451 469
 
452 470
 	check_blocks();
453 471
 	valgrind_make_blocks_noaccess();
@@ -490,9 +508,9 @@ void * realloc ( void *old_ptr, size_t new_size ) {
490 508
 		new_block = alloc_memblock ( new_total_size, 1, 0 );
491 509
 		if ( ! new_block )
492 510
 			return NULL;
493
-		VALGRIND_MAKE_MEM_UNDEFINED ( new_block, offsetof ( struct autosized_block, data ) );
494 511
 		new_block->size = new_total_size;
495
-		VALGRIND_MAKE_MEM_NOACCESS ( new_block, offsetof ( struct autosized_block, data ) );
512
+		VALGRIND_MAKE_MEM_NOACCESS ( &new_block->size,
513
+					     sizeof ( new_block->size ) );
496 514
 		new_ptr = &new_block->data;
497 515
 		VALGRIND_MALLOCLIKE_BLOCK ( new_ptr, new_size, 0, 0 );
498 516
 	}
@@ -505,16 +523,16 @@ void * realloc ( void *old_ptr, size_t new_size ) {
505 523
 	if ( old_ptr && ( old_ptr != NOWHERE ) ) {
506 524
 		old_block = container_of ( old_ptr, struct autosized_block,
507 525
 					   data );
508
-		VALGRIND_MAKE_MEM_DEFINED ( old_block, offsetof ( struct autosized_block, data ) );
526
+		VALGRIND_MAKE_MEM_DEFINED ( &old_block->size,
527
+					    sizeof ( old_block->size ) );
509 528
 		old_total_size = old_block->size;
510 529
 		assert ( old_total_size != 0 );
511 530
 		old_size = ( old_total_size -
512 531
 			     offsetof ( struct autosized_block, data ) );
513 532
 		memcpy ( new_ptr, old_ptr,
514 533
 			 ( ( old_size < new_size ) ? old_size : new_size ) );
515
-		free_memblock ( old_block, old_total_size );
516
-		VALGRIND_MAKE_MEM_NOACCESS ( old_block, offsetof ( struct autosized_block, data ) );
517 534
 		VALGRIND_FREELIKE_BLOCK ( old_ptr, 0 );
535
+		free_memblock ( old_block, old_total_size );
518 536
 	}
519 537
 
520 538
 	if ( ASSERTED ) {
@@ -611,6 +629,7 @@ void mpopulate ( void *start, size_t len ) {
611 629
  */
612 630
 static void init_heap ( void ) {
613 631
 	VALGRIND_MAKE_MEM_NOACCESS ( heap, sizeof ( heap ) );
632
+	VALGRIND_MAKE_MEM_NOACCESS ( &free_blocks, sizeof ( free_blocks ) );
614 633
 	mpopulate ( heap, sizeof ( heap ) );
615 634
 }
616 635
 

+ 2
- 2
src/include/ipxe/malloc.h View File

@@ -9,7 +9,7 @@
9 9
  *
10 10
  */
11 11
 
12
-FILE_LICENCE ( GPL2_OR_LATER );
12
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
13 13
 
14 14
 /*
15 15
  * Prototypes for the standard functions (malloc() et al) are in
@@ -77,8 +77,8 @@ static inline void * __malloc malloc_dma ( size_t size, size_t phys_align ) {
77 77
  * If @c ptr is NULL, no action is taken.
78 78
  */
79 79
 static inline void free_dma ( void *ptr, size_t size ) {
80
-	free_memblock ( ptr, size );
81 80
 	VALGRIND_FREELIKE_BLOCK ( ptr, 0 );
81
+	free_memblock ( ptr, size );
82 82
 }
83 83
 
84 84
 /** A cache discarder */

Loading…
Cancel
Save