|
@@ -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 */
|