@@ -623,6 +623,24 @@ static umf_result_t coarse_add_used_block(coarse_t *coarse, void *addr,
623623 return UMF_RESULT_SUCCESS ;
624624}
625625
626+ static umf_result_t coarse_add_free_block (coarse_t * coarse , void * addr ,
627+ size_t size , block_t * * free_block ) {
628+ * free_block = NULL ;
629+
630+ block_t * new_block =
631+ coarse_ravl_add_new (coarse -> all_blocks , addr , size , NULL );
632+ if (new_block == NULL ) {
633+ return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
634+ }
635+
636+ new_block -> used = false;
637+ coarse -> alloc_size += size ;
638+
639+ * free_block = new_block ;
640+
641+ return UMF_RESULT_SUCCESS ;
642+ }
643+
626644static void coarse_ravl_cb_rm_all_blocks_node (void * data , void * arg ) {
627645 assert (data );
628646 assert (arg );
@@ -1053,88 +1071,98 @@ umf_result_t coarse_alloc(coarse_t *coarse, size_t size, size_t alignment,
10531071
10541072 assert (debug_check (coarse ));
10551073
1074+ * resultPtr = NULL ;
1075+
10561076 // Find a block with greater or equal size using the given memory allocation strategy
10571077 block_t * curr = find_free_block (coarse -> free_blocks , size , alignment ,
10581078 coarse -> allocation_strategy );
1079+ if (curr == NULL ) {
1080+ // no suitable block found - try to get more memory from the upstream provider
1081+ umf_result = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
10591082
1060- // If the block that we want to reuse has a greater size, split it.
1061- // Try to merge the split part with the successor if it is not used.
1062- enum { ACTION_NONE = 0 , ACTION_USE , ACTION_SPLIT } action = ACTION_NONE ;
1063-
1064- if (curr && curr -> size > size ) {
1065- action = ACTION_SPLIT ;
1066- } else if (curr && curr -> size == size ) {
1067- action = ACTION_USE ;
1068- }
1069-
1070- if (action ) { // ACTION_SPLIT or ACTION_USE
1071- assert (curr -> used == false);
1072-
1073- // In case of non-zero alignment create an aligned block what would be further used.
1074- if (alignment > 0 ) {
1075- umf_result = create_aligned_block (coarse , size , alignment , & curr );
1076- if (umf_result != UMF_RESULT_SUCCESS ) {
1077- (void )free_blocks_re_add (coarse , curr );
1078- goto err_unlock ;
1079- }
1083+ if (!coarse -> cb .alloc ) {
1084+ LOG_ERR ("out of memory" );
1085+ goto err_unlock ;
10801086 }
10811087
1082- if (action == ACTION_SPLIT ) {
1083- // Split the current block and put the new block after the one that we use.
1084- umf_result = split_current_block (coarse , curr , size );
1085- if (umf_result != UMF_RESULT_SUCCESS ) {
1086- (void )free_blocks_re_add (coarse , curr );
1087- goto err_unlock ;
1088- }
1088+ size_t size_aligned = ALIGN_UP_SAFE (size , alignment );
1089+ if (size_aligned == 0 ) {
1090+ // cannot align up (arithmetic overflow)
1091+ size_aligned = size ;
1092+ }
10891093
1090- curr -> size = size ;
1094+ umf_result = coarse -> cb .alloc (coarse -> provider , size_aligned , alignment ,
1095+ resultPtr );
1096+ if (umf_result != UMF_RESULT_SUCCESS ) {
1097+ LOG_ERR ("coarse_alloc_cb() failed: out of memory" );
1098+ goto err_unlock ;
1099+ }
10911100
1092- LOG_DEBUG ("coarse_ALLOC (split_block) %zu used %zu alloc %zu" , size ,
1093- coarse -> used_size , coarse -> alloc_size );
1101+ ASSERT_IS_ALIGNED (((uintptr_t )(* resultPtr )), alignment );
10941102
1095- } else { // action == ACTION_USE
1096- LOG_DEBUG ("coarse_ALLOC (same_block) %zu used %zu alloc %zu" , size ,
1097- coarse -> used_size , coarse -> alloc_size );
1103+ block_t * new_free_block = NULL ;
1104+ umf_result = coarse_add_free_block (coarse , * resultPtr , size_aligned ,
1105+ & new_free_block );
1106+ if (umf_result != UMF_RESULT_SUCCESS ) {
1107+ if (coarse -> cb .free ) {
1108+ coarse -> cb .free (coarse -> provider , * resultPtr , size_aligned );
1109+ }
1110+ goto err_unlock ;
10981111 }
10991112
1100- curr -> used = true;
1101- * resultPtr = curr -> data ;
1102- coarse -> used_size += size ;
1103-
1104- assert (debug_check (coarse ));
1105- utils_mutex_unlock (& coarse -> lock );
1113+ LOG_DEBUG ("coarse_ALLOC (memory_provider) %zu used %zu alloc %zu" ,
1114+ size_aligned , coarse -> used_size , coarse -> alloc_size );
11061115
1107- return UMF_RESULT_SUCCESS ;
1116+ curr = new_free_block ;
11081117 }
11091118
1110- // no suitable block found - try to get more memory from the upstream provider
1111- umf_result = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
1112-
1113- * resultPtr = NULL ;
1119+ // If the block that we want to reuse has a greater size, split it.
1120+ // Try to merge the split part with the successor if it is not used.
1121+ enum { ACTION_NONE = 0 , ACTION_USE , ACTION_SPLIT } action = ACTION_NONE ;
11141122
1115- if (!coarse -> cb .alloc ) {
1123+ if (curr && curr -> size > size ) {
1124+ action = ACTION_SPLIT ;
1125+ } else if (curr && curr -> size == size ) {
1126+ action = ACTION_USE ;
1127+ } else {
1128+ umf_result = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
11161129 LOG_ERR ("out of memory" );
11171130 goto err_unlock ;
11181131 }
11191132
1120- umf_result = coarse -> cb .alloc (coarse -> provider , size , alignment , resultPtr );
1121- if (umf_result != UMF_RESULT_SUCCESS ) {
1122- LOG_ERR ("coarse_alloc_cb() failed: out of memory" );
1123- goto err_unlock ;
1124- }
1133+ // ACTION_SPLIT or ACTION_USE
1134+ assert (curr -> used == false);
11251135
1126- ASSERT_IS_ALIGNED (((uintptr_t )(* resultPtr )), alignment );
1136+ // In case of non-zero alignment create an aligned block what would be further used.
1137+ if (alignment > 0 ) {
1138+ umf_result = create_aligned_block (coarse , size , alignment , & curr );
1139+ if (umf_result != UMF_RESULT_SUCCESS ) {
1140+ (void )free_blocks_re_add (coarse , curr );
1141+ goto err_unlock ;
1142+ }
1143+ }
11271144
1128- umf_result = coarse_add_used_block (coarse , * resultPtr , size );
1129- if (umf_result != UMF_RESULT_SUCCESS ) {
1130- if (coarse -> cb .free ) {
1131- coarse -> cb .free (coarse -> provider , * resultPtr , size );
1145+ if (action == ACTION_SPLIT ) {
1146+ // Split the current block and put the new block after the one that we use.
1147+ umf_result = split_current_block (coarse , curr , size );
1148+ if (umf_result != UMF_RESULT_SUCCESS ) {
1149+ (void )free_blocks_re_add (coarse , curr );
1150+ goto err_unlock ;
11321151 }
1133- goto err_unlock ;
1152+
1153+ curr -> size = size ;
1154+
1155+ LOG_DEBUG ("coarse_ALLOC (split_block) %zu used %zu alloc %zu" , size ,
1156+ coarse -> used_size , coarse -> alloc_size );
1157+
1158+ } else { // action == ACTION_USE
1159+ LOG_DEBUG ("coarse_ALLOC (same_block) %zu used %zu alloc %zu" , size ,
1160+ coarse -> used_size , coarse -> alloc_size );
11341161 }
11351162
1136- LOG_DEBUG ("coarse_ALLOC (memory_provider) %zu used %zu alloc %zu" , size ,
1137- coarse -> used_size , coarse -> alloc_size );
1163+ curr -> used = true;
1164+ * resultPtr = curr -> data ;
1165+ coarse -> used_size += size ;
11381166
11391167 umf_result = UMF_RESULT_SUCCESS ;
11401168
0 commit comments