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

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

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
  * Prototypes for the standard functions (malloc() et al) are in
15
  * Prototypes for the standard functions (malloc() et al) are in
77
  * If @c ptr is NULL, no action is taken.
77
  * If @c ptr is NULL, no action is taken.
78
  */
78
  */
79
 static inline void free_dma ( void *ptr, size_t size ) {
79
 static inline void free_dma ( void *ptr, size_t size ) {
80
-	free_memblock ( ptr, size );
81
 	VALGRIND_FREELIKE_BLOCK ( ptr, 0 );
80
 	VALGRIND_FREELIKE_BLOCK ( ptr, 0 );
81
+	free_memblock ( ptr, size );
82
 }
82
 }
83
 
83
 
84
 /** A cache discarder */
84
 /** A cache discarder */

Loading…
Cancel
Save