Skip to content

Commit a3d2595

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

File tree

2 files changed

+301
-2
lines changed

2 files changed

+301
-2
lines changed

src/provider/provider_coarse.c

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

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