@@ -623,6 +623,24 @@ static umf_result_t coarse_add_used_block(coarse_t *coarse, void *addr,
623
623
return UMF_RESULT_SUCCESS ;
624
624
}
625
625
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
+
626
644
static void coarse_ravl_cb_rm_all_blocks_node (void * data , void * arg ) {
627
645
assert (data );
628
646
assert (arg );
@@ -1053,88 +1071,98 @@ umf_result_t coarse_alloc(coarse_t *coarse, size_t size, size_t alignment,
1053
1071
1054
1072
assert (debug_check (coarse ));
1055
1073
1074
+ * resultPtr = NULL ;
1075
+
1056
1076
// Find a block with greater or equal size using the given memory allocation strategy
1057
1077
block_t * curr = find_free_block (coarse -> free_blocks , size , alignment ,
1058
1078
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 ;
1059
1082
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 ;
1080
1086
}
1081
1087
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
+ }
1089
1093
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
+ }
1091
1100
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 );
1094
1102
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 ;
1098
1111
}
1099
1112
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 );
1106
1115
1107
- return UMF_RESULT_SUCCESS ;
1116
+ curr = new_free_block ;
1108
1117
}
1109
1118
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 ;
1114
1122
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 ;
1116
1129
LOG_ERR ("out of memory" );
1117
1130
goto err_unlock ;
1118
1131
}
1119
1132
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);
1125
1135
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
+ }
1127
1144
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 ;
1132
1151
}
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 );
1134
1161
}
1135
1162
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 ;
1138
1166
1139
1167
umf_result = UMF_RESULT_SUCCESS ;
1140
1168
0 commit comments