@@ -383,37 +383,24 @@ void *sys_heap_aligned_alloc(struct sys_heap *heap, size_t align, size_t bytes)
383
383
return mem ;
384
384
}
385
385
386
- void * sys_heap_aligned_realloc (struct sys_heap * heap , void * ptr ,
387
- size_t align , size_t bytes )
386
+ static bool inplace_realloc (struct sys_heap * heap , void * ptr , size_t bytes )
388
387
{
389
388
struct z_heap * h = heap -> heap ;
390
389
391
- /* special realloc semantics */
392
- if (ptr == NULL ) {
393
- return sys_heap_aligned_alloc (heap , align , bytes );
394
- }
395
- if (bytes == 0 ) {
396
- sys_heap_free (heap , ptr );
397
- return NULL ;
398
- }
399
-
400
- __ASSERT ((align & (align - 1 )) == 0 , "align must be a power of 2" );
401
-
402
390
if (size_too_big (h , bytes )) {
403
- return NULL ;
391
+ return false ;
404
392
}
405
393
406
394
chunkid_t c = mem_to_chunkid (h , ptr );
407
- chunkid_t rc = right_chunk (h , c );
408
395
size_t align_gap = (uint8_t * )ptr - (uint8_t * )chunk_mem (h , c );
409
396
chunksz_t chunks_need = bytes_to_chunksz (h , bytes + align_gap );
410
397
411
- if (align && ((uintptr_t )ptr & (align - 1 ))) {
412
- /* ptr is not sufficiently aligned */
413
- } else if (chunk_size (h , c ) == chunks_need ) {
398
+ if (chunk_size (h , c ) == chunks_need ) {
414
399
/* We're good already */
415
- return ptr ;
416
- } else if (chunk_size (h , c ) > chunks_need ) {
400
+ return true;
401
+ }
402
+
403
+ if (chunk_size (h , c ) > chunks_need ) {
417
404
/* Shrink in place, split off and free unused suffix */
418
405
#ifdef CONFIG_SYS_HEAP_LISTENER
419
406
size_t bytes_freed = chunksz_to_bytes (h , chunk_size (h , c ));
@@ -435,9 +422,13 @@ void *sys_heap_aligned_realloc(struct sys_heap *heap, void *ptr,
435
422
bytes_freed );
436
423
#endif
437
424
438
- return ptr ;
439
- } else if (!chunk_used (h , rc ) &&
440
- (chunk_size (h , c ) + chunk_size (h , rc ) >= chunks_need )) {
425
+ return true;
426
+ }
427
+
428
+ chunkid_t rc = right_chunk (h , c );
429
+
430
+ if (!chunk_used (h , rc ) &&
431
+ (chunk_size (h , c ) + chunk_size (h , rc ) >= chunks_need )) {
441
432
/* Expand: split the right chunk and append */
442
433
chunksz_t split_size = chunks_need - chunk_size (h , c );
443
434
@@ -466,22 +457,66 @@ void *sys_heap_aligned_realloc(struct sys_heap *heap, void *ptr,
466
457
bytes_freed );
467
458
#endif
468
459
460
+ return true;
461
+ }
462
+
463
+ return false;
464
+ }
465
+
466
+ void * sys_heap_realloc (struct sys_heap * heap , void * ptr , size_t bytes )
467
+ {
468
+ /* special realloc semantics */
469
+ if (ptr == NULL ) {
470
+ return sys_heap_alloc (heap , bytes );
471
+ }
472
+ if (bytes == 0 ) {
473
+ sys_heap_free (heap , ptr );
474
+ return NULL ;
475
+ }
476
+
477
+ if (inplace_realloc (heap , ptr , bytes )) {
478
+ return ptr ;
479
+ }
480
+
481
+ /* In-place realloc was not possible: fallback to allocate and copy. */
482
+ void * ptr2 = sys_heap_alloc (heap , bytes );
483
+
484
+ if (ptr2 != NULL ) {
485
+ size_t prev_size = sys_heap_usable_size (heap , ptr );
486
+
487
+ memcpy (ptr2 , ptr , MIN (prev_size , bytes ));
488
+ sys_heap_free (heap , ptr );
489
+ }
490
+ return ptr2 ;
491
+ }
492
+
493
+ void * sys_heap_aligned_realloc (struct sys_heap * heap , void * ptr ,
494
+ size_t align , size_t bytes )
495
+ {
496
+ /* special realloc semantics */
497
+ if (ptr == NULL ) {
498
+ return sys_heap_aligned_alloc (heap , align , bytes );
499
+ }
500
+ if (bytes == 0 ) {
501
+ sys_heap_free (heap , ptr );
502
+ return NULL ;
503
+ }
504
+
505
+ __ASSERT ((align & (align - 1 )) == 0 , "align must be a power of 2" );
506
+
507
+ if ((align == 0 || ((uintptr_t )ptr & (align - 1 )) == 0 ) &&
508
+ inplace_realloc (heap , ptr , bytes )) {
469
509
return ptr ;
470
- } else {
471
- ;
472
510
}
473
511
474
512
/*
475
- * Fallback: allocate and copy
476
- *
477
- * Note for heap listener notification:
478
- * The calls to allocation and free functions generate
479
- * notification already, so there is no need to those here.
513
+ * Either ptr is not sufficiently aligned for in-place realloc or
514
+ * in-place realloc was not possible: fallback to allocate and copy.
480
515
*/
481
516
void * ptr2 = sys_heap_aligned_alloc (heap , align , bytes );
482
517
483
518
if (ptr2 != NULL ) {
484
- size_t prev_size = chunksz_to_bytes ( h , chunk_size ( h , c )) - align_gap ;
519
+ size_t prev_size = sys_heap_usable_size ( heap , ptr ) ;
485
520
486
521
memcpy (ptr2 , ptr , MIN (prev_size , bytes ));
487
522
sys_heap_free (heap , ptr );
0 commit comments