LCOV - code coverage report
Current view: top level - libs/mem/src - mem_resize.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 85.2 % 128 109
Test Date: 2026-03-01 04:31:48 Functions: 100.0 % 2 2
Branches: 64.7 % 102 66

             Branch data     Line data    Source code
       1                 :             : #include "mem.h"
       2                 :             : #include <stdarg.h>
       3                 :             : #include <string.h>
       4                 :             : #include <limits.h>
       5                 :             : 
       6                 :             : /**
       7                 :             :  * @brief Round a byte size up to the allocator block boundary.
       8                 :             :  *
       9                 :             :  * Aligns @p requested_bytes to the next multiple of @ref MEMORY_BLOCK_BYTES, preserving zero
      10                 :             :  * and guarding against overflow. Returns non-zero on error so callers can log and fail early.
      11                 :             :  *
      12                 :             :  * @param requested_bytes Number of bytes requested by the caller.
      13                 :             :  * @param aligned_bytes   Output pointer receiving the aligned size when successful.
      14                 :             :  * @return 0 on success; non-zero if @p aligned_bytes is NULL or an overflow occurred.
      15                 :             :  */
      16                 :        4619 : static int align_to_block_boundary(
      17                 :             :         size_t requested_bytes,
      18                 :             :         size_t *aligned_bytes)
      19                 :             : {
      20         [ -  + ]:        4619 :         if(aligned_bytes == NULL)
      21                 :             :         {
      22                 :           0 :                 return 1;
      23                 :             :         }
      24                 :             : 
      25         [ -  + ]:        4619 :         if(requested_bytes == 0)
      26                 :             :         {
      27                 :           0 :                 *aligned_bytes = 0;
      28                 :           0 :                 return 0;
      29                 :             :         }
      30                 :             : 
      31                 :        4619 :         const size_t remainder = requested_bytes % MEMORY_BLOCK_BYTES;
      32                 :             : 
      33         [ +  + ]:        4619 :         if(remainder == 0)
      34                 :             :         {
      35                 :         117 :                 *aligned_bytes = requested_bytes;
      36                 :         117 :                 return 0;
      37                 :             :         }
      38                 :             : 
      39                 :        4502 :         const size_t padding = MEMORY_BLOCK_BYTES - remainder;
      40                 :             : 
      41         [ -  + ]:        4502 :         if(requested_bytes > SIZE_MAX - padding)
      42                 :             :         {
      43                 :           0 :                 return 1;
      44                 :             :         }
      45                 :             : 
      46                 :        4502 :         *aligned_bytes = requested_bytes + padding;
      47                 :        4502 :         return 0;
      48                 :             : }
      49                 :             : 
      50                 :        4650 : Return memory_resize(
      51                 :             :         memory *memory_structure,
      52                 :             :         size_t new_count,
      53                 :             :         ...)
      54                 :             : {
      55                 :             :         /* Status returned by this function through provide()
      56                 :             :            Default value assumes successful completion */
      57                 :        4650 :         Return status = SUCCESS;
      58                 :        4650 :         unsigned char behavior_flags = 0U;
      59                 :             : 
      60                 :             :         va_list optional_arguments;
      61                 :        4650 :         va_start(optional_arguments,new_count);
      62                 :        4650 :         const unsigned int provided_flags = va_arg(optional_arguments,unsigned int);
      63                 :             : 
      64         [ +  + ]:        4650 :         if(provided_flags == UCHAR_MAX)
      65                 :             :         {
      66                 :        4267 :                 behavior_flags = 0U;
      67                 :             :         } else {
      68                 :         383 :                 behavior_flags = (unsigned char)provided_flags;
      69                 :         383 :                 const unsigned int terminator = va_arg(optional_arguments,unsigned int);
      70                 :             : 
      71         [ -  + ]:         383 :                 if(terminator != UCHAR_MAX)
      72                 :             :                 {
      73                 :           0 :                         report("Memory management; Resize flags terminator missing");
      74                 :           0 :                         status = FAILURE;
      75                 :             :                 }
      76                 :             :         }
      77                 :        4650 :         va_end(optional_arguments);
      78                 :             : 
      79                 :        4650 :         const bool zero_new_memory = (behavior_flags & ZERO_NEW_MEMORY) != 0U;
      80                 :        4650 :         const bool allow_shrink = (behavior_flags & RELEASE_UNUSED) != 0U;
      81                 :             : 
      82         [ +  - ]:        4650 :         if(TRIUMPH & status)
      83                 :             :         {
      84   [ +  -  -  + ]:        4650 :                 if(memory_structure == NULL || memory_structure->element_size == 0)
      85                 :             :                 {
      86                 :           0 :                         report("Memory management; Descriptor is NULL or not initialized");
      87                 :           0 :                         provide(FAILURE);
      88                 :             :                 }
      89                 :             :         }
      90                 :             : 
      91                 :        4650 :         size_t previous_effective_bytes = 0;
      92                 :        4650 :         size_t previous_allocated_bytes = 0;
      93                 :        4650 :         size_t previous_elements = 0;
      94                 :        4650 :         size_t previous_alignment_overhead = 0;
      95                 :        4650 :         size_t total_size_in_bytes = 0;
      96                 :             : 
      97         [ +  - ]:        4650 :         if(TRIUMPH & status)
      98                 :             :         {
      99                 :        4650 :                 previous_elements = memory_structure->length;
     100                 :        4650 :                 previous_allocated_bytes = memory_structure->actually_allocated_bytes;
     101                 :        4650 :                 previous_effective_bytes = 0;
     102                 :             : 
     103   [ +  -  -  + ]:        4650 :                 run(memory_guarded_size(memory_structure->element_size,
     104                 :             :                         previous_elements,
     105                 :             :                         &previous_effective_bytes));
     106                 :             : 
     107         [ +  + ]:        4650 :                 if(previous_allocated_bytes > previous_effective_bytes)
     108                 :             :                 {
     109                 :        1074 :                         previous_alignment_overhead = previous_allocated_bytes - previous_effective_bytes;
     110                 :             :                 }
     111                 :             :         }
     112                 :             : 
     113   [ +  -  +  + ]:        4650 :         if((TRIUMPH & status) && new_count == previous_elements)
     114                 :             :         {
     115         [ +  + ]:          31 :                 if(new_count == 0)
     116                 :             :                 {
     117         [ +  - ]:           1 :                         if(memory_structure->data == NULL)
     118                 :             :                         {
     119                 :           1 :                                 telemetry_realloc_noop_counter();
     120                 :           1 :                                 telemetry_noop_resize_event();
     121                 :           1 :                                 provide(status);
     122                 :             :                         }
     123                 :             :                 } else {
     124                 :          30 :                         telemetry_realloc_noop_counter();
     125                 :          30 :                         telemetry_noop_resize_event();
     126                 :          30 :                         provide(status);
     127                 :             :                 }
     128                 :             :         }
     129                 :             : 
     130                 :        4619 :         telemetry_reset_noop_streak();
     131                 :             : 
     132   [ +  -  -  + ]:        4619 :         run(memory_guarded_size(memory_structure->element_size,new_count,&total_size_in_bytes));
     133                 :             : 
     134         [ -  + ]:        4619 :         if(CRITICAL & status)
     135                 :             :         {
     136                 :           0 :                 report("Memory management; Overflow for length=%zu (element_size=%zu)",new_count,memory_structure->element_size);
     137                 :             :         }
     138                 :             : 
     139         [ +  - ]:        4619 :         if(TRIUMPH & status)
     140                 :             :         {
     141         [ -  + ]:        4619 :                 if(new_count == 0)
     142                 :             :                 {
     143   [ #  #  #  # ]:           0 :                         call(del(memory_structure));
     144                 :             :                 } else {
     145                 :        4619 :                         size_t aligned_size_in_bytes = 0;
     146                 :             : 
     147         [ -  + ]:        4619 :                         if(align_to_block_boundary(total_size_in_bytes,&aligned_size_in_bytes) != 0)
     148                 :             :                         {
     149                 :           0 :                                 report("Memory management; Allocation alignment overflow for %zu bytes",total_size_in_bytes);
     150                 :           0 :                                 status = FAILURE;
     151                 :             :                         } else {
     152                 :        4619 :                                 const bool needs_fresh_allocation = memory_structure->data == NULL;
     153                 :        4619 :                                 const bool needs_growth = aligned_size_in_bytes > memory_structure->actually_allocated_bytes;
     154         [ +  + ]:        4620 :                                 const bool should_shrink = allow_shrink &&
     155         [ +  - ]:           1 :                                         aligned_size_in_bytes < memory_structure->actually_allocated_bytes;
     156                 :             : 
     157   [ +  +  +  +  :        4619 :                                 if(needs_fresh_allocation || needs_growth || should_shrink)
                   +  + ]
     158                 :        3603 :                                 {
     159                 :        3603 :                                         void *resized_pointer = NULL;
     160                 :             : 
     161         [ +  + ]:        3603 :                                         if(needs_fresh_allocation)
     162                 :             :                                         {
     163                 :        3574 :                                                 resized_pointer = malloc(aligned_size_in_bytes);
     164                 :             :                                         } else {
     165                 :          29 :                                                 resized_pointer = realloc(memory_structure->data,aligned_size_in_bytes);
     166                 :             :                                         }
     167                 :             : 
     168         [ -  + ]:        3603 :                                         if(resized_pointer == NULL)
     169                 :             :                                         {
     170                 :           0 :                                                 report("Memory management; Memory allocation failed for %zu bytes",aligned_size_in_bytes);
     171                 :           0 :                                                 status = FAILURE;
     172                 :             : 
     173         [ #  # ]:           0 :                                                 if(needs_fresh_allocation)
     174                 :             :                                                 {
     175                 :           0 :                                                         telemetry_allocation_failure();
     176                 :             :                                                 } else {
     177                 :           0 :                                                         telemetry_reallocation_failure();
     178                 :             :                                                 }
     179                 :             :                                         } else {
     180                 :        3603 :                                                 memory_structure->data = resized_pointer;
     181                 :             : 
     182         [ +  + ]:        3603 :                                                 if(needs_fresh_allocation)
     183                 :             :                                                 {
     184                 :        3574 :                                                         telemetry_active_descriptor_acquire();
     185                 :        3574 :                                                         telemetry_new_allocations_counter();
     186                 :             : 
     187         [ +  - ]:        3574 :                                                         if(aligned_size_in_bytes > 0)
     188                 :             :                                                         {
     189                 :        3574 :                                                                 telemetry_add(aligned_size_in_bytes);
     190                 :             :                                                         }
     191         [ +  + ]:          29 :                                                 } else if(needs_growth){
     192                 :          28 :                                                         telemetry_aligned_reallocations_counter();
     193                 :          28 :                                                         telemetry_add(aligned_size_in_bytes - previous_allocated_bytes);
     194         [ +  - ]:           1 :                                                 } else if(should_shrink){
     195                 :           1 :                                                         telemetry_aligned_reallocations_counter();
     196                 :           1 :                                                         const size_t reclaimed_bytes = previous_allocated_bytes - aligned_size_in_bytes;
     197                 :             : 
     198         [ +  - ]:           1 :                                                         if(reclaimed_bytes > 0)
     199                 :             :                                                         {
     200                 :           1 :                                                                 telemetry_release_unused_operation();
     201                 :           1 :                                                                 telemetry_release_unused_bytes(reclaimed_bytes);
     202                 :           1 :                                                                 telemetry_reduce(reclaimed_bytes);
     203                 :           1 :                                                                 telemetry_free_total_bytes(reclaimed_bytes);
     204                 :             :                                                         }
     205                 :             :                                                 }
     206                 :             : 
     207                 :        3603 :                                                 memory_structure->actually_allocated_bytes = aligned_size_in_bytes;
     208                 :             :                                         }
     209                 :             :                                 } else {
     210                 :        1016 :                                         telemetry_realloc_optimized_counter();
     211                 :             :                                 }
     212                 :             : 
     213         [ +  - ]:        4619 :                                 if(TRIUMPH & status)
     214                 :             :                                 {
     215                 :        4619 :                                         size_t bytes_to_zero = 0;
     216                 :             : 
     217   [ +  +  +  - ]:        4619 :                                         if(zero_new_memory && total_size_in_bytes > previous_effective_bytes)
     218                 :             :                                         {
     219                 :         382 :                                                 bytes_to_zero = total_size_in_bytes - previous_effective_bytes;
     220                 :             :                                         }
     221                 :             : 
     222                 :        4619 :                                         memory_structure->length = new_count;
     223                 :             : 
     224         [ +  + ]:        4619 :                                         if(bytes_to_zero > 0)
     225                 :             :                                         {
     226                 :         382 :                                                 unsigned char *byte_view = (unsigned char *)memory_structure->data;
     227                 :             : 
     228         [ -  + ]:         382 :                                                 if(byte_view == NULL)
     229                 :             :                                                 {
     230                 :           0 :                                                         report("Memory management; Data pointer is NULL during zero-fill");
     231                 :           0 :                                                         status = FAILURE;
     232                 :             :                                                 } else {
     233                 :         382 :                                                         memset(byte_view + previous_effective_bytes,0,bytes_to_zero);
     234                 :         382 :                                                         telemetry_new_callocations_counter();
     235                 :             :                                                 }
     236                 :             :                                         }
     237                 :             : 
     238         [ +  - ]:        4619 :                                         if(TRIUMPH & status)
     239                 :             :                                         {
     240         [ +  + ]:        4619 :                                                 if(total_size_in_bytes > previous_effective_bytes)
     241                 :             :                                                 {
     242                 :        4412 :                                                         telemetry_effective_add(total_size_in_bytes - previous_effective_bytes);
     243         [ +  - ]:         207 :                                                 } else if(total_size_in_bytes < previous_effective_bytes){
     244                 :         207 :                                                         telemetry_effective_reduce(previous_effective_bytes - total_size_in_bytes);
     245                 :             :                                                 }
     246                 :             :                                         }
     247                 :             :                                 }
     248                 :             :                         }
     249                 :             :                 }
     250                 :             :         }
     251                 :             : 
     252   [ +  -  +  - ]:        4619 :         if((TRIUMPH & status) && new_count != 0)
     253                 :             :         {
     254                 :        4619 :                 const size_t resulting_allocated_bytes = memory_structure->actually_allocated_bytes;
     255                 :        4619 :                 size_t new_alignment_overhead = 0;
     256                 :             : 
     257         [ +  + ]:        4619 :                 if(resulting_allocated_bytes > total_size_in_bytes)
     258                 :             :                 {
     259                 :        4502 :                         new_alignment_overhead = resulting_allocated_bytes - total_size_in_bytes;
     260                 :             :                 }
     261                 :             : 
     262         [ +  + ]:        4619 :                 if(new_alignment_overhead > previous_alignment_overhead)
     263                 :             :                 {
     264                 :        3683 :                         telemetry_alignment_overhead_add(new_alignment_overhead - previous_alignment_overhead);
     265         [ +  + ]:         936 :                 } else if(new_alignment_overhead < previous_alignment_overhead){
     266                 :         817 :                         telemetry_alignment_overhead_reduce(previous_alignment_overhead - new_alignment_overhead);
     267                 :             :                 }
     268                 :             :         }
     269                 :             : 
     270                 :        4619 :         provide(status);
     271                 :             : }
        

Generated by: LCOV version 2.0-1