Skip to content

Commit 81adf59

Browse files
authored
Merge pull request #1249 from ldorau/Refactor_coarse_alloc
Improve `coarse_alloc()`
2 parents 2b30804 + 3a8cbaa commit 81adf59

File tree

1 file changed

+97
-59
lines changed

1 file changed

+97
-59
lines changed

src/coarse/coarse.c

+97-59
Original file line numberDiff line numberDiff line change
@@ -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+
626644
static 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

Comments
 (0)