@@ -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,108 @@ 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 );
1059-
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- }
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 ;
1082+
1083+ if (!coarse -> cb .alloc ) {
1084+ LOG_ERR ("out of memory (the memory provider does not support "
1085+ "allocating more memory)" );
1086+ goto err_unlock ;
10801087 }
10811088
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- }
1089+ size_t size_aligned = ALIGN_UP_SAFE ( size , alignment );
1090+ if ( size_aligned == 0 ) {
1091+ // cannot align up (arithmetic overflow)
1092+ umf_result = UMF_RESULT_ERROR_INVALID_ARGUMENT ;
1093+ LOG_ERR ( "size too huge (arithmetic overflow)" );
1094+ goto err_unlock ;
1095+ }
10891096
1090- curr -> size = size ;
1097+ umf_result = coarse -> cb .alloc (coarse -> provider , size_aligned , alignment ,
1098+ resultPtr );
1099+ if (umf_result != UMF_RESULT_SUCCESS ) {
1100+ LOG_ERR ("alloc() of memory provider failed: out of memory" );
1101+ goto err_unlock ;
1102+ }
10911103
1092- LOG_DEBUG ("coarse_ALLOC (split_block) %zu used %zu alloc %zu" , size ,
1093- coarse -> used_size , coarse -> alloc_size );
1104+ ASSERT_IS_ALIGNED (((uintptr_t )(* resultPtr )), alignment );
10941105
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 );
1106+ block_t * new_free_block = NULL ;
1107+ umf_result = coarse_add_free_block (coarse , * resultPtr , size_aligned ,
1108+ & new_free_block );
1109+ if (umf_result != UMF_RESULT_SUCCESS ) {
1110+ LOG_ERR ("failed to add a newly allocated block from the memory "
1111+ "provider" );
1112+ if (coarse -> cb .free ) {
1113+ coarse -> cb .free (coarse -> provider , * resultPtr , size_aligned );
1114+ } else {
1115+ LOG_WARN ("the memory provider does not support the free() "
1116+ "operation, so the following memory block was leaked: "
1117+ "address %p, size %zu" ,
1118+ * resultPtr , size_aligned );
1119+ }
1120+ goto err_unlock ;
10981121 }
10991122
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 );
1123+ LOG_DEBUG ("coarse_ALLOC (memory_provider) %zu used %zu alloc %zu" ,
1124+ size_aligned , coarse -> used_size , coarse -> alloc_size );
11061125
1107- return UMF_RESULT_SUCCESS ;
1126+ curr = new_free_block ;
11081127 }
11091128
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 ;
1129+ // If the block that we want to reuse has a greater size, split it.
1130+ // Try to merge the split part with the successor if it is not used.
1131+ enum { ACTION_NONE = 0 , ACTION_USE , ACTION_SPLIT } action = ACTION_NONE ;
11141132
1115- if (!coarse -> cb .alloc ) {
1133+ if (curr && curr -> size > size ) {
1134+ action = ACTION_SPLIT ;
1135+ } else if (curr && curr -> size == size ) {
1136+ action = ACTION_USE ;
1137+ } else {
1138+ umf_result = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
11161139 LOG_ERR ("out of memory" );
11171140 goto err_unlock ;
11181141 }
11191142
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- }
1143+ // ACTION_SPLIT or ACTION_USE
1144+ assert (curr -> used == false);
11251145
1126- ASSERT_IS_ALIGNED (((uintptr_t )(* resultPtr )), alignment );
1146+ // In case of non-zero alignment create an aligned block what would be further used.
1147+ if (alignment > 0 ) {
1148+ umf_result = create_aligned_block (coarse , size , alignment , & curr );
1149+ if (umf_result != UMF_RESULT_SUCCESS ) {
1150+ (void )free_blocks_re_add (coarse , curr );
1151+ goto err_unlock ;
1152+ }
1153+ }
11271154
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 );
1155+ if (action == ACTION_SPLIT ) {
1156+ // Split the current block and put the new block after the one that we use.
1157+ umf_result = split_current_block (coarse , curr , size );
1158+ if (umf_result != UMF_RESULT_SUCCESS ) {
1159+ (void )free_blocks_re_add (coarse , curr );
1160+ goto err_unlock ;
11321161 }
1133- goto err_unlock ;
1162+
1163+ curr -> size = size ;
1164+
1165+ LOG_DEBUG ("coarse_ALLOC (split_block) %zu used %zu alloc %zu" , size ,
1166+ coarse -> used_size , coarse -> alloc_size );
1167+
1168+ } else { // action == ACTION_USE
1169+ LOG_DEBUG ("coarse_ALLOC (same_block) %zu used %zu alloc %zu" , size ,
1170+ coarse -> used_size , coarse -> alloc_size );
11341171 }
11351172
1136- LOG_DEBUG ("coarse_ALLOC (memory_provider) %zu used %zu alloc %zu" , size ,
1137- coarse -> used_size , coarse -> alloc_size );
1173+ curr -> used = true;
1174+ * resultPtr = curr -> data ;
1175+ coarse -> used_size += size ;
11381176
11391177 umf_result = UMF_RESULT_SUCCESS ;
11401178
0 commit comments