Skip to content

Commit a6db939

Browse files
committed
Implement split()/merge() API of the Coarse provider
Signed-off-by: Lukasz Dorau <[email protected]>
1 parent ade200a commit a6db939

File tree

2 files changed

+267
-2
lines changed

2 files changed

+267
-2
lines changed

src/provider/provider_coarse.c

Lines changed: 175 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,6 +1517,179 @@ coarse_memory_provider_get_stats(void *provider,
15171517
return UMF_RESULT_SUCCESS;
15181518
}
15191519

1520+
static umf_result_t coarse_memory_provider_allocation_split(void *provider,
1521+
void *ptr,
1522+
size_t totalSize,
1523+
size_t firstSize) {
1524+
if (provider == NULL || ptr == NULL || (firstSize >= totalSize) ||
1525+
firstSize == 0) {
1526+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
1527+
}
1528+
1529+
umf_result_t umf_result;
1530+
1531+
coarse_memory_provider_t *coarse_provider =
1532+
(struct coarse_memory_provider_t *)provider;
1533+
1534+
if (utils_mutex_lock(&coarse_provider->lock) != 0) {
1535+
LOG_ERR("lockng the lock failed");
1536+
return UMF_RESULT_ERROR_UNKNOWN;
1537+
}
1538+
1539+
assert(debug_check(coarse_provider));
1540+
1541+
ravl_node_t *node = coarse_ravl_find_node(coarse_provider->all_blocks, ptr);
1542+
if (node == NULL) {
1543+
LOG_ERR("memory block not found");
1544+
umf_result = UMF_RESULT_ERROR_INVALID_ARGUMENT;
1545+
goto err_mutex_unlock;
1546+
}
1547+
1548+
block_t *block = get_node_block(node);
1549+
1550+
if (block->size != totalSize) {
1551+
LOG_ERR("wrong totalSize");
1552+
umf_result = UMF_RESULT_ERROR_INVALID_ARGUMENT;
1553+
goto err_mutex_unlock;
1554+
}
1555+
1556+
if (!block->used) {
1557+
LOG_ERR("block is not allocated");
1558+
umf_result = UMF_RESULT_ERROR_INVALID_ARGUMENT;
1559+
goto err_mutex_unlock;
1560+
}
1561+
1562+
block_t *new_block = coarse_ravl_add_new(coarse_provider->all_blocks,
1563+
block->data + firstSize,
1564+
block->size - firstSize, NULL);
1565+
if (new_block == NULL) {
1566+
umf_result = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
1567+
goto err_mutex_unlock;
1568+
}
1569+
1570+
block->size = firstSize;
1571+
new_block->used = true;
1572+
1573+
assert(new_block->size == (totalSize - firstSize));
1574+
1575+
umf_result = UMF_RESULT_SUCCESS;
1576+
1577+
err_mutex_unlock:
1578+
assert(debug_check(coarse_provider));
1579+
1580+
if (utils_mutex_unlock(&coarse_provider->lock) != 0) {
1581+
LOG_ERR("unlockng the lock failed");
1582+
if (umf_result == UMF_RESULT_SUCCESS) {
1583+
umf_result = UMF_RESULT_ERROR_UNKNOWN;
1584+
}
1585+
}
1586+
1587+
return umf_result;
1588+
}
1589+
1590+
static umf_result_t coarse_memory_provider_allocation_merge(void *provider,
1591+
void *lowPtr,
1592+
void *highPtr,
1593+
size_t totalSize) {
1594+
if (provider == NULL || lowPtr == NULL || highPtr == NULL ||
1595+
((uintptr_t)highPtr <= (uintptr_t)lowPtr) ||
1596+
((uintptr_t)highPtr - (uintptr_t)lowPtr >= totalSize)) {
1597+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
1598+
}
1599+
1600+
umf_result_t umf_result;
1601+
1602+
coarse_memory_provider_t *coarse_provider =
1603+
(struct coarse_memory_provider_t *)provider;
1604+
1605+
if (utils_mutex_lock(&coarse_provider->lock) != 0) {
1606+
LOG_ERR("lockng the lock failed");
1607+
return UMF_RESULT_ERROR_UNKNOWN;
1608+
}
1609+
1610+
assert(debug_check(coarse_provider));
1611+
1612+
ravl_node_t *low_node =
1613+
coarse_ravl_find_node(coarse_provider->all_blocks, lowPtr);
1614+
if (low_node == NULL) {
1615+
LOG_ERR("the lowPtr memory block not found");
1616+
umf_result = UMF_RESULT_ERROR_INVALID_ARGUMENT;
1617+
goto err_mutex_unlock;
1618+
}
1619+
1620+
block_t *low_block = get_node_block(low_node);
1621+
if (!low_block->used) {
1622+
LOG_ERR("the lowPtr block is not allocated");
1623+
umf_result = UMF_RESULT_ERROR_INVALID_ARGUMENT;
1624+
goto err_mutex_unlock;
1625+
}
1626+
1627+
ravl_node_t *high_node =
1628+
coarse_ravl_find_node(coarse_provider->all_blocks, highPtr);
1629+
if (high_node == NULL) {
1630+
LOG_ERR("the highPtr memory block not found");
1631+
umf_result = UMF_RESULT_ERROR_INVALID_ARGUMENT;
1632+
goto err_mutex_unlock;
1633+
}
1634+
1635+
block_t *high_block = get_node_block(high_node);
1636+
if (!high_block->used) {
1637+
LOG_ERR("the highPtr block is not allocated");
1638+
umf_result = UMF_RESULT_ERROR_INVALID_ARGUMENT;
1639+
goto err_mutex_unlock;
1640+
}
1641+
1642+
if (get_node_next(low_node) != high_node) {
1643+
LOG_ERR("given pointers cannot be merged");
1644+
umf_result = UMF_RESULT_ERROR_INVALID_ARGUMENT;
1645+
goto err_mutex_unlock;
1646+
}
1647+
1648+
if (get_node_prev(high_node) != low_node) {
1649+
LOG_ERR("given pointers cannot be merged");
1650+
umf_result = UMF_RESULT_ERROR_INVALID_ARGUMENT;
1651+
goto err_mutex_unlock;
1652+
}
1653+
1654+
if (low_block->size + high_block->size != totalSize) {
1655+
LOG_ERR("wrong totalSize");
1656+
umf_result = UMF_RESULT_ERROR_INVALID_ARGUMENT;
1657+
goto err_mutex_unlock;
1658+
}
1659+
1660+
if ((uintptr_t)highPtr != ((uintptr_t)lowPtr + low_block->size)) {
1661+
LOG_ERR("given pointers cannot be merged");
1662+
umf_result = UMF_RESULT_ERROR_INVALID_ARGUMENT;
1663+
goto err_mutex_unlock;
1664+
}
1665+
1666+
ravl_node_t *merged_node = NULL;
1667+
1668+
umf_result = user_block_merge(coarse_provider, low_node, high_node, true,
1669+
&merged_node);
1670+
if (umf_result != UMF_RESULT_SUCCESS) {
1671+
LOG_ERR("merging failed");
1672+
goto err_mutex_unlock;
1673+
}
1674+
1675+
assert(merged_node == low_node);
1676+
assert(low_block->size == totalSize);
1677+
1678+
assert(debug_check(coarse_provider));
1679+
1680+
if (utils_mutex_unlock(&coarse_provider->lock) != 0) {
1681+
LOG_ERR("unlockng the lock failed");
1682+
return UMF_RESULT_ERROR_UNKNOWN;
1683+
}
1684+
1685+
return UMF_RESULT_SUCCESS;
1686+
1687+
err_mutex_unlock:
1688+
assert(debug_check(coarse_provider));
1689+
utils_mutex_unlock(&coarse_provider->lock);
1690+
return umf_result;
1691+
}
1692+
15201693
umf_memory_provider_ops_t UMF_COARSE_MEMORY_PROVIDER_OPS = {
15211694
.version = UMF_VERSION_CURRENT,
15221695
.initialize = coarse_memory_provider_initialize,
@@ -1528,12 +1701,12 @@ umf_memory_provider_ops_t UMF_COARSE_MEMORY_PROVIDER_OPS = {
15281701
.get_min_page_size = coarse_memory_provider_get_min_page_size,
15291702
.get_name = coarse_memory_provider_get_name,
15301703
.ext.free = coarse_memory_provider_free,
1704+
.ext.allocation_merge = coarse_memory_provider_allocation_merge,
1705+
.ext.allocation_split = coarse_memory_provider_allocation_split,
15311706
// TODO
15321707
/*
15331708
.ext.purge_lazy = coarse_memory_provider_purge_lazy,
15341709
.ext.purge_force = coarse_memory_provider_purge_force,
1535-
.ext.allocation_merge = coarse_memory_provider_allocation_merge,
1536-
.ext.allocation_split = coarse_memory_provider_allocation_split,
15371710
.ipc.get_ipc_handle_size = coarse_memory_provider_get_ipc_handle_size,
15381711
.ipc.get_ipc_handle = coarse_memory_provider_get_ipc_handle,
15391712
.ipc.put_ipc_handle = coarse_memory_provider_put_ipc_handle,

test/disjointCoarseMallocPool.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,3 +759,95 @@ TEST_P(CoarseWithMemoryStrategyTest, disjointCoarseMallocPool_wrong_params_4) {
759759

760760
umfMemoryProviderDestroy(malloc_memory_provider);
761761
}
762+
763+
TEST_P(CoarseWithMemoryStrategyTest, disjointCoarseMallocPool_split_merge) {
764+
umf_memory_provider_handle_t malloc_memory_provider;
765+
umf_result_t umf_result;
766+
767+
umf_result = umfMemoryProviderCreate(&UMF_MALLOC_MEMORY_PROVIDER_OPS, NULL,
768+
&malloc_memory_provider);
769+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
770+
ASSERT_NE(malloc_memory_provider, nullptr);
771+
772+
const size_t init_buffer_size = 20 * MB;
773+
774+
coarse_memory_provider_params_t coarse_memory_provider_params;
775+
// make sure there are no undefined members - prevent a UB
776+
memset(&coarse_memory_provider_params, 0,
777+
sizeof(coarse_memory_provider_params));
778+
coarse_memory_provider_params.upstream_memory_provider =
779+
malloc_memory_provider;
780+
coarse_memory_provider_params.immediate_init_from_upstream = true;
781+
coarse_memory_provider_params.init_buffer = NULL;
782+
coarse_memory_provider_params.init_buffer_size = init_buffer_size;
783+
784+
umf_memory_provider_handle_t coarse_memory_provider;
785+
umf_result = umfMemoryProviderCreate(umfCoarseMemoryProviderOps(),
786+
&coarse_memory_provider_params,
787+
&coarse_memory_provider);
788+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
789+
ASSERT_NE(coarse_memory_provider, nullptr);
790+
791+
umf_memory_provider_handle_t cp = coarse_memory_provider;
792+
char *ptr = nullptr;
793+
794+
ASSERT_EQ(GetStats(cp).used_size, 0 * MB);
795+
ASSERT_EQ(GetStats(cp).alloc_size, init_buffer_size);
796+
ASSERT_EQ(GetStats(cp).num_all_blocks, 1);
797+
798+
/* test umfMemoryProviderAllocationSplit */
799+
umf_result = umfMemoryProviderAlloc(cp, 2 * MB, 0, (void **)&ptr);
800+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
801+
ASSERT_NE(ptr, nullptr);
802+
ASSERT_EQ(GetStats(cp).used_size, 2 * MB);
803+
ASSERT_EQ(GetStats(cp).alloc_size, init_buffer_size);
804+
ASSERT_EQ(GetStats(cp).num_all_blocks, 2);
805+
806+
umf_result = umfMemoryProviderAllocationSplit(cp, ptr, 2 * MB, 1 * MB);
807+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
808+
ASSERT_EQ(GetStats(cp).used_size, 2 * MB);
809+
ASSERT_EQ(GetStats(cp).alloc_size, init_buffer_size);
810+
ASSERT_EQ(GetStats(cp).num_all_blocks, 3);
811+
812+
umf_result = umfMemoryProviderFree(cp, (ptr + 1 * MB), 1 * MB);
813+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
814+
ASSERT_EQ(GetStats(cp).used_size, 1 * MB);
815+
ASSERT_EQ(GetStats(cp).alloc_size, init_buffer_size);
816+
ASSERT_EQ(GetStats(cp).num_all_blocks, 2);
817+
818+
umf_result = umfMemoryProviderFree(cp, ptr, 1 * MB);
819+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
820+
ASSERT_EQ(GetStats(cp).used_size, 0);
821+
ASSERT_EQ(GetStats(cp).alloc_size, init_buffer_size);
822+
ASSERT_EQ(GetStats(cp).num_all_blocks, 1);
823+
824+
/* test umfMemoryProviderAllocationMerge */
825+
umf_result = umfMemoryProviderAlloc(cp, 2 * MB, 0, (void **)&ptr);
826+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
827+
ASSERT_NE(ptr, nullptr);
828+
ASSERT_EQ(GetStats(cp).used_size, 2 * MB);
829+
ASSERT_EQ(GetStats(cp).alloc_size, init_buffer_size);
830+
ASSERT_EQ(GetStats(cp).num_all_blocks, 2);
831+
832+
umf_result = umfMemoryProviderAllocationSplit(cp, ptr, 2 * MB, 1 * MB);
833+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
834+
ASSERT_EQ(GetStats(cp).used_size, 2 * MB);
835+
ASSERT_EQ(GetStats(cp).alloc_size, init_buffer_size);
836+
ASSERT_EQ(GetStats(cp).num_all_blocks, 3);
837+
838+
umf_result =
839+
umfMemoryProviderAllocationMerge(cp, ptr, (ptr + 1 * MB), 2 * MB);
840+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
841+
ASSERT_EQ(GetStats(cp).used_size, 2 * MB);
842+
ASSERT_EQ(GetStats(cp).alloc_size, init_buffer_size);
843+
ASSERT_EQ(GetStats(cp).num_all_blocks, 2);
844+
845+
umf_result = umfMemoryProviderFree(cp, ptr, 2 * MB);
846+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
847+
ASSERT_EQ(GetStats(cp).used_size, 0);
848+
ASSERT_EQ(GetStats(cp).alloc_size, init_buffer_size);
849+
ASSERT_EQ(GetStats(cp).num_all_blocks, 1);
850+
851+
umfMemoryProviderDestroy(coarse_memory_provider);
852+
umfMemoryProviderDestroy(malloc_memory_provider);
853+
}

0 commit comments

Comments
 (0)