diff --git a/benchmark/multithread.cpp b/benchmark/multithread.cpp index c698ed0452..efb46729c3 100644 --- a/benchmark/multithread.cpp +++ b/benchmark/multithread.cpp @@ -91,7 +91,12 @@ static void mt_alloc_free(poolCreateExtParams params, } int main() { - auto osParams = umfOsMemoryProviderParamsDefault(); + umf_os_memory_provider_params_handle_t osParams = nullptr; + umf_result_t res = umfOsMemoryProviderParamsCreate(&osParams); + if (res != UMF_RESULT_SUCCESS) { + std::cerr << "os memory provider params create failed" << std::endl; + return -1; + } #if defined(UMF_POOL_SCALABLE_ENABLED) @@ -102,7 +107,7 @@ int main() { std::cout << "scalable_pool mt_alloc_free: "; mt_alloc_free(poolCreateExtParams{umfScalablePoolOps(), nullptr, - umfOsMemoryProviderOps(), &osParams}, + umfOsMemoryProviderOps(), osParams}, params); #else std::cout << "skipping scalable_pool mt_alloc_free" << std::endl; @@ -111,7 +116,7 @@ int main() { #if defined(UMF_BUILD_LIBUMF_POOL_JEMALLOC) std::cout << "jemalloc_pool mt_alloc_free: "; mt_alloc_free(poolCreateExtParams{umfJemallocPoolOps(), nullptr, - umfOsMemoryProviderOps(), &osParams}); + umfOsMemoryProviderOps(), osParams}); #else std::cout << "skipping jemalloc_pool mt_alloc_free" << std::endl; #endif @@ -126,7 +131,7 @@ int main() { std::cout << "disjoint_pool mt_alloc_free: "; mt_alloc_free(poolCreateExtParams{umfDisjointPoolOps(), hDisjointParams, - umfOsMemoryProviderOps(), &osParams}); + umfOsMemoryProviderOps(), osParams}); #else std::cout << "skipping disjoint_pool mt_alloc_free" << std::endl; #endif diff --git a/benchmark/ubench.c b/benchmark/ubench.c index 645ddb743e..1deabde0c6 100644 --- a/benchmark/ubench.c +++ b/benchmark/ubench.c @@ -124,22 +124,6 @@ UBENCH_EX(simple, glibc_malloc) { ////////////////// OS MEMORY PROVIDER -static umf_os_memory_provider_params_t UMF_OS_MEMORY_PROVIDER_PARAMS = { - /* .protection = */ UMF_PROTECTION_READ | UMF_PROTECTION_WRITE, - /* .visibility = */ UMF_MEM_MAP_PRIVATE, - /* .shm_name = */ NULL, - - // NUMA config - /* .numa_list = */ NULL, - /* .numa_list_len = */ 0, - - /* .numa_mode = */ UMF_NUMA_MODE_DEFAULT, - /* .part_size = */ 0, - - /* .partitions = */ NULL, - /* .partitions_len = */ 0, -}; - static void *w_umfMemoryProviderAlloc(void *provider, size_t size, size_t alignment) { void *ptr = NULL; @@ -171,9 +155,17 @@ UBENCH_EX(simple, os_memory_provider) { umf_result_t umf_result; umf_memory_provider_handle_t os_memory_provider = NULL; - umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), - &UMF_OS_MEMORY_PROVIDER_PARAMS, + umf_os_memory_provider_params_handle_t os_params = NULL; + + umf_result = umfOsMemoryProviderParamsCreate(&os_params); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf(stderr, "error: umfOsMemoryProviderParamsCreate() failed\n"); + exit(-1); + } + + umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), os_params, &os_memory_provider); + umfOsMemoryProviderParamsDestroy(os_params); if (umf_result != UMF_RESULT_SUCCESS) { fprintf(stderr, "error: umfMemoryProviderCreate() failed\n"); exit(-1); @@ -215,9 +207,17 @@ UBENCH_EX(simple, proxy_pool_with_os_memory_provider) { umf_result_t umf_result; umf_memory_provider_handle_t os_memory_provider = NULL; - umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), - &UMF_OS_MEMORY_PROVIDER_PARAMS, + umf_os_memory_provider_params_handle_t os_params = NULL; + + umf_result = umfOsMemoryProviderParamsCreate(&os_params); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf(stderr, "error: umfOsMemoryProviderParamsCreate() failed\n"); + exit(-1); + } + + umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), os_params, &os_memory_provider); + umfOsMemoryProviderParamsDestroy(os_params); if (umf_result != UMF_RESULT_SUCCESS) { fprintf(stderr, "error: umfMemoryProviderCreate() failed\n"); exit(-1); @@ -252,9 +252,17 @@ UBENCH_EX(simple, disjoint_pool_with_os_memory_provider) { umf_result_t umf_result; umf_memory_provider_handle_t os_memory_provider = NULL; - umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), - &UMF_OS_MEMORY_PROVIDER_PARAMS, + umf_os_memory_provider_params_handle_t os_params = NULL; + + umf_result = umfOsMemoryProviderParamsCreate(&os_params); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf(stderr, "error: umfOsMemoryProviderParamsCreate() failed\n"); + exit(-1); + } + + umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), os_params, &os_memory_provider); + umfOsMemoryProviderParamsDestroy(os_params); if (umf_result != UMF_RESULT_SUCCESS) { fprintf(stderr, "error: umfMemoryProviderCreate() failed\n"); exit(-1); @@ -329,9 +337,17 @@ UBENCH_EX(simple, jemalloc_pool_with_os_memory_provider) { umf_result_t umf_result; umf_memory_provider_handle_t os_memory_provider = NULL; - umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), - &UMF_OS_MEMORY_PROVIDER_PARAMS, + umf_os_memory_provider_params_handle_t os_params = NULL; + + umf_result = umfOsMemoryProviderParamsCreate(&os_params); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf(stderr, "error: umfOsMemoryProviderParamsCreate() failed\n"); + exit(-1); + } + + umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), os_params, &os_memory_provider); + umfOsMemoryProviderParamsDestroy(os_params); if (umf_result != UMF_RESULT_SUCCESS) { fprintf(stderr, "error: umfMemoryProviderCreate() failed\n"); exit(-1); @@ -367,9 +383,17 @@ UBENCH_EX(simple, scalable_pool_with_os_memory_provider) { umf_result_t umf_result; umf_memory_provider_handle_t os_memory_provider = NULL; - umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), - &UMF_OS_MEMORY_PROVIDER_PARAMS, + umf_os_memory_provider_params_handle_t os_params = NULL; + + umf_result = umfOsMemoryProviderParamsCreate(&os_params); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf(stderr, "error: umfOsMemoryProviderParamsCreate() failed\n"); + exit(-1); + } + + umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), os_params, &os_memory_provider); + umfOsMemoryProviderParamsDestroy(os_params); if (umf_result != UMF_RESULT_SUCCESS) { fprintf(stderr, "error: umfMemoryProviderCreate() failed\n"); exit(-1); diff --git a/examples/basic/basic.c b/examples/basic/basic.c index d886c4af8f..846e71edaa 100644 --- a/examples/basic/basic.c +++ b/examples/basic/basic.c @@ -23,10 +23,17 @@ int main(void) { // in an mmap call like this: // mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0) umf_memory_provider_ops_t *provider_ops = umfOsMemoryProviderOps(); - umf_os_memory_provider_params_t params = umfOsMemoryProviderParamsDefault(); + umf_os_memory_provider_params_handle_t params = NULL; umf_memory_provider_handle_t provider; - res = umfMemoryProviderCreate(provider_ops, ¶ms, &provider); + res = umfOsMemoryProviderParamsCreate(¶ms); + if (res != UMF_RESULT_SUCCESS) { + printf("Failed to create OS memory provider params!\n"); + return -1; + } + + res = umfMemoryProviderCreate(provider_ops, params, &provider); + umfOsMemoryProviderParamsDestroy(params); if (res != UMF_RESULT_SUCCESS) { printf("Failed to create a memory provider!\n"); return -1; diff --git a/examples/dram_and_fsdax/dram_and_fsdax.c b/examples/dram_and_fsdax/dram_and_fsdax.c index ef11c186e3..26f4517281 100644 --- a/examples/dram_and_fsdax/dram_and_fsdax.c +++ b/examples/dram_and_fsdax/dram_and_fsdax.c @@ -21,11 +21,16 @@ static umf_memory_pool_handle_t create_dram_pool(void) { umf_memory_pool_handle_t pool_dram; umf_result_t umf_result; - umf_os_memory_provider_params_t params_dram = - umfOsMemoryProviderParamsDefault(); + umf_os_memory_provider_params_handle_t params_dram = NULL; + umf_result = umfOsMemoryProviderParamsCreate(¶ms_dram); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf(stderr, "Failed to create OS memory provider params!\n"); + return NULL; + } - umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), ¶ms_dram, + umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), params_dram, &provider_dram); + umfOsMemoryProviderParamsDestroy(params_dram); if (umf_result != UMF_RESULT_SUCCESS) { fprintf(stderr, "Creation of the OS memory provider failed"); return NULL; diff --git a/examples/ipc_ipcapi/ipc_ipcapi_consumer.c b/examples/ipc_ipcapi/ipc_ipcapi_consumer.c index 05596bd161..1739e005a8 100644 --- a/examples/ipc_ipcapi/ipc_ipcapi_consumer.c +++ b/examples/ipc_ipcapi/ipc_ipcapi_consumer.c @@ -99,17 +99,33 @@ int main(int argc, char *argv[]) { int port = atoi(argv[1]); umf_memory_provider_handle_t OS_memory_provider = NULL; - umf_os_memory_provider_params_t os_params; + umf_os_memory_provider_params_handle_t os_params = NULL; enum umf_result_t umf_result; - os_params = umfOsMemoryProviderParamsDefault(); - os_params.visibility = UMF_MEM_MAP_SHARED; + umf_result = umfOsMemoryProviderParamsCreate(&os_params); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf( + stderr, + "[consumer] ERROR: creating OS memory provider params failed\n"); + return -1; + } + umf_result = + umfOsMemoryProviderParamsSetVisibility(os_params, UMF_MEM_MAP_SHARED); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf(stderr, "[consumer] ERROR: setting visibility mode failed\n"); + goto err_destroy_OS_params; + } if (argc >= 3) { - os_params.shm_name = argv[2]; + umf_result = umfOsMemoryProviderParamsSetShmName(os_params, argv[2]); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf(stderr, + "[consumer] ERROR: setting shared memory name failed\n"); + goto err_destroy_OS_params; + } } // create OS memory provider - umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), &os_params, + umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), os_params, &OS_memory_provider); if (umf_result != UMF_RESULT_SUCCESS) { fprintf(stderr, @@ -267,6 +283,9 @@ int main(int argc, char *argv[]) { err_destroy_OS_memory_provider: umfMemoryProviderDestroy(OS_memory_provider); +err_destroy_OS_params: + umfOsMemoryProviderParamsDestroy(os_params); + if (ret == 0) { fprintf(stderr, "[consumer] Shutting down (status OK) ...\n"); } else if (ret == 1) { diff --git a/examples/ipc_ipcapi/ipc_ipcapi_producer.c b/examples/ipc_ipcapi/ipc_ipcapi_producer.c index fcb73650f2..4157e8284f 100644 --- a/examples/ipc_ipcapi/ipc_ipcapi_producer.c +++ b/examples/ipc_ipcapi/ipc_ipcapi_producer.c @@ -70,17 +70,33 @@ int main(int argc, char *argv[]) { int port = atoi(argv[1]); umf_memory_provider_handle_t OS_memory_provider = NULL; - umf_os_memory_provider_params_t os_params; + umf_os_memory_provider_params_handle_t os_params = NULL; enum umf_result_t umf_result; - os_params = umfOsMemoryProviderParamsDefault(); - os_params.visibility = UMF_MEM_MAP_SHARED; + umf_result = umfOsMemoryProviderParamsCreate(&os_params); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf( + stderr, + "[producer] ERROR: creating OS memory provider params failed\n"); + return -1; + } + umf_result = + umfOsMemoryProviderParamsSetVisibility(os_params, UMF_MEM_MAP_SHARED); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf(stderr, "[producer] ERROR: setting visibility mode failed\n"); + goto err_destroy_OS_params; + } if (argc >= 3) { - os_params.shm_name = argv[2]; + umf_result = umfOsMemoryProviderParamsSetShmName(os_params, argv[2]); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf(stderr, + "[producer] ERROR: setting shared memory name failed\n"); + goto err_destroy_OS_params; + } } // create OS memory provider - umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), &os_params, + umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), os_params, &OS_memory_provider); if (umf_result != UMF_RESULT_SUCCESS) { fprintf(stderr, @@ -240,6 +256,9 @@ int main(int argc, char *argv[]) { err_destroy_OS_memory_provider: umfMemoryProviderDestroy(OS_memory_provider); +err_destroy_OS_params: + umfOsMemoryProviderParamsDestroy(os_params); + if (ret == 0) { fprintf(stderr, "[producer] Shutting down (status OK) ...\n"); } else if (ret == 1) { diff --git a/include/umf/providers/provider_os_memory.h b/include/umf/providers/provider_os_memory.h index e175aaa6a7..a6bf43a7d9 100644 --- a/include/umf/providers/provider_os_memory.h +++ b/include/umf/providers/provider_os_memory.h @@ -60,32 +60,77 @@ typedef struct umf_numa_split_partition_t { unsigned target; } umf_numa_split_partition_t; -/// @brief Memory provider settings struct -typedef struct umf_os_memory_provider_params_t { - /// Combination of 'umf_mem_protection_flags_t' flags - unsigned protection; - /// memory visibility mode - umf_memory_visibility_t visibility; - /// (optional) a name of a shared memory file (valid only in case of the shared memory visibility) - char *shm_name; - - // NUMA config - /// ordered list of numa nodes - unsigned *numa_list; - /// length of numa_list - unsigned numa_list_len; - - /// Describes how node list is interpreted - umf_numa_mode_t numa_mode; - /// part size for interleave mode - 0 means default (system specific) - /// It might be rounded up because of HW constraints - size_t part_size; - - /// ordered list of the partitions for the split mode - umf_numa_split_partition_t *partitions; - /// len of the partitions array - unsigned partitions_len; -} umf_os_memory_provider_params_t; +struct umf_os_memory_provider_params_t; + +typedef struct umf_os_memory_provider_params_t + *umf_os_memory_provider_params_handle_t; + +/// @brief Create a struct to store parameters of the OS memory provider. +/// @param hParams [out] handle to the newly created parameters struct. +/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure. +umf_result_t umfOsMemoryProviderParamsCreate( + umf_os_memory_provider_params_handle_t *hParams); + +/// @brief Destroy parameters struct. +/// @param hParams handle to the parameters of the OS memory provider. +/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure. +umf_result_t umfOsMemoryProviderParamsDestroy( + umf_os_memory_provider_params_handle_t hParams); + +/// @brief Set protection flags for the OS memory provider. +/// @param hParams handle to the parameters of the OS memory provider. +/// @param protection combination of \p umf_mem_protection_flags_t flags. +/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure. +umf_result_t umfOsMemoryProviderParamsSetProtection( + umf_os_memory_provider_params_handle_t hParams, unsigned protection); + +/// @brief Set visibility mode for the OS memory provider. +/// @param hParams handle to the parameters of the OS memory provider. +/// @param visibility memory visibility mode. +/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure. +umf_result_t umfOsMemoryProviderParamsSetVisibility( + umf_os_memory_provider_params_handle_t hParams, + umf_memory_visibility_t visibility); + +/// @brief Set a name of a shared memory file for the OS memory provider. +/// @param hParams handle to the parameters of the OS memory provider. +/// @param shm_name a name of a shared memory file. +/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure. +umf_result_t umfOsMemoryProviderParamsSetShmName( + umf_os_memory_provider_params_handle_t hParams, const char *shm_name); + +/// @brief Set NUMA nodes for the OS memory provider. +/// @param hParams handle to the parameters of the OS memory provider. +/// @param numa_list ordered list of NUMA nodes. +/// @param numa_list_len length of the numa_list. +/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure. +umf_result_t umfOsMemoryProviderParamsSetNumaList( + umf_os_memory_provider_params_handle_t hParams, unsigned *numa_list, + unsigned numa_list_len); + +/// @brief Set NUMA mode for the OS memory provider. +/// @param hParams handle to the parameters of the OS memory provider. +/// @param numa_mode NUMA mode. Describes how node list is interpreted. +/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure. +umf_result_t umfOsMemoryProviderParamsSetNumaMode( + umf_os_memory_provider_params_handle_t hParams, umf_numa_mode_t numa_mode); + +/// @brief Set part size for the interleave mode. 0 means default (system specific) +/// It might be rounded up because of HW constraints. +/// @param hParams handle to the parameters of the OS memory provider. +/// @param part_size part size for interleave mode. +/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure. +umf_result_t umfOsMemoryProviderParamsSetPartSize( + umf_os_memory_provider_params_handle_t hParams, size_t part_size); + +/// @brief Set partitions for the split mode. +/// @param hParams handle to the parameters of the OS memory provider. +/// @param partitions ordered list of the partitions for the split mode. +/// @param partitions_len length of the partitions array. +/// @return UMF_RESULT_SUCCESS on success or appropriate error code on failure. +umf_result_t umfOsMemoryProviderParamsSetPartitions( + umf_os_memory_provider_params_handle_t hParams, + umf_numa_split_partition_t *partitions, unsigned partitions_len); /// @brief OS Memory Provider operation results typedef enum umf_os_memory_provider_native_error { @@ -101,23 +146,6 @@ typedef enum umf_os_memory_provider_native_error { umf_memory_provider_ops_t *umfOsMemoryProviderOps(void); -/// @brief Create default params for os memory provider -static inline umf_os_memory_provider_params_t -umfOsMemoryProviderParamsDefault(void) { - umf_os_memory_provider_params_t params = { - UMF_PROTECTION_READ | UMF_PROTECTION_WRITE, /* protection */ - UMF_MEM_MAP_PRIVATE, /* visibility mode */ - NULL, /* (optional) a name of a shared memory file (valid only in case of the shared memory visibility) */ - NULL, /* numa_list */ - 0, /* numa_list_len */ - UMF_NUMA_MODE_DEFAULT, /* numa_mode */ - 0, /* part_size */ - NULL, /* partitions */ - 0}; /* partitions_len*/ - - return params; -} - #ifdef __cplusplus } #endif diff --git a/scripts/docs_config/examples.rst b/scripts/docs_config/examples.rst index 5e2ff71fa1..a84dd3aa2e 100644 --- a/scripts/docs_config/examples.rst +++ b/scripts/docs_config/examples.rst @@ -31,11 +31,20 @@ the OS Memory Provider API:: #include "umf/providers/provider_os_memory.h" -Get a pointer to the OS memory provider operations struct and -a copy of default parameters:: +Get a pointer to the OS memory provider operations struct:: umf_memory_provider_ops_t *provider_ops = umfOsMemoryProviderOps(); - umf_os_memory_provider_params_t params = umfOsMemoryProviderParamsDefault(); + +Get a default OS memory provider parameters. The handle to the parameters object +is returned by the :any:`umfOsMemoryProviderParamsCreate` function:: + + umf_os_memory_provider_params_handle_t params = NULL; + + res = umfOsMemoryProviderParamsCreate(¶ms); + if (res != UMF_RESULT_SUCCESS) { + printf("Failed to create OS memory provider params!\n"); + return -1; + } The handle to created memory ``provider`` object is returned as the last argument of :any:`umfMemoryProviderCreate`:: @@ -43,7 +52,10 @@ of :any:`umfMemoryProviderCreate`:: umf_memory_provider_handle_t provider; umfMemoryProviderCreate(provider_ops, ¶ms, &provider); -With this handle we can allocate a chunk of memory, call :any:`umfMemoryProviderAlloc`:: +The ``params`` object can be destroyed after the provider is created:: + umfOsMemoryProviderParamsDestroy(params); + +With the ``provider`` handle we can allocate a chunk of memory, call :any:`umfMemoryProviderAlloc`:: size_t alloc_size = 5000; size_t alignment = 0; diff --git a/src/libumf.def b/src/libumf.def index abb25204c4..ae1ba68096 100644 --- a/src/libumf.def +++ b/src/libumf.def @@ -82,6 +82,15 @@ EXPORTS umfMemtargetGetType umfOpenIPCHandle umfOsMemoryProviderOps + umfOsMemoryProviderParamsCreate + umfOsMemoryProviderParamsDestroy + umfOsMemoryProviderParamsSetProtection + umfOsMemoryProviderParamsSetVisibility + umfOsMemoryProviderParamsSetShmName + umfOsMemoryProviderParamsSetNumaList + umfOsMemoryProviderParamsSetNumaMode + umfOsMemoryProviderParamsSetPartSize + umfOsMemoryProviderParamsSetPartitions umfPoolAlignedMalloc umfPoolByPtr umfPoolCalloc diff --git a/src/libumf.map b/src/libumf.map index 3a5e73f448..9231123846 100644 --- a/src/libumf.map +++ b/src/libumf.map @@ -76,6 +76,15 @@ UMF_1.0 { umfMemtargetGetType; umfOpenIPCHandle; umfOsMemoryProviderOps; + umfOsMemoryProviderParamsCreate; + umfOsMemoryProviderParamsDestroy; + umfOsMemoryProviderParamsSetProtection; + umfOsMemoryProviderParamsSetVisibility; + umfOsMemoryProviderParamsSetShmName; + umfOsMemoryProviderParamsSetNumaList; + umfOsMemoryProviderParamsSetNumaMode; + umfOsMemoryProviderParamsSetPartSize; + umfOsMemoryProviderParamsSetPartitions; umfPoolAlignedMalloc; umfPoolByPtr; umfPoolCalloc; diff --git a/src/memtargets/memtarget_numa.c b/src/memtargets/memtarget_numa.c index 34ba7fc100..f32774ebbc 100644 --- a/src/memtargets/memtarget_numa.c +++ b/src/memtargets/memtarget_numa.c @@ -69,22 +69,27 @@ static umf_result_t numa_memory_provider_create_from_memspace( return UMF_RESULT_ERROR_INVALID_ARGUMENT; } - umf_os_memory_provider_params_t params = umfOsMemoryProviderParamsDefault(); + umf_numa_mode_t numa_mode = UMF_NUMA_MODE_DEFAULT; + size_t part_size = 0; + umf_numa_split_partition_t *partitions = NULL; + unsigned partitions_len = 0; + unsigned *numa_list = NULL; + unsigned numa_list_len = 0; if (policy) { switch (policy->type) { case UMF_MEMPOLICY_INTERLEAVE: - params.numa_mode = UMF_NUMA_MODE_INTERLEAVE; - params.part_size = policy->ops.interleave.part_size; + numa_mode = UMF_NUMA_MODE_INTERLEAVE; + part_size = policy->ops.interleave.part_size; break; case UMF_MEMPOLICY_BIND: - params.numa_mode = UMF_NUMA_MODE_BIND; + numa_mode = UMF_NUMA_MODE_BIND; break; case UMF_MEMPOLICY_PREFERRED: - params.numa_mode = UMF_NUMA_MODE_PREFERRED; + numa_mode = UMF_NUMA_MODE_PREFERRED; break; case UMF_MEMPOLICY_SPLIT: - params.numa_mode = UMF_NUMA_MODE_SPLIT; + numa_mode = UMF_NUMA_MODE_SPLIT; // compile time check to ensure we can just cast // umf_mempolicy_split_partition_t to @@ -98,9 +103,8 @@ static umf_result_t numa_memory_provider_create_from_memspace( offsetof(umf_mempolicy_split_partition_t, target) != offsetof(umf_numa_split_partition_t, target)); - params.partitions = - (umf_numa_split_partition_t *)policy->ops.split.part; - params.partitions_len = (unsigned)policy->ops.split.part_len; + partitions = (umf_numa_split_partition_t *)policy->ops.split.part; + partitions_len = (unsigned)policy->ops.split.part_len; break; default: return UMF_RESULT_ERROR_INVALID_ARGUMENT; @@ -109,44 +113,80 @@ static umf_result_t numa_memory_provider_create_from_memspace( if (memspace == umfMemspaceHostAllGet()) { // For the default memspace, we use the default mode without any // call to mbind - params.numa_mode = UMF_NUMA_MODE_DEFAULT; + numa_mode = UMF_NUMA_MODE_DEFAULT; } else { - params.numa_mode = UMF_NUMA_MODE_BIND; + numa_mode = UMF_NUMA_MODE_BIND; } } if (memspace == umfMemspaceHostAllGet() && policy == NULL) { // For default memspace with default policy we use all numa nodes so // simply left numa list empty - params.numa_list_len = 0; - params.numa_list = NULL; + numa_list_len = 0; + numa_list = NULL; } else { - params.numa_list = - umf_ba_global_alloc(sizeof(*params.numa_list) * numNodesProvider); + numa_list = umf_ba_global_alloc(sizeof(*numa_list) * numNodesProvider); - if (!params.numa_list) { + if (!numa_list) { return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; } for (size_t i = 0; i < numNodesProvider; i++) { - params.numa_list[i] = numaTargets[i]->physical_id; + numa_list[i] = numaTargets[i]->physical_id; } - params.numa_list_len = (unsigned)numNodesProvider; + numa_list_len = (unsigned)numNodesProvider; } - umf_memory_provider_handle_t numaProvider = NULL; - int ret = umfMemoryProviderCreate(umfOsMemoryProviderOps(), ¶ms, - &numaProvider); + umf_os_memory_provider_params_handle_t params = NULL; + umf_result_t ret = umfOsMemoryProviderParamsCreate(¶ms); + if (ret != UMF_RESULT_SUCCESS) { + LOG_ERR("Creating OS memory provider params failed"); + goto destroy_numa_list; + } - umf_ba_global_free(params.numa_list); + ret = umfOsMemoryProviderParamsSetNumaMode(params, numa_mode); + if (ret != UMF_RESULT_SUCCESS) { + LOG_ERR("Setting NUMA mode failed"); + goto destroy_provider_params; + } - if (ret) { - return ret; + ret = + umfOsMemoryProviderParamsSetNumaList(params, numa_list, numa_list_len); + if (ret != UMF_RESULT_SUCCESS) { + LOG_ERR("Setting NUMA list failed"); + goto destroy_provider_params; + } + + ret = umfOsMemoryProviderParamsSetPartitions(params, partitions, + partitions_len); + if (ret != UMF_RESULT_SUCCESS) { + LOG_ERR("Setting partitions failed"); + goto destroy_provider_params; + } + + ret = umfOsMemoryProviderParamsSetPartSize(params, part_size); + if (ret != UMF_RESULT_SUCCESS) { + LOG_ERR("Setting part size failed"); + goto destroy_provider_params; + } + + umf_memory_provider_handle_t numaProvider = NULL; + ret = umfMemoryProviderCreate(umfOsMemoryProviderOps(), params, + &numaProvider); + if (ret != UMF_RESULT_SUCCESS) { + LOG_ERR("Creating OS memory provider failed"); + goto destroy_provider_params; } *provider = numaProvider; - return UMF_RESULT_SUCCESS; +destroy_provider_params: + umfOsMemoryProviderParamsDestroy(params); + +destroy_numa_list: + umf_ba_global_free(numa_list); + + return ret; } static umf_result_t numa_pool_create_from_memspace( diff --git a/src/provider/provider_os_memory.c b/src/provider/provider_os_memory.c index dae947651c..4c19944a96 100644 --- a/src/provider/provider_os_memory.c +++ b/src/provider/provider_os_memory.c @@ -22,10 +22,77 @@ umf_memory_provider_ops_t *umfOsMemoryProviderOps(void) { return NULL; } +umf_result_t umfOsMemoryProviderParamsCreate( + umf_os_memory_provider_params_handle_t *hParams) { + (void)hParams; + return UMF_RESULT_ERROR_NOT_SUPPORTED; +} + +umf_result_t umfOsMemoryProviderParamsDestroy( + umf_os_memory_provider_params_handle_t hParams) { + (void)hParams; + return UMF_RESULT_ERROR_NOT_SUPPORTED; +} + +umf_result_t umfOsMemoryProviderParamsSetProtection( + umf_os_memory_provider_params_handle_t hParams, unsigned protection) { + (void)hParams; + (void)protection; + return UMF_RESULT_ERROR_NOT_SUPPORTED; +} + +umf_result_t umfOsMemoryProviderParamsSetVisibility( + umf_os_memory_provider_params_handle_t hParams, + umf_memory_visibility_t visibility) { + (void)hParams; + (void)visibility; + return UMF_RESULT_ERROR_NOT_SUPPORTED; +} + +umf_result_t umfOsMemoryProviderParamsSetShmName( + umf_os_memory_provider_params_handle_t hParams, const char *shm_name) { + (void)hParams; + (void)shm_name; + return UMF_RESULT_ERROR_NOT_SUPPORTED; +} + +umf_result_t umfOsMemoryProviderParamsSetNumaList( + umf_os_memory_provider_params_handle_t hParams, unsigned *numa_list, + unsigned numa_list_len) { + (void)hParams; + (void)numa_list; + (void)numa_list_len; + return UMF_RESULT_ERROR_NOT_SUPPORTED; +} + +umf_result_t umfOsMemoryProviderParamsSetNumaMode( + umf_os_memory_provider_params_handle_t hParams, umf_numa_mode_t numa_mode) { + (void)hParams; + (void)numa_mode; + return UMF_RESULT_ERROR_NOT_SUPPORTED; +} + +umf_result_t umfOsMemoryProviderParamsSetPartSize( + umf_os_memory_provider_params_handle_t hParams, size_t part_size) { + (void)hParams; + (void)part_size; + return UMF_RESULT_ERROR_NOT_SUPPORTED; +} + +umf_result_t umfOsMemoryProviderParamsSetPartitions( + umf_os_memory_provider_params_handle_t hParams, + umf_numa_split_partition_t *partitions, unsigned partitions_len) { + (void)hParams; + (void)partitions; + (void)partitions_len; + return UMF_RESULT_ERROR_NOT_SUPPORTED; +} + #else // !defined(UMF_NO_HWLOC) #include "base_alloc_global.h" #include "critnib.h" +#include "libumf.h" #include "provider_os_memory_internal.h" #include "utils_common.h" #include "utils_concurrency.h" @@ -35,6 +102,32 @@ umf_memory_provider_ops_t *umfOsMemoryProviderOps(void) { return NULL; } #define TLS_MSG_BUF_LEN 1024 +typedef struct umf_os_memory_provider_params_t { + // Combination of 'umf_mem_protection_flags_t' flags + unsigned protection; + /// memory visibility mode + umf_memory_visibility_t visibility; + /// (optional) a name of a shared memory file (valid only in case of the shared memory visibility) + char *shm_name; + + // NUMA config + /// ordered list of numa nodes + unsigned *numa_list; + /// length of numa_list + unsigned numa_list_len; + + /// Describes how node list is interpreted + umf_numa_mode_t numa_mode; + /// part size for interleave mode - 0 means default (system specific) + /// It might be rounded up because of HW constraints + size_t part_size; + + /// ordered list of the partitions for the split mode + umf_numa_split_partition_t *partitions; + /// len of the partitions array + unsigned partitions_len; +} umf_os_memory_provider_params_t; + typedef struct os_last_native_error_t { int32_t native_error; int errno_value; @@ -1334,4 +1427,184 @@ umf_memory_provider_ops_t *umfOsMemoryProviderOps(void) { return &UMF_OS_MEMORY_PROVIDER_OPS; } +umf_result_t umfOsMemoryProviderParamsCreate( + umf_os_memory_provider_params_handle_t *hParams) { + libumfInit(); + if (hParams == NULL) { + LOG_ERR("OS memory provider params handle is NULL"); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + umf_os_memory_provider_params_handle_t params = + umf_ba_global_alloc(sizeof(*params)); + if (params == NULL) { + LOG_ERR("allocating memory for OS memory provider params failed"); + return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + params->protection = UMF_PROTECTION_READ | UMF_PROTECTION_WRITE; + params->visibility = UMF_MEM_MAP_PRIVATE; + params->shm_name = NULL; + params->numa_list = NULL; + params->numa_list_len = 0; + params->numa_mode = UMF_NUMA_MODE_DEFAULT; + params->part_size = 0; + params->partitions = NULL; + params->partitions_len = 0; + + *hParams = params; + + return UMF_RESULT_SUCCESS; +} + +umf_result_t umfOsMemoryProviderParamsDestroy( + umf_os_memory_provider_params_handle_t hParams) { + if (hParams != NULL) { + umf_ba_global_free(hParams->shm_name); + umf_ba_global_free(hParams->numa_list); + umf_ba_global_free(hParams->partitions); + } + + umf_ba_global_free(hParams); + + return UMF_RESULT_SUCCESS; +} + +umf_result_t umfOsMemoryProviderParamsSetProtection( + umf_os_memory_provider_params_handle_t hParams, unsigned protection) { + if (hParams == NULL) { + LOG_ERR("OS memory provider params handle is NULL"); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + hParams->protection = protection; + + return UMF_RESULT_SUCCESS; +} + +umf_result_t umfOsMemoryProviderParamsSetVisibility( + umf_os_memory_provider_params_handle_t hParams, + umf_memory_visibility_t visibility) { + if (hParams == NULL) { + LOG_ERR("OS memory provider params handle is NULL"); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + hParams->visibility = visibility; + + return UMF_RESULT_SUCCESS; +} + +umf_result_t umfOsMemoryProviderParamsSetShmName( + umf_os_memory_provider_params_handle_t hParams, const char *shm_name) { + if (hParams == NULL) { + LOG_ERR("OS memory provider params handle is NULL"); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + char *name = NULL; + if (shm_name) { + size_t len = strlen(shm_name) + 1; + name = umf_ba_global_alloc(len); + if (name == NULL) { + LOG_ERR("allocating memory for the shared memory name failed"); + return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + strncpy(name, shm_name, len); + } + umf_ba_global_free(hParams->shm_name); + hParams->shm_name = name; + + return UMF_RESULT_SUCCESS; +} + +umf_result_t umfOsMemoryProviderParamsSetNumaList( + umf_os_memory_provider_params_handle_t hParams, unsigned *numa_list, + unsigned numa_list_len) { + if (hParams == NULL) { + LOG_ERR("OS memory provider params handle is NULL"); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + if (numa_list_len && !numa_list) { + LOG_ERR("numa_list_len is not 0, but numa_list is NULL"); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + unsigned *new_list = NULL; + if (numa_list_len) { + new_list = umf_ba_global_alloc(numa_list_len * sizeof(*new_list)); + if (new_list == NULL) { + LOG_ERR("allocating memory for the NUMA list failed"); + return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + memcpy(new_list, numa_list, numa_list_len * sizeof(*new_list)); + } + + umf_ba_global_free(hParams->numa_list); + hParams->numa_list = new_list; + hParams->numa_list_len = numa_list_len; + + return UMF_RESULT_SUCCESS; +} + +umf_result_t umfOsMemoryProviderParamsSetNumaMode( + umf_os_memory_provider_params_handle_t hParams, umf_numa_mode_t numa_mode) { + if (hParams == NULL) { + LOG_ERR("OS memory provider params handle is NULL"); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + hParams->numa_mode = numa_mode; + + return UMF_RESULT_SUCCESS; +} + +umf_result_t umfOsMemoryProviderParamsSetPartSize( + umf_os_memory_provider_params_handle_t hParams, size_t part_size) { + if (hParams == NULL) { + LOG_ERR("OS memory provider params handle is NULL"); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + hParams->part_size = part_size; + + return UMF_RESULT_SUCCESS; +} + +umf_result_t umfOsMemoryProviderParamsSetPartitions( + umf_os_memory_provider_params_handle_t hParams, + umf_numa_split_partition_t *partitions, unsigned partitions_len) { + if (hParams == NULL) { + LOG_ERR("OS memory provider params handle is NULL"); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + if (partitions_len && !partitions) { + LOG_ERR("partitions_len is not 0, but partitions is NULL"); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + umf_numa_split_partition_t *new_partitions = NULL; + if (partitions_len) { + new_partitions = + umf_ba_global_alloc(partitions_len * sizeof(*new_partitions)); + if (new_partitions == NULL) { + LOG_ERR("allocating memory for the partitions failed"); + return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + memcpy(new_partitions, partitions, + partitions_len * sizeof(*new_partitions)); + } + + umf_ba_global_free(hParams->partitions); + hParams->partitions = new_partitions; + hParams->partitions_len = partitions_len; + + return UMF_RESULT_SUCCESS; +} + #endif // !defined(UMF_NO_HWLOC) diff --git a/src/proxy_lib/proxy_lib.c b/src/proxy_lib/proxy_lib.c index 3320f28983..4b168ab809 100644 --- a/src/proxy_lib/proxy_lib.c +++ b/src/proxy_lib/proxy_lib.c @@ -183,10 +183,15 @@ static int get_system_allocator_symbols(void) { void proxy_lib_create_common(void) { utils_log_init(); - umf_os_memory_provider_params_t os_params = - umfOsMemoryProviderParamsDefault(); + umf_os_memory_provider_params_handle_t os_params = NULL; umf_result_t umf_result; + umf_result = umfOsMemoryProviderParamsCreate(&os_params); + if (umf_result != UMF_RESULT_SUCCESS) { + LOG_ERR("creating OS memory provider params failed"); + exit(-1); + } + #ifndef _WIN32 size_t _threshold = get_size_threshold(); if (_threshold > 0) { @@ -203,26 +208,44 @@ void proxy_lib_create_common(void) { if (utils_env_var_has_str("UMF_PROXY", "page.disposition=shared-fd")) { LOG_INFO("proxy_lib: using the MAP_SHARED visibility mode with the " "file descriptor duplication"); - os_params.visibility = UMF_MEM_MAP_SHARED; - os_params.shm_name = NULL; - + umf_result = umfOsMemoryProviderParamsSetVisibility(os_params, + UMF_MEM_MAP_SHARED); + if (umf_result != UMF_RESULT_SUCCESS) { + LOG_ERR("setting visibility mode failed"); + exit(-1); + } + umf_result = umfOsMemoryProviderParamsSetShmName(os_params, NULL); + if (umf_result != UMF_RESULT_SUCCESS) { + LOG_ERR("setting shared memory name failed"); + exit(-1); + } } else if (utils_env_var_has_str("UMF_PROXY", "page.disposition=shared-shm")) { - os_params.visibility = UMF_MEM_MAP_SHARED; + umf_result = umfOsMemoryProviderParamsSetVisibility(os_params, + UMF_MEM_MAP_SHARED); + if (umf_result != UMF_RESULT_SUCCESS) { + LOG_ERR("setting visibility mode failed"); + exit(-1); + } char shm_name[NAME_MAX]; memset(shm_name, 0, NAME_MAX); sprintf(shm_name, "umf_proxy_lib_shm_pid_%i", utils_getpid()); - os_params.shm_name = shm_name; + umf_result = umfOsMemoryProviderParamsSetShmName(os_params, shm_name); + if (umf_result != UMF_RESULT_SUCCESS) { + LOG_ERR("setting shared memory name failed"); + exit(-1); + } LOG_INFO("proxy_lib: using the MAP_SHARED visibility mode with the " "named shared memory: %s", - os_params.shm_name); + shm_name); } #endif /* _WIN32 */ - umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), &os_params, + umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), os_params, &OS_memory_provider); + umfOsMemoryProviderParamsDestroy(os_params); if (umf_result != UMF_RESULT_SUCCESS) { LOG_ERR("creating OS memory provider failed"); exit(-1); diff --git a/test/c_api/multi_pool.c b/test/c_api/multi_pool.c index 518f992ea2..bbd8383124 100644 --- a/test/c_api/multi_pool.c +++ b/test/c_api/multi_pool.c @@ -60,11 +60,15 @@ createScalablePool(umf_memory_provider_handle_t provider) { #define ALLOC_SIZE 64 int main(void) { - umf_os_memory_provider_params_t params = umfOsMemoryProviderParamsDefault(); + umf_os_memory_provider_params_handle_t params = NULL; + umf_result_t ret = umfOsMemoryProviderParamsCreate(¶ms); + UT_ASSERTeq(ret, UMF_RESULT_SUCCESS); umf_memory_provider_handle_t hProvider; - umf_result_t ret = - umfMemoryProviderCreate(umfOsMemoryProviderOps(), ¶ms, &hProvider); + ret = umfMemoryProviderCreate(umfOsMemoryProviderOps(), params, &hProvider); + UT_ASSERTeq(ret, UMF_RESULT_SUCCESS); + + ret = umfOsMemoryProviderParamsDestroy(params); UT_ASSERTeq(ret, UMF_RESULT_SUCCESS); umf_memory_pool_handle_t pools[4]; diff --git a/test/fuzz/umfFuzz.cpp b/test/fuzz/umfFuzz.cpp index ac52c96b5e..360184c731 100644 --- a/test/fuzz/umfFuzz.cpp +++ b/test/fuzz/umfFuzz.cpp @@ -13,10 +13,15 @@ constexpr int MAX_PROVIDER_ALLOC_SIZE = 100 * 1024; // 100 kB int umf_memory_provider_create(TestState &test_state) { umf_memory_provider_ops_t *provider_ops = umfOsMemoryProviderOps(); - umf_os_memory_provider_params_t params = umfOsMemoryProviderParamsDefault(); - umf_result_t res = - umfMemoryProviderCreate(provider_ops, ¶ms, &test_state.provider); + umf_os_memory_provider_params_handle_t params = NULL; + + umf_result_t res = umfOsMemoryProviderParamsCreate(¶ms); + if (res != UMF_RESULT_SUCCESS) { + return -1; + } + res = umfMemoryProviderCreate(provider_ops, params, &test_state.provider); + umfOsMemoryProviderParamsDestroy(params); if (res != UMF_RESULT_SUCCESS) { return -1; } diff --git a/test/ipc_os_prov_consumer.c b/test/ipc_os_prov_consumer.c index 34f51fe1c4..f3f8d0090e 100644 --- a/test/ipc_os_prov_consumer.c +++ b/test/ipc_os_prov_consumer.c @@ -19,18 +19,44 @@ int main(int argc, char *argv[]) { return -1; } + int ret = 0; int port = atoi(argv[1]); - umf_os_memory_provider_params_t os_params; + umf_os_memory_provider_params_handle_t os_params = NULL; + + umf_result_t umf_result = umfOsMemoryProviderParamsCreate(&os_params); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf( + stderr, + "[consumer] ERROR: creating OS memory provider params failed\n"); + return -1; + } + + umf_result = + umfOsMemoryProviderParamsSetVisibility(os_params, UMF_MEM_MAP_SHARED); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf(stderr, "[consumer] ERROR: setting visibility mode failed\n"); + ret = -1; + goto destroy_provider_params; + } - os_params = umfOsMemoryProviderParamsDefault(); - os_params.visibility = UMF_MEM_MAP_SHARED; if (argc >= 3) { - os_params.shm_name = argv[2]; + umf_result = umfOsMemoryProviderParamsSetShmName(os_params, argv[2]); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf(stderr, + "[consumer] ERROR: setting shared memory name failed\n"); + ret = -1; + goto destroy_provider_params; + } } void *pool_params = NULL; - return run_consumer(port, umfScalablePoolOps(), pool_params, - umfOsMemoryProviderOps(), &os_params, memcopy, NULL); + ret = run_consumer(port, umfScalablePoolOps(), pool_params, + umfOsMemoryProviderOps(), os_params, memcopy, NULL); + +destroy_provider_params: + umfOsMemoryProviderParamsDestroy(os_params); + + return ret; } diff --git a/test/ipc_os_prov_producer.c b/test/ipc_os_prov_producer.c index 6232449022..890f1eb3e4 100644 --- a/test/ipc_os_prov_producer.c +++ b/test/ipc_os_prov_producer.c @@ -19,18 +19,44 @@ int main(int argc, char *argv[]) { return -1; } + int ret = 0; int port = atoi(argv[1]); - umf_os_memory_provider_params_t os_params; + umf_os_memory_provider_params_handle_t os_params = NULL; + + umf_result_t umf_result = umfOsMemoryProviderParamsCreate(&os_params); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf( + stderr, + "[producer] ERROR: creating OS memory provider params failed\n"); + return -1; + } + + umf_result = + umfOsMemoryProviderParamsSetVisibility(os_params, UMF_MEM_MAP_SHARED); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf(stderr, "[producer] ERROR: setting visibility mode failed\n"); + ret = -1; + goto destroy_provider_params; + } - os_params = umfOsMemoryProviderParamsDefault(); - os_params.visibility = UMF_MEM_MAP_SHARED; if (argc >= 3) { - os_params.shm_name = argv[2]; + umf_result = umfOsMemoryProviderParamsSetShmName(os_params, argv[2]); + if (umf_result != UMF_RESULT_SUCCESS) { + fprintf(stderr, + "[producer] ERROR: setting shared memory name failed\n"); + ret = -1; + goto destroy_provider_params; + } } void *pool_params = NULL; - return run_producer(port, umfScalablePoolOps(), pool_params, - umfOsMemoryProviderOps(), &os_params, memcopy, NULL); + ret = run_producer(port, umfScalablePoolOps(), pool_params, + umfOsMemoryProviderOps(), os_params, memcopy, NULL); + +destroy_provider_params: + umfOsMemoryProviderParamsDestroy(os_params); + + return ret; } diff --git a/test/pools/jemalloc_pool.cpp b/test/pools/jemalloc_pool.cpp index 3a78c53714..4dddbcd32b 100644 --- a/test/pools/jemalloc_pool.cpp +++ b/test/pools/jemalloc_pool.cpp @@ -11,11 +11,25 @@ using umf_test::test; using namespace umf_test; -auto defaultParams = umfOsMemoryProviderParamsDefault(); +using os_params_unique_handle_t = + std::unique_ptr; + +os_params_unique_handle_t createOsMemoryProviderParams() { + umf_os_memory_provider_params_handle_t params = nullptr; + umf_result_t res = umfOsMemoryProviderParamsCreate(¶ms); + if (res != UMF_RESULT_SUCCESS) { + throw std::runtime_error("Failed to create os memory provider params"); + } + + return os_params_unique_handle_t(params, &umfOsMemoryProviderParamsDestroy); +} +auto defaultParams = createOsMemoryProviderParams(); + INSTANTIATE_TEST_SUITE_P(jemallocPoolTest, umfPoolTest, ::testing::Values(poolCreateExtParams{ umfJemallocPoolOps(), nullptr, - umfOsMemoryProviderOps(), &defaultParams, + umfOsMemoryProviderOps(), defaultParams.get(), nullptr})); // this test makes sure that jemalloc does not use @@ -28,12 +42,18 @@ TEST_F(test, metadataNotAllocatedUsingProvider) { // set coarse grain allocations to PROT_NONE so that we can be sure // jemalloc does not touch any of the allocated memory - auto params = umfOsMemoryProviderParamsDefault(); - params.protection = UMF_PROTECTION_NONE; + umf_os_memory_provider_params_handle_t params = nullptr; + umf_result_t res = umfOsMemoryProviderParamsCreate(¶ms); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); + res = umfOsMemoryProviderParamsSetProtection(params, UMF_PROTECTION_NONE); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); auto pool = poolCreateExtUnique({umfJemallocPoolOps(), nullptr, - umfOsMemoryProviderOps(), ¶ms, nullptr}); + umfOsMemoryProviderOps(), params, nullptr}); + + res = umfOsMemoryProviderParamsDestroy(params); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); std::vector> allocs; for (size_t i = 0; i < numAllocs; i++) { diff --git a/test/pools/scalable_pool.cpp b/test/pools/scalable_pool.cpp index 0066f75e33..3edacd965c 100644 --- a/test/pools/scalable_pool.cpp +++ b/test/pools/scalable_pool.cpp @@ -9,11 +9,25 @@ #include "poolFixtures.hpp" #include "provider.hpp" -auto defaultParams = umfOsMemoryProviderParamsDefault(); +using os_params_unique_handle_t = + std::unique_ptr; + +os_params_unique_handle_t createOsMemoryProviderParams() { + umf_os_memory_provider_params_handle_t params = nullptr; + umf_result_t res = umfOsMemoryProviderParamsCreate(¶ms); + if (res != UMF_RESULT_SUCCESS) { + throw std::runtime_error("Failed to create os memory provider params"); + } + + return os_params_unique_handle_t(params, &umfOsMemoryProviderParamsDestroy); +} +auto defaultParams = createOsMemoryProviderParams(); + INSTANTIATE_TEST_SUITE_P(scalablePoolTest, umfPoolTest, ::testing::Values(poolCreateExtParams{ umfScalablePoolOps(), nullptr, - umfOsMemoryProviderOps(), &defaultParams, + umfOsMemoryProviderOps(), defaultParams.get(), nullptr})); using scalablePoolParams = std::tuple; diff --git a/test/provider_os_memory.cpp b/test/provider_os_memory.cpp index fc6469a0d8..57bce46d24 100644 --- a/test/provider_os_memory.cpp +++ b/test/provider_os_memory.cpp @@ -138,16 +138,23 @@ static umf_result_t create_os_provider_with_mode(umf_numa_mode_t mode, unsigned node_list_size) { umf_result_t umf_result; umf_memory_provider_handle_t os_memory_provider = nullptr; - umf_os_memory_provider_params_t os_memory_provider_params = - umfOsMemoryProviderParamsDefault(); + umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr; - os_memory_provider_params.numa_mode = mode; - os_memory_provider_params.numa_list = node_list; - os_memory_provider_params.numa_list_len = node_list_size; + umf_result = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + EXPECT_EQ(umf_result, UMF_RESULT_SUCCESS); - umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), - &os_memory_provider_params, - &os_memory_provider); + umf_result = + umfOsMemoryProviderParamsSetNumaMode(os_memory_provider_params, mode); + EXPECT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = umfOsMemoryProviderParamsSetNumaList( + os_memory_provider_params, node_list, node_list_size); + EXPECT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = + umfMemoryProviderCreate(umfOsMemoryProviderOps(), + os_memory_provider_params, &os_memory_provider); + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); if (umf_result == UMF_RESULT_SUCCESS) { EXPECT_NE(os_memory_provider, nullptr); umfMemoryProviderDestroy(os_memory_provider); @@ -193,29 +200,53 @@ TEST_F(test, create_ZERO_WEIGHT_PARTITION) { umf_numa_split_partition_t p = {0, 0}; umf_result_t umf_result; umf_memory_provider_handle_t os_memory_provider = nullptr; - umf_os_memory_provider_params_t os_memory_provider_params = - umfOsMemoryProviderParamsDefault(); + umf_os_memory_provider_params_handle_t os_memory_provider_params = NULL; + + umf_result = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + EXPECT_EQ(umf_result, UMF_RESULT_SUCCESS); - os_memory_provider_params.numa_mode = UMF_NUMA_MODE_SPLIT; - os_memory_provider_params.numa_list = &valid_list; - os_memory_provider_params.numa_list_len = valid_list_len; - os_memory_provider_params.partitions = &p; - os_memory_provider_params.partitions_len = 1; + umf_result = umfOsMemoryProviderParamsSetNumaMode(os_memory_provider_params, + UMF_NUMA_MODE_SPLIT); + EXPECT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = umfOsMemoryProviderParamsSetNumaList( + os_memory_provider_params, &valid_list, valid_list_len); + EXPECT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = umfOsMemoryProviderParamsSetPartitions( + os_memory_provider_params, &p, 1); + EXPECT_EQ(umf_result, UMF_RESULT_SUCCESS); umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), &os_memory_provider_params, &os_memory_provider); + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); + EXPECT_EQ(os_memory_provider, nullptr); ASSERT_EQ(umf_result, UMF_RESULT_ERROR_INVALID_ARGUMENT); } // positive tests using test_alloc_free_success -auto defaultParams = umfOsMemoryProviderParamsDefault(); +using os_params_unique_handle_t = + std::unique_ptr; + +os_params_unique_handle_t createOsMemoryProviderParams() { + umf_os_memory_provider_params_handle_t params = nullptr; + umf_result_t res = umfOsMemoryProviderParamsCreate(¶ms); + if (res != UMF_RESULT_SUCCESS) { + throw std::runtime_error("Failed to create os memory provider params"); + } + + return os_params_unique_handle_t(params, &umfOsMemoryProviderParamsDestroy); +} +auto defaultParams = createOsMemoryProviderParams(); + INSTANTIATE_TEST_SUITE_P(osProviderTest, umfProviderTest, ::testing::Values(providerCreateExtParams{ - umfOsMemoryProviderOps(), &defaultParams})); + umfOsMemoryProviderOps(), defaultParams.get()})); TEST_P(umfProviderTest, create_destroy) {} @@ -376,10 +407,22 @@ TEST_P(umfProviderTest, close_ipc_handle_wrong_visibility) { GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(umfIpcTest); -umf_os_memory_provider_params_t osMemoryProviderParamsShared() { - auto params = umfOsMemoryProviderParamsDefault(); - params.visibility = UMF_MEM_MAP_SHARED; - return params; +using os_params_unique_handle_t = + std::unique_ptr; + +os_params_unique_handle_t osMemoryProviderParamsShared() { + umf_os_memory_provider_params_handle_t params = nullptr; + umf_result_t res = umfOsMemoryProviderParamsCreate(¶ms); + if (res != UMF_RESULT_SUCCESS) { + throw std::runtime_error("Failed to create os memory provider params"); + } + res = umfOsMemoryProviderParamsSetVisibility(params, UMF_MEM_MAP_SHARED); + if (res != UMF_RESULT_SUCCESS) { + throw std::runtime_error("Failed to set protection"); + } + + return os_params_unique_handle_t(params, &umfOsMemoryProviderParamsDestroy); } auto os_params = osMemoryProviderParamsShared(); @@ -422,10 +465,10 @@ disjoint_params_unique_handle_t disjointParams = disjointPoolParams(); static std::vector ipcTestParamsList = { #if (defined UMF_POOL_DISJOINT_ENABLED) {umfDisjointPoolOps(), disjointParams.get(), umfOsMemoryProviderOps(), - &os_params, &hostAccessor, false}, + os_params.get(), &hostAccessor, false}, #endif #ifdef UMF_POOL_JEMALLOC_ENABLED - {umfJemallocPoolOps(), nullptr, umfOsMemoryProviderOps(), &os_params, + {umfJemallocPoolOps(), nullptr, umfOsMemoryProviderOps(), os_params.get(), &hostAccessor, false}, #endif }; diff --git a/test/provider_os_memory_config.cpp b/test/provider_os_memory_config.cpp index 78008f898e..ed34566182 100644 --- a/test/provider_os_memory_config.cpp +++ b/test/provider_os_memory_config.cpp @@ -22,13 +22,16 @@ struct providerConfigTest : testing::Test { const size_t size = 128; void *ptr = nullptr; std::string dest = "destination"; - umf_os_memory_provider_params_t params = umfOsMemoryProviderParamsDefault(); + umf_os_memory_provider_params_handle_t params = nullptr; void SetUp() override { int ret = numa_available(); if (ret) { GTEST_SKIP() << "Test skipped, NUMA not available"; } + + auto res = umfOsMemoryProviderParamsCreate(¶ms); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); } void TearDown() override { @@ -38,9 +41,11 @@ struct providerConfigTest : testing::Test { if (provider) { umfMemoryProviderDestroy(provider); } + + umfOsMemoryProviderParamsDestroy(params); } - void create_provider(umf_os_memory_provider_params_t *params) { + void create_provider(umf_os_memory_provider_params_handle_t params) { auto res = umfMemoryProviderCreate(umfOsMemoryProviderOps(), params, &provider); ASSERT_EQ(res, UMF_RESULT_SUCCESS); @@ -68,9 +73,9 @@ struct providerConfigTest : testing::Test { TEST_F(providerConfigTest, protection_flag_none) { // pages may not be accessed - PROT_NONE - params.protection = UMF_PROTECTION_NONE; + umfOsMemoryProviderParamsSetProtection(params, UMF_PROTECTION_NONE); - create_provider(¶ms); + create_provider(params); allocate_memory(); // read failure @@ -82,9 +87,9 @@ TEST_F(providerConfigTest, protection_flag_none) { TEST_F(providerConfigTest, protection_flag_read) { // pages may be read - PROT_READ - params.protection = UMF_PROTECTION_READ; + umfOsMemoryProviderParamsSetProtection(params, UMF_PROTECTION_READ); - create_provider(¶ms); + create_provider(params); allocate_memory(); // read success @@ -96,9 +101,9 @@ TEST_F(providerConfigTest, protection_flag_read) { TEST_F(providerConfigTest, protection_flag_write) { // pages may be written to - PROT_WRITE - params.protection = UMF_PROTECTION_WRITE; + umfOsMemoryProviderParamsSetProtection(params, UMF_PROTECTION_WRITE); - create_provider(¶ms); + create_provider(params); allocate_memory(); // write success @@ -107,9 +112,10 @@ TEST_F(providerConfigTest, protection_flag_write) { TEST_F(providerConfigTest, protection_flag_read_write) { // pages may be read and written to - PROT_READ | PROT_WRITE - params.protection = UMF_PROTECTION_READ | UMF_PROTECTION_WRITE; + umfOsMemoryProviderParamsSetProtection(params, UMF_PROTECTION_READ | + UMF_PROTECTION_WRITE); - create_provider(¶ms); + create_provider(params); allocate_memory(); // read success @@ -119,21 +125,115 @@ TEST_F(providerConfigTest, protection_flag_read_write) { write_memory("write string"); } +TEST_F(providerConfigTest, set_params_null_params_handle) { + umf_result_t res = umfOsMemoryProviderParamsCreate(nullptr); + ASSERT_EQ(res, UMF_RESULT_ERROR_INVALID_ARGUMENT); + + res = umfOsMemoryProviderParamsDestroy(nullptr); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); + + res = umfOsMemoryProviderParamsSetProtection(nullptr, UMF_PROTECTION_READ); + ASSERT_EQ(res, UMF_RESULT_ERROR_INVALID_ARGUMENT); + + res = umfOsMemoryProviderParamsSetVisibility(nullptr, UMF_MEM_MAP_PRIVATE); + ASSERT_EQ(res, UMF_RESULT_ERROR_INVALID_ARGUMENT); + + res = umfOsMemoryProviderParamsSetShmName(nullptr, "shm_name"); + ASSERT_EQ(res, UMF_RESULT_ERROR_INVALID_ARGUMENT); + + res = umfOsMemoryProviderParamsSetNumaList(nullptr, nullptr, 0); + ASSERT_EQ(res, UMF_RESULT_ERROR_INVALID_ARGUMENT); + + res = umfOsMemoryProviderParamsSetNumaMode(nullptr, UMF_NUMA_MODE_DEFAULT); + ASSERT_EQ(res, UMF_RESULT_ERROR_INVALID_ARGUMENT); + + res = umfOsMemoryProviderParamsSetPartSize(nullptr, 0); + ASSERT_EQ(res, UMF_RESULT_ERROR_INVALID_ARGUMENT); + + res = umfOsMemoryProviderParamsSetPartitions(nullptr, nullptr, 0); + ASSERT_EQ(res, UMF_RESULT_ERROR_INVALID_ARGUMENT); +} + +TEST_F(providerConfigTest, set_params_shm_name) { + umf_result_t res = umfOsMemoryProviderParamsSetShmName(params, nullptr); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); + + res = umfOsMemoryProviderParamsSetShmName(params, "shm_name"); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); + + res = umfOsMemoryProviderParamsSetShmName(params, ""); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); + + res = umfOsMemoryProviderParamsSetShmName(params, nullptr); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); +} + +TEST_F(providerConfigTest, set_params_numa_list) { + unsigned numa_list[1] = {0}; + + umf_result_t res = umfOsMemoryProviderParamsSetNumaList(params, nullptr, 0); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); + + res = umfOsMemoryProviderParamsSetNumaList(params, numa_list, 1); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); + + res = umfOsMemoryProviderParamsSetNumaList(params, nullptr, 1); + ASSERT_EQ(res, UMF_RESULT_ERROR_INVALID_ARGUMENT); + + res = umfOsMemoryProviderParamsSetNumaList(params, numa_list, 0); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); + + // repeat the valid set to check memory leaks under Valgrind + res = umfOsMemoryProviderParamsSetNumaList(params, numa_list, 1); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); +} + +TEST_F(providerConfigTest, set_params_partitions) { + umf_numa_split_partition_t partitions[1] = {{0, 1}}; + + umf_result_t res = + umfOsMemoryProviderParamsSetPartitions(params, nullptr, 0); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); + + res = umfOsMemoryProviderParamsSetPartitions(params, partitions, 1); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); + + res = umfOsMemoryProviderParamsSetPartitions(params, nullptr, 1); + ASSERT_EQ(res, UMF_RESULT_ERROR_INVALID_ARGUMENT); + + res = umfOsMemoryProviderParamsSetPartitions(params, partitions, 0); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); + + // repeat the valid set to check memory leaks under Valgrind + res = umfOsMemoryProviderParamsSetPartitions(params, partitions, 1); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); +} + struct providerConfigTestNumaMode : providerConfigTest, testing::WithParamInterface { struct bitmask *allowed_nodes = nullptr; - umf_os_memory_provider_params_t params = umfOsMemoryProviderParamsDefault(); + umf_numa_mode_t expected_numa_mode; void SetUp() override { providerConfigTest::SetUp(); - params.numa_mode = GetParam(); + + if (::providerConfigTest::IsSkipped()) { + GTEST_SKIP(); + } + + expected_numa_mode = GetParam(); + + auto res = + umfOsMemoryProviderParamsSetNumaMode(params, expected_numa_mode); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); } void TearDown() override { if (allowed_nodes) { numa_bitmask_free(allowed_nodes); } + providerConfigTest::TearDown(); } }; @@ -152,24 +252,27 @@ INSTANTIATE_TEST_SUITE_P(numa_modes, providerConfigTestNumaMode, #endif TEST_P(providerConfigTestNumaMode, numa_modes) { - if (params.numa_mode != UMF_NUMA_MODE_DEFAULT && - params.numa_mode != UMF_NUMA_MODE_LOCAL) { + unsigned numa_list_len = 0; + unsigned *numa_list = nullptr; + if (expected_numa_mode != UMF_NUMA_MODE_DEFAULT && + expected_numa_mode != UMF_NUMA_MODE_LOCAL) { allowed_nodes = numa_get_mems_allowed(); // convert bitmask to array of nodes - params.numa_list_len = numa_bitmask_weight(allowed_nodes); - params.numa_list = (unsigned *)malloc(params.numa_list_len * - sizeof(*params.numa_list)); - ASSERT_NE(params.numa_list, nullptr); + numa_list_len = numa_bitmask_weight(allowed_nodes); + numa_list = (unsigned *)malloc(numa_list_len * sizeof(*numa_list)); + ASSERT_NE(numa_list, nullptr); unsigned count = 0; - for (unsigned i = 0; i < params.numa_list_len; i++) { + for (unsigned i = 0; i < numa_list_len; i++) { if (numa_bitmask_isbitset(allowed_nodes, i)) { - params.numa_list[count++] = i; + numa_list[count++] = i; } } - ASSERT_EQ(count, params.numa_list_len); + ASSERT_EQ(count, numa_list_len); + + umfOsMemoryProviderParamsSetNumaList(params, numa_list, numa_list_len); } - create_provider(¶ms); + create_provider(params); allocate_memory(); write_memory("write string"); @@ -177,25 +280,25 @@ TEST_P(providerConfigTestNumaMode, numa_modes) { long ret = get_mempolicy(&actual_mode, nullptr, 0, ptr, MPOL_F_ADDR); ASSERT_EQ(ret, 0); - if (params.numa_mode == UMF_NUMA_MODE_DEFAULT) { + if (expected_numa_mode == UMF_NUMA_MODE_DEFAULT) { ASSERT_EQ(actual_mode, MPOL_DEFAULT); - } else if (params.numa_mode == UMF_NUMA_MODE_BIND) { + } else if (expected_numa_mode == UMF_NUMA_MODE_BIND) { ASSERT_EQ(actual_mode, MPOL_BIND); - } else if (params.numa_mode == UMF_NUMA_MODE_INTERLEAVE) { + } else if (expected_numa_mode == UMF_NUMA_MODE_INTERLEAVE) { ASSERT_EQ(actual_mode, MPOL_INTERLEAVE); - } else if (params.numa_mode == UMF_NUMA_MODE_PREFERRED) { + } else if (expected_numa_mode == UMF_NUMA_MODE_PREFERRED) { // MPOL_PREFERRED_MANY is equivalent to MPOL_PREFERRED if a single node is set if (actual_mode != MPOL_PREFERRED_MANY) { ASSERT_EQ(actual_mode, MPOL_PREFERRED); } - } else if (params.numa_mode == UMF_NUMA_MODE_LOCAL) { + } else if (expected_numa_mode == UMF_NUMA_MODE_LOCAL) { // MPOL_PREFERRED_* is equivalent to MPOL_LOCAL if no node is set if (actual_mode == MPOL_PREFERRED || actual_mode == MPOL_PREFERRED_MANY) { - ASSERT_EQ(params.numa_list_len, 0); + ASSERT_EQ(numa_list_len, 0); } else { ASSERT_EQ(actual_mode, MPOL_LOCAL); } } - free(params.numa_list); + free(numa_list); } diff --git a/test/provider_os_memory_multiple_numa_nodes.cpp b/test/provider_os_memory_multiple_numa_nodes.cpp index 7f0a1401bc..e493a427ca 100644 --- a/test/provider_os_memory_multiple_numa_nodes.cpp +++ b/test/provider_os_memory_multiple_numa_nodes.cpp @@ -14,9 +14,6 @@ #include -static umf_os_memory_provider_params_t UMF_OS_MEMORY_PROVIDER_PARAMS_TEST = - umfOsMemoryProviderParamsDefault(); - std::vector get_available_numa_nodes() { if (numa_available() == -1 || numa_all_nodes_ptr == nullptr) { return std::vector(); @@ -85,11 +82,11 @@ struct testNuma : testing::Test { ASSERT_NE(nodemask, nullptr); } - void - initOsProvider(umf_os_memory_provider_params_t os_memory_provider_params) { + void initOsProvider( + umf_os_memory_provider_params_handle_t os_memory_provider_params) { umf_result_t umf_result; umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), - &os_memory_provider_params, + os_memory_provider_params, &os_memory_provider); ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); ASSERT_NE(os_memory_provider, nullptr); @@ -157,16 +154,25 @@ INSTANTIATE_TEST_SUITE_P(testNumaNodesAllocations, testNumaOnEachNode, TEST_P(testNumaOnEachNode, checkNumaNodesAllocations) { unsigned numa_node_number = GetParam(); ASSERT_GE(numa_node_number, 0); + umf_result_t umf_result; - umf_os_memory_provider_params_t os_memory_provider_params = - UMF_OS_MEMORY_PROVIDER_PARAMS_TEST; + umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr; + + umf_result = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = umfOsMemoryProviderParamsSetNumaList(os_memory_provider_params, + &numa_node_number, 1); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = umfOsMemoryProviderParamsSetNumaMode(os_memory_provider_params, + UMF_NUMA_MODE_BIND); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); - os_memory_provider_params.numa_list = &numa_node_number; - os_memory_provider_params.numa_list_len = 1; - os_memory_provider_params.numa_mode = UMF_NUMA_MODE_BIND; initOsProvider(os_memory_provider_params); - umf_result_t umf_result; + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); + umf_result = umfMemoryProviderAlloc(os_memory_provider, alloc_size, 0, &ptr); ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); @@ -181,16 +187,25 @@ TEST_P(testNumaOnEachNode, checkNumaNodesAllocations) { // on each of the available numa nodes. TEST_P(testNumaOnEachNode, checkModePreferred) { unsigned numa_node_number = GetParam(); - umf_os_memory_provider_params_t os_memory_provider_params = - UMF_OS_MEMORY_PROVIDER_PARAMS_TEST; + umf_result_t umf_result; + umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr; + + umf_result = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); - os_memory_provider_params.numa_list = &numa_node_number; + umf_result = umfOsMemoryProviderParamsSetNumaList(os_memory_provider_params, + &numa_node_number, 1); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); numa_bitmask_setbit(nodemask, numa_node_number); - os_memory_provider_params.numa_list_len = 1; - os_memory_provider_params.numa_mode = UMF_NUMA_MODE_PREFERRED; + + umf_result = umfOsMemoryProviderParamsSetNumaMode(os_memory_provider_params, + UMF_NUMA_MODE_PREFERRED); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + initOsProvider(os_memory_provider_params); - umf_result_t umf_result; + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); + umf_result = umfMemoryProviderAlloc(os_memory_provider, alloc_size, 0, &ptr); ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); @@ -207,14 +222,19 @@ TEST_P(testNumaOnEachNode, checkModePreferred) { TEST_P(testNumaOnEachNode, checkModeDefaultSetMempolicy) { unsigned numa_node_number = GetParam(); numa_bitmask_setbit(nodemask, numa_node_number); - umf_os_memory_provider_params_t os_memory_provider_params = - UMF_OS_MEMORY_PROVIDER_PARAMS_TEST; + umf_result_t umf_result; + umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr; + + umf_result = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + initOsProvider(os_memory_provider_params); + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); + long ret = set_mempolicy(MPOL_BIND, nodemask->maskp, nodemask->size); ASSERT_EQ(ret, 0); - umf_result_t umf_result; umf_result = umfMemoryProviderAlloc(os_memory_provider, alloc_size, 0, &ptr); ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); @@ -232,15 +252,24 @@ TEST_P(testNumaOnEachNode, checkModeInterleaveSingleNode) { constexpr int pages_num = 1024; size_t page_size = sysconf(_SC_PAGE_SIZE); - umf_os_memory_provider_params_t os_memory_provider_params = - UMF_OS_MEMORY_PROVIDER_PARAMS_TEST; + umf_result_t umf_result; + umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr; + + umf_result = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = umfOsMemoryProviderParamsSetNumaList(os_memory_provider_params, + &numa_node_number, 1); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = umfOsMemoryProviderParamsSetNumaMode(os_memory_provider_params, + UMF_NUMA_MODE_INTERLEAVE); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); - os_memory_provider_params.numa_list = &numa_node_number; - os_memory_provider_params.numa_list_len = 1; - os_memory_provider_params.numa_mode = UMF_NUMA_MODE_INTERLEAVE; initOsProvider(os_memory_provider_params); - umf_result_t umf_result; + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); + umf_result = umfMemoryProviderAlloc(os_memory_provider, pages_num * page_size, 0, &ptr); ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); @@ -282,12 +311,20 @@ TEST_P(testNumaOnEachCpu, checkModePreferredEmptyNodeset) { ASSERT_EQ(ret, 0); - umf_os_memory_provider_params_t os_memory_provider_params = - UMF_OS_MEMORY_PROVIDER_PARAMS_TEST; - os_memory_provider_params.numa_mode = UMF_NUMA_MODE_PREFERRED; + umf_result_t umf_result; + umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr; + + umf_result = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = umfOsMemoryProviderParamsSetNumaMode(os_memory_provider_params, + UMF_NUMA_MODE_PREFERRED); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + initOsProvider(os_memory_provider_params); - umf_result_t umf_result; + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); + umf_result = umfMemoryProviderAlloc(os_memory_provider, alloc_size, 0, &ptr); ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); @@ -319,12 +356,20 @@ TEST_P(testNumaOnEachCpu, checkModeLocal) { ASSERT_EQ(ret, 0); - umf_os_memory_provider_params_t os_memory_provider_params = - UMF_OS_MEMORY_PROVIDER_PARAMS_TEST; - os_memory_provider_params.numa_mode = UMF_NUMA_MODE_LOCAL; + umf_result_t umf_result; + umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr; + + umf_result = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = umfOsMemoryProviderParamsSetNumaMode(os_memory_provider_params, + UMF_NUMA_MODE_LOCAL); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + initOsProvider(os_memory_provider_params); - umf_result_t umf_result; + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); + umf_result = umfMemoryProviderAlloc(os_memory_provider, alloc_size, 0, &ptr); ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); @@ -347,11 +392,16 @@ TEST_P(testNumaOnEachCpu, checkModeLocal) { // default policy - it allocates pages on the node of the CPU that triggered // the allocation. TEST_F(testNuma, checkModeDefault) { - umf_os_memory_provider_params_t os_memory_provider_params = - UMF_OS_MEMORY_PROVIDER_PARAMS_TEST; + umf_result_t umf_result; + umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr; + + umf_result = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + initOsProvider(os_memory_provider_params); - umf_result_t umf_result; + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); + umf_result = umfMemoryProviderAlloc(os_memory_provider, alloc_size, 0, &ptr); ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); @@ -371,18 +421,27 @@ TEST_F(testNuma, checkModeDefault) { TEST_F(testNuma, checkModeInterleave) { constexpr int pages_num = 1024; size_t page_size = sysconf(_SC_PAGE_SIZE); - umf_os_memory_provider_params_t os_memory_provider_params = - UMF_OS_MEMORY_PROVIDER_PARAMS_TEST; + umf_result_t umf_result; + umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr; + + umf_result = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); std::vector numa_nodes = get_available_numa_nodes(); set_all_available_nodemask_bits(nodemask); - os_memory_provider_params.numa_list = numa_nodes.data(); - os_memory_provider_params.numa_list_len = numa_nodes.size(); - os_memory_provider_params.numa_mode = UMF_NUMA_MODE_INTERLEAVE; + umf_result = umfOsMemoryProviderParamsSetNumaList( + os_memory_provider_params, numa_nodes.data(), numa_nodes.size()); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = umfOsMemoryProviderParamsSetNumaMode(os_memory_provider_params, + UMF_NUMA_MODE_INTERLEAVE); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + initOsProvider(os_memory_provider_params); - umf_result_t umf_result; + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); + umf_result = umfMemoryProviderAlloc(os_memory_provider, pages_num * page_size, 0, &ptr); ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); @@ -432,20 +491,32 @@ TEST_F(testNuma, checkModeInterleaveCustomPartSize) { ASSERT_GT(_page_size, 0); size_t page_size = _page_size; size_t part_size = page_size * 100; - umf_os_memory_provider_params_t os_memory_provider_params = - UMF_OS_MEMORY_PROVIDER_PARAMS_TEST; + umf_result_t umf_result; + umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr; + + umf_result = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); std::vector numa_nodes = get_available_numa_nodes(); - os_memory_provider_params.numa_list = numa_nodes.data(); - os_memory_provider_params.numa_list_len = numa_nodes.size(); - os_memory_provider_params.numa_mode = UMF_NUMA_MODE_INTERLEAVE; + umf_result = umfOsMemoryProviderParamsSetNumaList( + os_memory_provider_params, numa_nodes.data(), numa_nodes.size()); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = umfOsMemoryProviderParamsSetNumaMode(os_memory_provider_params, + UMF_NUMA_MODE_INTERLEAVE); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + // part size do not need to be multiple of page size - os_memory_provider_params.part_size = part_size - 1; + umf_result = umfOsMemoryProviderParamsSetPartSize(os_memory_provider_params, + part_size - 1); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + initOsProvider(os_memory_provider_params); + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); + size_t size = part_num * part_size; - umf_result_t umf_result; umf_result = umfMemoryProviderAlloc(os_memory_provider, size, 0, &ptr); ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); ASSERT_NE(ptr, nullptr); @@ -601,9 +672,12 @@ TEST_P(testNumaSplit, checkModeSplit) { ASSERT_GT(_page_size, 0); size_t page_size = _page_size; auto [required_numa_nodes, pages, in, out] = param; + umf_result_t umf_result; + + umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr; - umf_os_memory_provider_params_t os_memory_provider_params = - UMF_OS_MEMORY_PROVIDER_PARAMS_TEST; + umf_result = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); std::vector numa_nodes = get_available_numa_nodes(); @@ -622,16 +696,24 @@ TEST_P(testNumaSplit, checkModeSplit) { numa_nodes.begin() + required_numa_nodes, g); } - os_memory_provider_params.numa_list = numa_nodes.data(); - os_memory_provider_params.numa_list_len = required_numa_nodes; - os_memory_provider_params.numa_mode = UMF_NUMA_MODE_SPLIT; + umf_result = umfOsMemoryProviderParamsSetNumaList( + os_memory_provider_params, numa_nodes.data(), required_numa_nodes); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = umfOsMemoryProviderParamsSetNumaMode(os_memory_provider_params, + UMF_NUMA_MODE_SPLIT); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = umfOsMemoryProviderParamsSetPartitions( + os_memory_provider_params, in.data(), in.size()); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); - os_memory_provider_params.partitions = in.data(); - os_memory_provider_params.partitions_len = in.size(); initOsProvider(os_memory_provider_params); + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); + size_t size = page_size * pages; - umf_result_t umf_result; + umf_result = umfMemoryProviderAlloc(os_memory_provider, size, 0, &ptr); ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); ASSERT_NE(ptr, nullptr); @@ -665,17 +747,26 @@ TEST_P(testNumaSplit, checkModeSplit) { // Test for allocations on all numa nodes with BIND mode. // According to mbind it should go to the closest node. TEST_F(testNuma, checkModeBindOnAllNodes) { - umf_os_memory_provider_params_t os_memory_provider_params = - UMF_OS_MEMORY_PROVIDER_PARAMS_TEST; + umf_result_t umf_result; + umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr; + + umf_result = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); std::vector numa_nodes = get_available_numa_nodes(); - os_memory_provider_params.numa_list = numa_nodes.data(); - os_memory_provider_params.numa_list_len = numa_nodes.size(); - os_memory_provider_params.numa_mode = UMF_NUMA_MODE_BIND; + umf_result = umfOsMemoryProviderParamsSetNumaList( + os_memory_provider_params, numa_nodes.data(), numa_nodes.size()); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = umfOsMemoryProviderParamsSetNumaMode(os_memory_provider_params, + UMF_NUMA_MODE_BIND); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + initOsProvider(os_memory_provider_params); - umf_result_t umf_result; + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); + umf_result = umfMemoryProviderAlloc(os_memory_provider, alloc_size, 0, &ptr); ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); @@ -709,19 +800,28 @@ TEST_F(testNuma, checkModeBindOnAllNodes) { // Local mode enabled when numa_list is set. // For the local mode the nodeset must be empty. TEST_F(testNuma, checkModeLocalIllegalArgSet) { - umf_os_memory_provider_params_t os_memory_provider_params = - UMF_OS_MEMORY_PROVIDER_PARAMS_TEST; + umf_result_t umf_result; + umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr; + + umf_result = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); std::vector numa_nodes = get_available_numa_nodes(); - os_memory_provider_params.numa_list = numa_nodes.data(); - os_memory_provider_params.numa_list_len = numa_nodes.size(); - os_memory_provider_params.numa_mode = UMF_NUMA_MODE_LOCAL; + umf_result = umfOsMemoryProviderParamsSetNumaList( + os_memory_provider_params, numa_nodes.data(), numa_nodes.size()); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = umfOsMemoryProviderParamsSetNumaMode(os_memory_provider_params, + UMF_NUMA_MODE_LOCAL); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); - umf_result_t umf_result; umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), &os_memory_provider_params, &os_memory_provider); + + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_ERROR_INVALID_ARGUMENT); ASSERT_EQ(os_memory_provider, nullptr); } @@ -729,18 +829,24 @@ TEST_F(testNuma, checkModeLocalIllegalArgSet) { // Default mode enabled when numa_list is set. // For the default mode the nodeset must be empty. TEST_F(testNuma, checkModeDefaultIllegalArgSet) { - umf_os_memory_provider_params_t os_memory_provider_params = - UMF_OS_MEMORY_PROVIDER_PARAMS_TEST; + umf_result_t umf_result; + umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr; + + umf_result = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); std::vector numa_nodes = get_available_numa_nodes(); - os_memory_provider_params.numa_list = numa_nodes.data(); - os_memory_provider_params.numa_list_len = numa_nodes.size(); + umf_result = umfOsMemoryProviderParamsSetNumaList( + os_memory_provider_params, numa_nodes.data(), numa_nodes.size()); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); - umf_result_t umf_result; umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), &os_memory_provider_params, &os_memory_provider); + + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_ERROR_INVALID_ARGUMENT); ASSERT_EQ(os_memory_provider, nullptr); } @@ -748,14 +854,22 @@ TEST_F(testNuma, checkModeDefaultIllegalArgSet) { // Bind mode enabled when numa_list is not set. // For the bind mode the nodeset must be non-empty. TEST_F(testNuma, checkModeBindIllegalArgSet) { - umf_os_memory_provider_params_t os_memory_provider_params = - UMF_OS_MEMORY_PROVIDER_PARAMS_TEST; - os_memory_provider_params.numa_mode = UMF_NUMA_MODE_BIND; - umf_result_t umf_result; + umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr; + + umf_result = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = umfOsMemoryProviderParamsSetNumaMode(os_memory_provider_params, + UMF_NUMA_MODE_BIND); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), &os_memory_provider_params, &os_memory_provider); + + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_ERROR_INVALID_ARGUMENT); ASSERT_EQ(os_memory_provider, nullptr); } @@ -763,14 +877,22 @@ TEST_F(testNuma, checkModeBindIllegalArgSet) { // Interleave mode enabled numa_list is not set. // For the interleave mode the nodeset must be non-empty. TEST_F(testNuma, checkModeInterleaveIllegalArgSet) { - umf_os_memory_provider_params_t os_memory_provider_params = - UMF_OS_MEMORY_PROVIDER_PARAMS_TEST; - os_memory_provider_params.numa_mode = UMF_NUMA_MODE_INTERLEAVE; - umf_result_t umf_result; + umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr; + + umf_result = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + + umf_result = umfOsMemoryProviderParamsSetNumaMode(os_memory_provider_params, + UMF_NUMA_MODE_INTERLEAVE); + ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS); + umf_result = umfMemoryProviderCreate(umfOsMemoryProviderOps(), &os_memory_provider_params, &os_memory_provider); + + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); + ASSERT_EQ(umf_result, UMF_RESULT_ERROR_INVALID_ARGUMENT); ASSERT_EQ(os_memory_provider, nullptr); } @@ -779,16 +901,29 @@ TEST_F(testNuma, checkModeInterleaveIllegalArgSet) { TEST_F(testNuma, maxPartSize) { std::vector numa_nodes = get_available_numa_nodes(); - umf_os_memory_provider_params_t os_memory_provider_params = - UMF_OS_MEMORY_PROVIDER_PARAMS_TEST; - os_memory_provider_params.numa_mode = UMF_NUMA_MODE_INTERLEAVE; - os_memory_provider_params.part_size = SIZE_MAX; - os_memory_provider_params.numa_list = numa_nodes.data(); - os_memory_provider_params.numa_list_len = numa_nodes.size(); + umf_os_memory_provider_params_handle_t os_memory_provider_params = nullptr; + + auto res = umfOsMemoryProviderParamsCreate(&os_memory_provider_params); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); + + res = umfOsMemoryProviderParamsSetNumaMode(os_memory_provider_params, + UMF_NUMA_MODE_INTERLEAVE); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); + + res = umfOsMemoryProviderParamsSetPartSize(os_memory_provider_params, + SIZE_MAX); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); + + res = umfOsMemoryProviderParamsSetNumaList( + os_memory_provider_params, numa_nodes.data(), numa_nodes.size()); + ASSERT_EQ(res, UMF_RESULT_SUCCESS); + + res = umfMemoryProviderCreate(umfOsMemoryProviderOps(), + &os_memory_provider_params, + &os_memory_provider); + + umfOsMemoryProviderParamsDestroy(os_memory_provider_params); - auto res = umfMemoryProviderCreate(umfOsMemoryProviderOps(), - &os_memory_provider_params, - &os_memory_provider); ASSERT_EQ(res, UMF_RESULT_ERROR_INVALID_ARGUMENT); ASSERT_EQ(os_memory_provider, nullptr); }