@@ -434,26 +434,27 @@ static void s_aws_ticket_wrapper_destroy(void *data) {
434434 if (ticket -> reserved_from == AWS_S3_BUFFER_POOL_RESERVED_FROM_SPECIAL ) {
435435 struct aws_hash_element * elem = NULL ;
436436 aws_hash_table_find (& buffer_pool -> special_blocks , (void * )ticket -> size , & elem );
437- /* TODO: the lifetime between the ticket and the special block, let's assume the block will always be
438- * available first. */
439- AWS_FATAL_ASSERT (elem != NULL );
440- special_list = elem -> value ;
441-
442- bool found = false;
443- for (size_t i = 0 ; i < aws_array_list_length (& special_list -> blocks ); ++ i ) {
444- struct s3_buffer_pool_block * block ;
445- aws_array_list_get_at_ptr (& special_list -> blocks , (void * * )& block , i );
446- if (block -> block_ptr == ticket -> ptr ) {
447- /* Make sure the block is marked as used. */
448- AWS_FATAL_ASSERT (block -> alloc_bit_mask == UINT16_MAX );
449- block -> alloc_bit_mask = 0 ;
450- found = true;
451- break ;
437+ if (elem ) {
438+ special_list = elem -> value ;
439+
440+ bool found = false;
441+ for (size_t i = 0 ; i < aws_array_list_length (& special_list -> blocks ); ++ i ) {
442+ struct s3_buffer_pool_block * block ;
443+ aws_array_list_get_at_ptr (& special_list -> blocks , (void * * )& block , i );
444+ if (block -> block_ptr == ticket -> ptr ) {
445+ /* Make sure the block is marked as used. */
446+ if (block -> alloc_bit_mask == UINT16_MAX ) {
447+ block -> alloc_bit_mask = 0 ;
448+ found = true;
449+ break ;
450+ }
451+ }
452+ }
453+ /* Make sure we do find where the ticket buffer from the list. */
454+ if (found ) {
455+ buffer_pool -> special_blocks_used -= ticket -> size ;
452456 }
453457 }
454- /* Make sure we do find where the ticket buffer from the list. */
455- AWS_FATAL_ASSERT (found );
456- buffer_pool -> special_blocks_used -= ticket -> size ;
457458 } else if (ticket -> reserved_from == AWS_S3_BUFFER_POOL_RESERVED_FROM_PRIMARY ) {
458459
459460 size_t chunks_used = ticket -> size / buffer_pool -> chunk_size ;
@@ -557,37 +558,31 @@ static void s_aws_ticket_wrapper_destroy(void *data) {
557558static bool s_should_trim_for_reserve_synced (
558559 bool from_special ,
559560 size_t to_reserve ,
560- struct aws_s3_default_buffer_pool * buffer_pool ) {
561+ struct aws_s3_default_buffer_pool * buffer_pool ,
562+ size_t overall_taken ) {
561563 if (from_special || to_reserve <= buffer_pool -> primary_size_cutoff ) {
562564 /* Only trim when it will be allocated from secondary, which is directly from malloc. */
563565 return false;
564566 }
565- /* The tracked usage SHOULD NOT overflow. */
566- size_t total_allocated =
567- buffer_pool -> primary_allocated + buffer_pool -> secondary_used + buffer_pool -> special_blocks_allocated ;
567+
568568 size_t total_allocation_needs = 0 ;
569- if (aws_add_size_checked (total_allocated , to_reserve , & total_allocation_needs )) {
570- /* Will overflow, trim it. */
571- return true ;
569+ if (aws_add_size_checked (overall_taken , to_reserve , & total_allocation_needs )) {
570+ /* Will overflow, ignores it, which should not happen . */
571+ return false ;
572572 }
573573 if (total_allocation_needs < buffer_pool -> mem_limit ) {
574574 /* No need to trim as we still have space to allocate the new block. */
575575 return false;
576576 }
577577
578- size_t primary_overallocation = 0 ;
579- int overflow = 0 ;
580- overflow |=
581- aws_sub_size_checked (buffer_pool -> primary_allocated , buffer_pool -> primary_used , & primary_overallocation );
582- overflow |= aws_sub_size_checked (primary_overallocation , buffer_pool -> primary_reserved , & primary_overallocation );
583- size_t special_overallocation = 0 ;
584- overflow |= aws_sub_size_checked (
585- buffer_pool -> special_blocks_allocated , buffer_pool -> special_blocks_used , & special_overallocation );
586- overflow |=
587- aws_sub_size_checked (special_overallocation , buffer_pool -> special_blocks_reserved , & special_overallocation );
588- /* The already allocated should be reasonable and not cause overflow. Otherwise, bugs in the code. */
589- AWS_FATAL_ASSERT (!overflow );
590- /* Use max if overflow */
578+ size_t primary_overallocation = aws_sub_size_saturating (buffer_pool -> primary_allocated , buffer_pool -> primary_used );
579+ /* Reserved can be more tha allocated */
580+ primary_overallocation = aws_sub_size_saturating (primary_overallocation , buffer_pool -> primary_reserved );
581+ size_t special_overallocation =
582+ aws_sub_size_saturating (buffer_pool -> special_blocks_allocated , buffer_pool -> special_blocks_used );
583+ /* Reserved can be more tha allocated */
584+ special_overallocation = aws_sub_size_saturating (special_overallocation , buffer_pool -> special_blocks_reserved );
585+
591586 size_t total_overallocation = aws_add_size_saturating (special_overallocation , primary_overallocation );
592587 if (total_overallocation < to_reserve ) {
593588 /* If the overallocation is less than the new block, trim it won't help, skip trimming. */
@@ -616,7 +611,7 @@ struct aws_s3_default_buffer_ticket *s_try_reserve_synced(
616611 * the blocks, trim the blocks in hopes we can free up enough memory.
617612 * TODO: something smarter, like partial trim?
618613 */
619- if (s_should_trim_for_reserve_synced (from_special , meta .size , buffer_pool )) {
614+ if (s_should_trim_for_reserve_synced (from_special , meta .size , buffer_pool , overall_taken )) {
620615 s_buffer_pool_trim_synced (buffer_pool );
621616 overall_taken = buffer_pool -> primary_used + buffer_pool -> primary_reserved + buffer_pool -> secondary_used +
622617 buffer_pool -> secondary_reserved + buffer_pool -> special_blocks_reserved +
@@ -627,7 +622,7 @@ struct aws_s3_default_buffer_ticket *s_try_reserve_synced(
627622 const size_t max_impact_of_forced_on_limit =
628623 (size_t )(buffer_pool -> mem_limit * (s_max_impact_of_forced_buffers_on_memory_limit_as_percentage / 100.0 ));
629624 if (buffer_pool -> forced_used > max_impact_of_forced_on_limit ) {
630- overall_taken -= buffer_pool -> forced_used - max_impact_of_forced_on_limit ;
625+ overall_taken = ( overall_taken - buffer_pool -> forced_used ) + max_impact_of_forced_on_limit ;
631626 }
632627
633628 if ((meta .size + overall_taken ) <= buffer_pool -> mem_limit ) {
0 commit comments