From b1e1edb4e05e27c4311bcfe5441b958d1e69c3a4 Mon Sep 17 00:00:00 2001 From: Lukasz Dorau Date: Fri, 20 Sep 2024 08:53:46 +0200 Subject: [PATCH] Move all common functions to utils_common Move all common functions to utils_common and rename them to utils_* Signed-off-by: Lukasz Dorau --- include/umf/memory_provider.h | 17 ++ include/umf/providers/provider_os_memory.h | 17 -- src/CMakeLists.txt | 18 +- src/provider/provider_devdax_memory.c | 31 ++- src/provider/provider_file_memory.c | 37 ++-- src/provider/provider_os_memory.c | 82 +++----- src/provider/provider_os_memory_internal.h | 51 ----- src/provider/provider_os_memory_posix.c | 180 ----------------- src/provider/provider_os_memory_windows.c | 190 ------------------ src/utils/CMakeLists.txt | 11 + src/utils/utils_common.c | 25 +++ src/utils/utils_common.h | 51 +++++ .../utils_linux_common.c} | 128 ++++++------ .../utils_macosx_common.c} | 57 +++++- src/utils/utils_posix_common.c | 162 +++++++++++++++ src/utils/utils_windows_common.c | 165 +++++++++++++++ test/CMakeLists.txt | 23 ++- test/utils/utils_log.cpp | 2 + 18 files changed, 636 insertions(+), 611 deletions(-) delete mode 100644 src/provider/provider_os_memory_posix.c delete mode 100644 src/provider/provider_os_memory_windows.c rename src/{provider/provider_os_memory_linux.c => utils/utils_linux_common.c} (82%) rename src/{provider/provider_os_memory_macosx.c => utils/utils_macosx_common.c} (56%) diff --git a/include/umf/memory_provider.h b/include/umf/memory_provider.h index cec8edbcf..fb217a0e8 100644 --- a/include/umf/memory_provider.h +++ b/include/umf/memory_provider.h @@ -17,6 +17,23 @@ extern "C" { #endif +/// @brief Memory visibility mode +typedef enum umf_memory_visibility_t { + UMF_MEM_MAP_PRIVATE = 1, ///< private memory mapping + UMF_MEM_MAP_SHARED, ///< shared memory mapping (supported on Linux only) +} umf_memory_visibility_t; + +/// @brief Protection of the memory allocations +typedef enum umf_mem_protection_flags_t { + UMF_PROTECTION_NONE = (1 << 0), ///< Memory allocations can not be accessed + UMF_PROTECTION_READ = (1 << 1), ///< Memory allocations can be read. + UMF_PROTECTION_WRITE = (1 << 2), ///< Memory allocations can be written. + UMF_PROTECTION_EXEC = (1 << 3), ///< Memory allocations can be executed. + /// @cond + UMF_PROTECTION_MAX // must be the last one + /// @endcond +} umf_mem_protection_flags_t; + /// @brief A struct containing memory provider specific set of functions typedef struct umf_memory_provider_t *umf_memory_provider_handle_t; diff --git a/include/umf/providers/provider_os_memory.h b/include/umf/providers/provider_os_memory.h index 1d4494547..e175aaa6a 100644 --- a/include/umf/providers/provider_os_memory.h +++ b/include/umf/providers/provider_os_memory.h @@ -18,23 +18,6 @@ extern "C" { #define UMF_OS_RESULTS_START_FROM 1000 /// @endcond -/// @brief Protection of the memory allocations -typedef enum umf_mem_protection_flags_t { - UMF_PROTECTION_NONE = (1 << 0), ///< Memory allocations can not be accessed - UMF_PROTECTION_READ = (1 << 1), ///< Memory allocations can be read. - UMF_PROTECTION_WRITE = (1 << 2), ///< Memory allocations can be written. - UMF_PROTECTION_EXEC = (1 << 3), ///< Memory allocations can be executed. - /// @cond - UMF_PROTECTION_MAX // must be the last one - /// @endcond -} umf_mem_protection_flags_t; - -/// @brief Memory visibility mode -typedef enum umf_memory_visibility_t { - UMF_MEM_MAP_PRIVATE = 1, ///< private memory mapping - UMF_MEM_MAP_SHARED, ///< shared memory mapping (supported on Linux only) -} umf_memory_visibility_t; - /// @brief Memory binding mode /// Specifies how memory is bound to NUMA nodes on systems that support NUMA. /// Not every mode is supported on every system. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cabe71b2d..9eb883cfa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -130,7 +130,6 @@ set(UMF_SOURCES_COMMON_LINUX_MACOSX provider/provider_devdax_memory.c provider/provider_file_memory.c provider/provider_os_memory.c - provider/provider_os_memory_posix.c memtargets/memtarget_numa.c memspaces/memspace_numa.c memspaces/memspace_host_all.c @@ -139,17 +138,14 @@ set(UMF_SOURCES_COMMON_LINUX_MACOSX memspaces/memspace_lowest_latency.c) if(NOT UMF_DISABLE_HWLOC) - set(UMF_SOURCES_LINUX - ${UMF_SOURCES_LINUX} ${UMF_SOURCES_COMMON_LINUX_MACOSX} - provider/provider_os_memory_linux.c) + set(UMF_SOURCES_LINUX ${UMF_SOURCES_LINUX} + ${UMF_SOURCES_COMMON_LINUX_MACOSX}) - set(UMF_SOURCES_MACOSX - ${UMF_SOURCES_MACOSX} ${UMF_SOURCES_COMMON_LINUX_MACOSX} - provider/provider_os_memory_macosx.c) + set(UMF_SOURCES_MACOSX ${UMF_SOURCES_MACOSX} + ${UMF_SOURCES_COMMON_LINUX_MACOSX}) - set(UMF_SOURCES_WINDOWS - ${UMF_SOURCES_WINDOWS} provider/provider_os_memory.c - provider/provider_os_memory_windows.c) + set(UMF_SOURCES_WINDOWS ${UMF_SOURCES_WINDOWS} + provider/provider_os_memory.c) set(UMF_LIBS ${UMF_LIBS} ${LIBHWLOC_LIBRARIES}) @@ -180,7 +176,7 @@ set(UMF_PRIVATE_LIBRARY_DIRS ${UMF_PRIVATE_LIBRARY_DIRS} if(LINUX) set(UMF_SOURCES ${UMF_SOURCES} ${UMF_SOURCES_LINUX}) - set(UMF_LIBS ${UMF_LIBS} dl rt) # librt for shm_open() + set(UMF_LIBS ${UMF_LIBS} dl) elseif(WINDOWS) set(UMF_SOURCES ${UMF_SOURCES} ${UMF_SOURCES_WINDOWS}) diff --git a/src/provider/provider_devdax_memory.c b/src/provider/provider_devdax_memory.c index 0507463c0..321c68d9c 100644 --- a/src/provider/provider_devdax_memory.c +++ b/src/provider/provider_devdax_memory.c @@ -14,7 +14,6 @@ #include #include "base_alloc_global.h" -#include "provider_os_memory_internal.h" #include "utils_common.h" #include "utils_concurrency.h" #include "utils_log.h" @@ -76,8 +75,8 @@ devdax_translate_params(umf_devdax_memory_provider_params_t *in_params, devdax_memory_provider_t *provider) { umf_result_t result; - result = os_translate_mem_protection_flags(in_params->protection, - &provider->protection); + result = utils_translate_mem_protection_flags(in_params->protection, + &provider->protection); if (result != UMF_RESULT_SUCCESS) { LOG_ERR("incorrect memory protection flags: %u", in_params->protection); return result; @@ -124,15 +123,15 @@ static umf_result_t devdax_initialize(void *params, void **provider) { goto err_free_devdax_provider; } - int fd = os_devdax_open(in_params->path); + int fd = utils_devdax_open(in_params->path); if (fd == -1) { LOG_ERR("cannot open the device DAX: %s", in_params->path); ret = UMF_RESULT_ERROR_INVALID_ARGUMENT; goto err_free_devdax_provider; } - devdax_provider->base = os_devdax_mmap(NULL, devdax_provider->size, - devdax_provider->protection, fd); + devdax_provider->base = utils_devdax_mmap(NULL, devdax_provider->size, + devdax_provider->protection, fd); utils_close_fd(fd); if (devdax_provider->base == NULL) { LOG_PDEBUG("devdax memory mapping failed (path=%s, size=%zu)", @@ -155,7 +154,7 @@ static umf_result_t devdax_initialize(void *params, void **provider) { return UMF_RESULT_SUCCESS; err_unmap_devdax: - os_munmap(devdax_provider->base, devdax_provider->size); + utils_munmap(devdax_provider->base, devdax_provider->size); err_free_devdax_provider: umf_ba_global_free(devdax_provider); return ret; @@ -169,7 +168,7 @@ static void devdax_finalize(void *provider) { devdax_memory_provider_t *devdax_provider = provider; util_mutex_destroy_not_free(&devdax_provider->lock); - os_munmap(devdax_provider->base, devdax_provider->size); + utils_munmap(devdax_provider->base, devdax_provider->size); umf_ba_global_free(devdax_provider); } @@ -281,8 +280,8 @@ static void devdax_get_last_native_error(void *provider, const char **ppMessage, memcpy(TLS_last_native_error.msg_buff + pos, msg, len + 1); pos += len; - os_strerror(TLS_last_native_error.errno_value, - TLS_last_native_error.msg_buff + pos, TLS_MSG_BUF_LEN - pos); + utils_strerror(TLS_last_native_error.errno_value, + TLS_last_native_error.msg_buff + pos, TLS_MSG_BUF_LEN - pos); *ppMessage = TLS_last_native_error.msg_buff; } @@ -296,7 +295,7 @@ static umf_result_t devdax_get_recommended_page_size(void *provider, return UMF_RESULT_ERROR_INVALID_ARGUMENT; } - *page_size = os_get_page_size(); + *page_size = util_get_page_size(); return UMF_RESULT_SUCCESS; } @@ -324,7 +323,7 @@ static umf_result_t devdax_purge_force(void *provider, void *ptr, size_t size) { } errno = 0; - if (os_purge(ptr, size, UMF_PURGE_FORCE)) { + if (utils_purge(ptr, size, UMF_PURGE_FORCE)) { devdax_store_last_native_error( UMF_DEVDAX_RESULT_ERROR_PURGE_FORCE_FAILED, errno); LOG_PERR("force purging failed"); @@ -453,14 +452,14 @@ static umf_result_t devdax_open_ipc_handle(void *provider, } umf_result_t ret = UMF_RESULT_SUCCESS; - int fd = os_devdax_open(devdax_provider->path); + int fd = utils_devdax_open(devdax_provider->path); if (fd == -1) { LOG_PERR("opening a devdax (%s) failed", devdax_provider->path); return UMF_RESULT_ERROR_INVALID_ARGUMENT; } - char *base = os_devdax_mmap(NULL, devdax_provider->size, - devdax_provider->protection, fd); + char *base = utils_devdax_mmap(NULL, devdax_provider->size, + devdax_provider->protection, fd); if (base == NULL) { devdax_store_last_native_error(UMF_DEVDAX_RESULT_ERROR_ALLOC_FAILED, errno); @@ -493,7 +492,7 @@ static umf_result_t devdax_close_ipc_handle(void *provider, void *ptr, (devdax_memory_provider_t *)provider; errno = 0; - int ret = os_munmap(devdax_provider->base, devdax_provider->size); + int ret = utils_munmap(devdax_provider->base, devdax_provider->size); // ignore error when size == 0 if (ret && (size > 0)) { devdax_store_last_native_error(UMF_DEVDAX_RESULT_ERROR_FREE_FAILED, diff --git a/src/provider/provider_file_memory.c b/src/provider/provider_file_memory.c index b42be4526..0936daaf0 100644 --- a/src/provider/provider_file_memory.c +++ b/src/provider/provider_file_memory.c @@ -15,7 +15,6 @@ #include "base_alloc_global.h" #include "critnib.h" -#include "provider_os_memory_internal.h" #include "utils_common.h" #include "utils_concurrency.h" #include "utils_log.h" @@ -88,15 +87,15 @@ file_translate_params(umf_file_memory_provider_params_t *in_params, file_memory_provider_t *provider) { umf_result_t result; - result = os_translate_mem_protection_flags(in_params->protection, - &provider->protection); + result = utils_translate_mem_protection_flags(in_params->protection, + &provider->protection); if (result != UMF_RESULT_SUCCESS) { LOG_ERR("incorrect memory protection flags: %u", in_params->protection); return result; } - result = os_translate_mem_visibility_flag(in_params->visibility, - &provider->visibility); + result = utils_translate_mem_visibility_flag(in_params->visibility, + &provider->visibility); if (result != UMF_RESULT_SUCCESS) { LOG_ERR("incorrect memory visibility flag: %u", in_params->visibility); return result; @@ -115,7 +114,7 @@ static umf_result_t file_initialize(void *params, void **provider) { umf_file_memory_provider_params_t *in_params = (umf_file_memory_provider_params_t *)params; - size_t page_size = os_get_page_size(); + size_t page_size = util_get_page_size(); if (in_params->path == NULL) { LOG_ERR("file path is missing"); @@ -141,14 +140,14 @@ static umf_result_t file_initialize(void *params, void **provider) { goto err_free_file_provider; } - file_provider->fd = os_file_open_or_create(in_params->path); + file_provider->fd = utils_file_open_or_create(in_params->path); if (file_provider->fd == -1) { LOG_ERR("cannot open the file: %s", in_params->path); ret = UMF_RESULT_ERROR_INVALID_ARGUMENT; goto err_free_file_provider; } - if (os_set_file_size(file_provider->fd, page_size)) { + if (utils_set_file_size(file_provider->fd, page_size)) { LOG_ERR("cannot set size of the file: %s", in_params->path); ret = UMF_RESULT_ERROR_UNKNOWN; goto err_close_fd; @@ -207,7 +206,7 @@ static void file_finalize(void *provider) { void *rvalue = NULL; while (1 == critnib_find(file_provider->mmaps, key, FIND_G, &rkey, &rvalue)) { - os_munmap((void *)rkey, (size_t)rvalue); + utils_munmap((void *)rkey, (size_t)rvalue); critnib_remove(file_provider->mmaps, rkey); key = rkey; } @@ -248,7 +247,7 @@ static umf_result_t file_mmap_aligned(file_memory_provider_t *file_provider, } if (offset_fd + extended_size > size_fd) { - if (os_fallocate(fd, offset_fd, extended_size)) { + if (utils_fallocate(fd, offset_fd, extended_size)) { LOG_ERR("cannot grow the file size from %zu to %zu", size_fd, offset_fd + extended_size); return UMF_RESULT_ERROR_UNKNOWN; @@ -262,7 +261,7 @@ static umf_result_t file_mmap_aligned(file_memory_provider_t *file_provider, ASSERT_IS_ALIGNED(extended_size, page_size); ASSERT_IS_ALIGNED(offset_fd, page_size); - void *ptr = os_mmap(NULL, extended_size, prot, flag, fd, offset_fd); + void *ptr = utils_mmap(NULL, extended_size, prot, flag, fd, offset_fd); if (ptr == NULL) { LOG_PERR("memory mapping failed"); return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC; @@ -423,8 +422,8 @@ static void file_get_last_native_error(void *provider, const char **ppMessage, memcpy(TLS_last_native_error.msg_buff + pos, msg, len + 1); pos += len; - os_strerror(TLS_last_native_error.errno_value, - TLS_last_native_error.msg_buff + pos, TLS_MSG_BUF_LEN - pos); + utils_strerror(TLS_last_native_error.errno_value, + TLS_last_native_error.msg_buff + pos, TLS_MSG_BUF_LEN - pos); *ppMessage = TLS_last_native_error.msg_buff; } @@ -437,7 +436,7 @@ static umf_result_t file_get_recommended_page_size(void *provider, size_t size, return UMF_RESULT_ERROR_INVALID_ARGUMENT; } - *page_size = os_get_page_size(); + *page_size = util_get_page_size(); return UMF_RESULT_SUCCESS; } @@ -465,7 +464,7 @@ static umf_result_t file_purge_force(void *provider, void *ptr, size_t size) { } errno = 0; - if (os_purge(ptr, size, UMF_PURGE_FORCE)) { + if (utils_purge(ptr, size, UMF_PURGE_FORCE)) { file_store_last_native_error(UMF_FILE_RESULT_ERROR_PURGE_FORCE_FAILED, errno); LOG_PERR("force purging failed"); @@ -606,15 +605,15 @@ static umf_result_t file_open_ipc_handle(void *provider, void *providerIpcData, return UMF_RESULT_ERROR_INVALID_ARGUMENT; } - fd = os_file_open(file_ipc_data->path); + fd = utils_file_open(file_ipc_data->path); if (fd == -1) { LOG_PERR("opening the file to be mapped (%s) failed", file_ipc_data->path); return UMF_RESULT_ERROR_INVALID_ARGUMENT; } - *ptr = os_mmap(NULL, file_ipc_data->size, file_provider->protection, - file_provider->visibility, fd, file_ipc_data->offset_fd); + *ptr = utils_mmap(NULL, file_ipc_data->size, file_provider->protection, + file_provider->visibility, fd, file_ipc_data->offset_fd); (void)utils_close_fd(fd); if (*ptr == NULL) { file_store_last_native_error(UMF_FILE_RESULT_ERROR_ALLOC_FAILED, errno); @@ -632,7 +631,7 @@ static umf_result_t file_close_ipc_handle(void *provider, void *ptr, } errno = 0; - int ret = os_munmap(ptr, size); + int ret = utils_munmap(ptr, size); // ignore error when size == 0 if (ret && (size > 0)) { file_store_last_native_error(UMF_FILE_RESULT_ERROR_FREE_FAILED, errno); diff --git a/src/provider/provider_os_memory.c b/src/provider/provider_os_memory.c index 00251e53b..fe2505dce 100644 --- a/src/provider/provider_os_memory.c +++ b/src/provider/provider_os_memory.c @@ -134,31 +134,6 @@ static umf_result_t initialize_nodeset(os_memory_provider_t *os_provider, return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY; } -umf_result_t os_translate_flags(unsigned in_flags, unsigned max, - umf_result_t (*translate_flag)(unsigned, - unsigned *), - unsigned *out_flags) { - unsigned out_f = 0; - for (unsigned n = 1; n < max; n <<= 1) { - if (in_flags & n) { - unsigned flag; - umf_result_t result = translate_flag(n, &flag); - if (result != UMF_RESULT_SUCCESS) { - return result; - } - out_f |= flag; - in_flags &= ~n; // clear this bit - } - } - - if (in_flags != 0) { - return UMF_RESULT_ERROR_INVALID_ARGUMENT; - } - - *out_flags = out_f; - return UMF_RESULT_SUCCESS; -} - static umf_result_t validate_numa_mode(umf_numa_mode_t mode, int nodemaskEmpty) { switch (mode) { @@ -289,7 +264,7 @@ create_fd_for_mmap(umf_os_memory_provider_params_t *in_params, /* create a new shared memory file */ provider->fd = - os_shm_create(in_params->shm_name, provider->max_size_fd); + utils_shm_create(in_params->shm_name, provider->max_size_fd); if (provider->fd == -1) { LOG_ERR("creating a shared memory file /dev/shm/%s of size %zu for " "memory mapping failed", @@ -304,14 +279,14 @@ create_fd_for_mmap(umf_os_memory_provider_params_t *in_params, return UMF_RESULT_SUCCESS; } - provider->fd = os_create_anonymous_fd(); + provider->fd = utils_create_anonymous_fd(); if (provider->fd <= 0) { LOG_ERR( "creating an anonymous file descriptor for memory mapping failed"); return UMF_RESULT_ERROR_UNKNOWN; } - int ret = os_set_file_size(provider->fd, provider->max_size_fd); + int ret = utils_set_file_size(provider->fd, provider->max_size_fd); if (ret) { LOG_ERR("setting size %zu of an anonymous file failed", provider->max_size_fd); @@ -413,15 +388,15 @@ static umf_result_t translate_params(umf_os_memory_provider_params_t *in_params, os_memory_provider_t *provider) { umf_result_t result; - result = os_translate_mem_protection_flags(in_params->protection, - &provider->protection); + result = utils_translate_mem_protection_flags(in_params->protection, + &provider->protection); if (result != UMF_RESULT_SUCCESS) { LOG_ERR("incorrect memory protection flags: %u", in_params->protection); return result; } - result = os_translate_mem_visibility_flag(in_params->visibility, - &provider->visibility); + result = utils_translate_mem_visibility_flag(in_params->visibility, + &provider->visibility); if (result != UMF_RESULT_SUCCESS) { LOG_ERR("incorrect memory visibility flag: %u", in_params->visibility); return result; @@ -634,11 +609,11 @@ static inline void assert_is_page_aligned(uintptr_t ptr, size_t page_size) { (void)page_size; // unused in Release build } -static int os_mmap_aligned(void *hint_addr, size_t length, size_t alignment, - size_t page_size, int prot, int flag, int fd, - size_t max_fd_size, os_mutex_t *lock_fd, - void **out_addr, size_t *fd_size, - size_t *fd_offset) { +static int utils_mmap_aligned(void *hint_addr, size_t length, size_t alignment, + size_t page_size, int prot, int flag, int fd, + size_t max_fd_size, os_mutex_t *lock_fd, + void **out_addr, size_t *fd_size, + size_t *fd_offset) { assert(out_addr); size_t extended_length = length; @@ -670,7 +645,8 @@ static int os_mmap_aligned(void *hint_addr, size_t length, size_t alignment, util_mutex_unlock(lock_fd); } - void *ptr = os_mmap(hint_addr, extended_length, prot, flag, fd, *fd_offset); + void *ptr = + utils_mmap(hint_addr, extended_length, prot, flag, fd, *fd_offset); if (ptr == NULL) { LOG_PDEBUG("memory mapping failed"); return -1; @@ -689,7 +665,7 @@ static int os_mmap_aligned(void *hint_addr, size_t length, size_t alignment, size_t head_len = aligned_addr - addr; if (head_len > 0) { - os_munmap(ptr, head_len); + utils_munmap(ptr, head_len); } // tail address has to page-aligned @@ -703,7 +679,7 @@ static int os_mmap_aligned(void *hint_addr, size_t length, size_t alignment, size_t tail_len = (addr + extended_length) - tail; if (tail_len > 0) { - os_munmap((void *)tail, tail_len); + utils_munmap((void *)tail, tail_len); } *out_addr = (void *)aligned_addr; @@ -917,7 +893,7 @@ static umf_result_t os_alloc(void *provider, size_t size, size_t alignment, void *addr = NULL; errno = 0; - ret = os_mmap_aligned( + ret = utils_mmap_aligned( NULL, size, alignment, page_size, os_provider->protection, os_provider->visibility, os_provider->fd, os_provider->max_size_fd, &os_provider->lock_fd, &addr, &os_provider->size_fd, &fd_offset); @@ -984,7 +960,7 @@ static umf_result_t os_alloc(void *provider, size_t size, size_t alignment, return UMF_RESULT_SUCCESS; err_unmap: - (void)os_munmap(addr, size); + (void)utils_munmap(addr, size); return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC; } @@ -1004,7 +980,7 @@ static umf_result_t os_free(void *provider, void *ptr, size_t size) { } errno = 0; - int ret = os_munmap(ptr, size); + int ret = utils_munmap(ptr, size); if (ret) { os_store_last_native_error(UMF_OS_RESULT_ERROR_FREE_FAILED, errno); LOG_PERR("memory deallocation failed"); @@ -1044,8 +1020,8 @@ static void os_get_last_native_error(void *provider, const char **ppMessage, memcpy(TLS_last_native_error.msg_buff + pos, msg, len + 1); pos += len; - os_strerror(TLS_last_native_error.errno_value, - TLS_last_native_error.msg_buff + pos, TLS_MSG_BUF_LEN - pos); + utils_strerror(TLS_last_native_error.errno_value, + TLS_last_native_error.msg_buff + pos, TLS_MSG_BUF_LEN - pos); *ppMessage = TLS_last_native_error.msg_buff; } @@ -1058,7 +1034,7 @@ static umf_result_t os_get_recommended_page_size(void *provider, size_t size, return UMF_RESULT_ERROR_INVALID_ARGUMENT; } - *page_size = os_get_page_size(); + *page_size = util_get_page_size(); return UMF_RESULT_SUCCESS; } @@ -1076,7 +1052,7 @@ static umf_result_t os_purge_lazy(void *provider, void *ptr, size_t size) { } errno = 0; - if (os_purge(ptr, size, UMF_PURGE_LAZY)) { + if (utils_purge(ptr, size, UMF_PURGE_LAZY)) { os_store_last_native_error(UMF_OS_RESULT_ERROR_PURGE_LAZY_FAILED, errno); LOG_PERR("lazy purging failed"); @@ -1092,7 +1068,7 @@ static umf_result_t os_purge_force(void *provider, void *ptr, size_t size) { } errno = 0; - if (os_purge(ptr, size, UMF_PURGE_FORCE)) { + if (utils_purge(ptr, size, UMF_PURGE_FORCE)) { os_store_last_native_error(UMF_OS_RESULT_ERROR_PURGE_FORCE_FAILED, errno); LOG_PERR("force purging failed"); @@ -1258,13 +1234,13 @@ static umf_result_t os_open_ipc_handle(void *provider, void *providerIpcData, int fd; if (os_provider->shm_name[0]) { - fd = os_shm_open(os_provider->shm_name); + fd = utils_shm_open(os_provider->shm_name); if (fd <= 0) { LOG_PERR("opening a shared memory file (%s) failed", os_provider->shm_name); return UMF_RESULT_ERROR_UNKNOWN; } - (void)os_shm_unlink(os_provider->shm_name); + (void)utils_shm_unlink(os_provider->shm_name); } else { umf_result_t umf_result = utils_duplicate_fd(os_ipc_data->pid, os_ipc_data->fd, &fd); @@ -1274,8 +1250,8 @@ static umf_result_t os_open_ipc_handle(void *provider, void *providerIpcData, } } - *ptr = os_mmap(NULL, os_ipc_data->size, os_provider->protection, - os_provider->visibility, fd, os_ipc_data->fd_offset); + *ptr = utils_mmap(NULL, os_ipc_data->size, os_provider->protection, + os_provider->visibility, fd, os_ipc_data->fd_offset); if (*ptr == NULL) { os_store_last_native_error(UMF_OS_RESULT_ERROR_ALLOC_FAILED, errno); LOG_PERR("memory mapping failed"); @@ -1294,7 +1270,7 @@ static umf_result_t os_close_ipc_handle(void *provider, void *ptr, } errno = 0; - int ret = os_munmap(ptr, size); + int ret = utils_munmap(ptr, size); // ignore error when size == 0 if (ret && (size > 0)) { os_store_last_native_error(UMF_OS_RESULT_ERROR_FREE_FAILED, errno); diff --git a/src/provider/provider_os_memory_internal.h b/src/provider/provider_os_memory_internal.h index 54972686d..e01a3de75 100644 --- a/src/provider/provider_os_memory_internal.h +++ b/src/provider/provider_os_memory_internal.h @@ -26,11 +26,6 @@ extern "C" { #endif -typedef enum umf_purge_advise_t { - UMF_PURGE_LAZY, - UMF_PURGE_FORCE, -} umf_purge_advise_t; - typedef struct os_memory_provider_t { unsigned protection; // combination of OS-specific protection flags unsigned visibility; // memory visibility mode @@ -69,52 +64,6 @@ typedef struct os_memory_provider_t { hwloc_topology_t topo; } os_memory_provider_t; -umf_result_t os_translate_flags(unsigned in_flags, unsigned max, - umf_result_t (*translate_flag)(unsigned, - unsigned *), - unsigned *out_flags); - -umf_result_t os_translate_mem_protection_flags(unsigned in_protection, - unsigned *out_protection); - -umf_result_t os_translate_mem_visibility_flag(umf_memory_visibility_t in_flag, - unsigned *out_flag); - -int os_create_anonymous_fd(void); - -int os_shm_create(const char *shm_name, size_t size); - -int os_shm_open(const char *shm_name); - -int os_shm_unlink(const char *shm_name); - -size_t get_max_file_size(void); - -int os_get_file_size(int fd, size_t *size); - -int os_set_file_size(int fd, size_t size); - -void *os_mmap(void *hint_addr, size_t length, int prot, int flag, int fd, - size_t fd_offset); - -void *os_devdax_mmap(void *hint_addr, size_t length, int prot, int fd); - -int os_munmap(void *addr, size_t length); - -int os_purge(void *addr, size_t length, int advice); - -size_t os_get_page_size(void); - -void os_strerror(int errnum, char *buf, size_t buflen); - -int os_devdax_open(const char *path); - -int os_file_open(const char *path); - -int os_file_open_or_create(const char *path); - -int os_fallocate(int fd, long offset, long len); - #ifdef __cplusplus } #endif diff --git a/src/provider/provider_os_memory_posix.c b/src/provider/provider_os_memory_posix.c deleted file mode 100644 index 90348ebfa..000000000 --- a/src/provider/provider_os_memory_posix.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2023-2024 Intel Corporation - * - * Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "provider_os_memory_internal.h" -#include "utils_log.h" -#include "utils_sanitizers.h" - -// maximum value of the off_t type -#define OFF_T_MAX \ - (sizeof(off_t) == sizeof(long long) \ - ? LLONG_MAX \ - : (sizeof(off_t) == sizeof(long) ? LONG_MAX : INT_MAX)) - -umf_result_t os_translate_mem_protection_one_flag(unsigned in_protection, - unsigned *out_protection) { - switch (in_protection) { - case UMF_PROTECTION_NONE: - *out_protection = PROT_NONE; - return UMF_RESULT_SUCCESS; - case UMF_PROTECTION_READ: - *out_protection = PROT_READ; - return UMF_RESULT_SUCCESS; - case UMF_PROTECTION_WRITE: - *out_protection = PROT_WRITE; - return UMF_RESULT_SUCCESS; - case UMF_PROTECTION_EXEC: - *out_protection = PROT_EXEC; - return UMF_RESULT_SUCCESS; - } - return UMF_RESULT_ERROR_INVALID_ARGUMENT; -} - -size_t get_max_file_size(void) { return OFF_T_MAX; } - -umf_result_t os_translate_mem_protection_flags(unsigned in_protection, - unsigned *out_protection) { - // translate protection - combination of 'umf_mem_protection_flags_t' flags - return os_translate_flags(in_protection, UMF_PROTECTION_MAX, - os_translate_mem_protection_one_flag, - out_protection); -} - -static int os_translate_purge_advise(umf_purge_advise_t advise) { - switch (advise) { - case UMF_PURGE_LAZY: - return MADV_FREE; - case UMF_PURGE_FORCE: - return MADV_DONTNEED; - } - return -1; -} - -void *os_mmap(void *hint_addr, size_t length, int prot, int flag, int fd, - size_t fd_offset) { - fd = (fd == 0) ? -1 : fd; - if (fd == -1) { - // MAP_ANONYMOUS - the mapping is not backed by any file - flag |= MAP_ANONYMOUS; - } - - void *ptr = mmap(hint_addr, length, prot, flag, fd, fd_offset); - if (ptr == MAP_FAILED) { - return NULL; - } - // this should be unnecessary but pairs of mmap/munmap do not reset - // asan's user-poisoning flags, leading to invalid error reports - // Bug 81619: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81619 - utils_annotate_memory_defined(ptr, length); - return ptr; -} - -int os_munmap(void *addr, size_t length) { - // this should be unnecessary but pairs of mmap/munmap do not reset - // asan's user-poisoning flags, leading to invalid error reports - // Bug 81619: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81619 - utils_annotate_memory_defined(addr, length); - return munmap(addr, length); -} - -size_t os_get_page_size(void) { return sysconf(_SC_PAGE_SIZE); } - -int os_purge(void *addr, size_t length, int advice) { - return madvise(addr, length, os_translate_purge_advise(advice)); -} - -void os_strerror(int errnum, char *buf, size_t buflen) { -// 'strerror_r' implementation is XSI-compliant (returns 0 on success) -#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE - if (strerror_r(errnum, buf, buflen)) { -#else // 'strerror_r' implementation is GNU-specific (returns pointer on success) - if (!strerror_r(errnum, buf, buflen)) { -#endif - LOG_PERR("Retrieving error code description failed"); - } -} - -// open a devdax -int os_devdax_open(const char *path) { - if (path == NULL) { - LOG_ERR("empty path"); - return -1; - } - - if (strstr(path, "/dev/dax") != path) { - LOG_ERR("path of the file \"%s\" does not start with \"/dev/dax\"", - path); - return -1; - } - - int fd = open(path, O_RDWR); - if (fd == -1) { - LOG_PERR("cannot open the file: %s", path); - return -1; - } - - struct stat statbuf; - int ret = stat(path, &statbuf); - if (ret) { - LOG_PERR("stat(%s) failed", path); - close(fd); - return -1; - } - - if (!S_ISCHR(statbuf.st_mode)) { - LOG_ERR("file %s is not a character device", path); - close(fd); - return -1; - } - - return fd; -} - -// open a file -int os_file_open(const char *path) { - if (!path) { - LOG_ERR("empty path"); - return -1; - } - - int fd = open(path, O_RDWR); - if (fd == -1) { - LOG_PERR("cannot open the file: %s", path); - } - - return fd; -} - -// open a file or create -int os_file_open_or_create(const char *path) { - if (!path) { - LOG_ERR("empty path"); - return -1; - } - - int fd = open(path, O_RDWR | O_CREAT, 0600); - if (fd == -1) { - LOG_PERR("cannot open/create the file: %s", path); - return -1; - } - - LOG_DEBUG("opened/created the file: %s", path); - - return fd; -} diff --git a/src/provider/provider_os_memory_windows.c b/src/provider/provider_os_memory_windows.c deleted file mode 100644 index b295c75f1..000000000 --- a/src/provider/provider_os_memory_windows.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2024 Intel Corporation - * - * Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -*/ - -#include - -#include -#include -#include -#include - -#include - -#include "utils_concurrency.h" -#include "utils_log.h" - -static UTIL_ONCE_FLAG Page_size_is_initialized = UTIL_ONCE_FLAG_INIT; -static size_t Page_size; - -umf_result_t os_translate_mem_protection_flags(unsigned in_protection, - unsigned *out_protection) { - switch (in_protection) { - case UMF_PROTECTION_NONE: - *out_protection = PAGE_NOACCESS; - return UMF_RESULT_SUCCESS; - case UMF_PROTECTION_EXEC: - *out_protection = PAGE_EXECUTE; - return UMF_RESULT_SUCCESS; - case (UMF_PROTECTION_EXEC | UMF_PROTECTION_READ): - *out_protection = PAGE_EXECUTE_READ; - return UMF_RESULT_SUCCESS; - case (UMF_PROTECTION_EXEC | UMF_PROTECTION_READ | UMF_PROTECTION_WRITE): - *out_protection = PAGE_EXECUTE_READWRITE; - return UMF_RESULT_SUCCESS; - case (UMF_PROTECTION_EXEC | UMF_PROTECTION_WRITE): - *out_protection = PAGE_EXECUTE_WRITECOPY; - return UMF_RESULT_SUCCESS; - case UMF_PROTECTION_READ: - *out_protection = PAGE_READONLY; - return UMF_RESULT_SUCCESS; - case (UMF_PROTECTION_READ | UMF_PROTECTION_WRITE): - *out_protection = PAGE_READWRITE; - return UMF_RESULT_SUCCESS; - case UMF_PROTECTION_WRITE: - *out_protection = PAGE_WRITECOPY; - return UMF_RESULT_SUCCESS; - } - LOG_ERR("os_translate_mem_protection_flags(): unsupported protection flag: " - "%u", - in_protection); - return UMF_RESULT_ERROR_INVALID_ARGUMENT; -} - -umf_result_t os_translate_mem_visibility_flag(umf_memory_visibility_t in_flag, - unsigned *out_flag) { - switch (in_flag) { - case UMF_MEM_MAP_PRIVATE: - *out_flag = 0; // ignored on Windows - return UMF_RESULT_SUCCESS; - case UMF_MEM_MAP_SHARED: - return UMF_RESULT_ERROR_NOT_SUPPORTED; // not supported on Windows yet - } - return UMF_RESULT_ERROR_INVALID_ARGUMENT; -} - -// create a shared memory file -int os_shm_create(const char *shm_name, size_t size) { - (void)shm_name; // unused - (void)size; // unused - return 0; // ignored on Windows -} - -// open a shared memory file -int os_shm_open(const char *shm_name) { - (void)shm_name; // unused - return 0; // ignored on Windows -} - -// unlink a shared memory file -int os_shm_unlink(const char *shm_name) { - (void)shm_name; // unused - return 0; // ignored on Windows -} - -int os_create_anonymous_fd(void) { - return 0; // ignored on Windows -} - -size_t get_max_file_size(void) { return SIZE_MAX; } - -int os_get_file_size(int fd, size_t *size) { - (void)fd; // unused - (void)size; // unused - return -1; // not supported on Windows -} - -int os_set_file_size(int fd, size_t size) { - (void)fd; // unused - (void)size; // unused - return 0; // ignored on Windows -} - -void *os_mmap(void *hint_addr, size_t length, int prot, int flag, int fd, - size_t fd_offset) { - (void)flag; // ignored on Windows - (void)fd; // ignored on Windows - (void)fd_offset; // ignored on Windows - return VirtualAlloc(hint_addr, length, MEM_RESERVE | MEM_COMMIT, prot); -} - -void *os_devdax_mmap(void *hint_addr, size_t length, int prot, int fd) { - (void)hint_addr; // unused - (void)length; // unused - (void)prot; // unused - (void)fd; // unused - return NULL; // not supported on Windows -} - -int os_munmap(void *addr, size_t length) { - // If VirtualFree() succeeds, the return value is nonzero. - // If VirtualFree() fails, the return value is 0 (zero). - (void)length; // unused - return (VirtualFree(addr, 0, MEM_RELEASE) == 0); -} - -int os_purge(void *addr, size_t length, int advice) { - // If VirtualFree() succeeds, the return value is nonzero. - // If VirtualFree() fails, the return value is 0 (zero). - (void)advice; // unused - - // temporarily disable the C6250 warning as we intentionally use the - // MEM_DECOMMIT flag only -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable : 6250) -#endif // _MSC_VER - - return (VirtualFree(addr, length, MEM_DECOMMIT) == 0); - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif // _MSC_VER -} - -static void _os_get_page_size(void) { - SYSTEM_INFO SystemInfo; - GetSystemInfo(&SystemInfo); - Page_size = SystemInfo.dwPageSize; -} - -size_t os_get_page_size(void) { - util_init_once(&Page_size_is_initialized, _os_get_page_size); - return Page_size; -} - -void os_strerror(int errnum, char *buf, size_t buflen) { - strerror_s(buf, buflen, errnum); -} - -// open a devdax -int os_devdax_open(const char *path) { - (void)path; // unused - - return -1; -} - -// open a file -int os_file_open(const char *path) { - (void)path; // unused - - return -1; -} - -// open a file or create -int os_file_open_or_create(const char *path) { - (void)path; // unused - - return -1; -} - -int os_fallocate(int fd, long offset, long len) { - (void)fd; // unused - (void)offset; // unused - (void)len; // unused - - return -1; -} diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index c7a285ce2..a0bff39fd 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -10,6 +10,10 @@ set(UMF_UTILS_SOURCES_COMMON utils_common.c utils_log.c utils_load_library.c) set(UMF_UTILS_SOURCES_POSIX utils_posix_common.c utils_posix_concurrency.c utils_posix_math.c) +set(UMF_UTILS_SOURCES_LINUX utils_linux_common.c) + +set(UMF_UTILS_SOURCES_MACOSX utils_macosx_common.c) + set(UMF_UTILS_SOURCES_WINDOWS utils_windows_common.c utils_windows_concurrency.c utils_windows_math.c) @@ -33,6 +37,13 @@ if(LINUX OR MACOSX) set(UMF_UTILS_SOURCES ${UMF_UTILS_SOURCES_COMMON} ${UMF_UTILS_SOURCES_POSIX}) set(UMF_UTILS_LIBS dl) + + if(LINUX) + set(UMF_UTILS_SOURCES ${UMF_UTILS_SOURCES} ${UMF_UTILS_SOURCES_LINUX}) + set(UMF_UTILS_LIBS ${UMF_UTILS_LIBS} rt) # librt for shm_open() + elseif(MACOSX) + set(UMF_UTILS_SOURCES ${UMF_UTILS_SOURCES} ${UMF_UTILS_SOURCES_MACOSX}) + endif() elseif(WINDOWS) set(UMF_UTILS_SOURCES ${UMF_UTILS_SOURCES_COMMON} ${UMF_UTILS_SOURCES_WINDOWS}) diff --git a/src/utils/utils_common.c b/src/utils/utils_common.c index e94126b33..5ae1be3a1 100644 --- a/src/utils/utils_common.c +++ b/src/utils/utils_common.c @@ -91,3 +91,28 @@ int util_copy_path(const char *in_path, char out_path[], size_t path_max) { return 0; } + +umf_result_t utils_translate_flags(unsigned in_flags, unsigned max, + umf_result_t (*translate_flag)(unsigned, + unsigned *), + unsigned *out_flags) { + unsigned out_f = 0; + for (unsigned n = 1; n < max; n <<= 1) { + if (in_flags & n) { + unsigned flag; + umf_result_t result = translate_flag(n, &flag); + if (result != UMF_RESULT_SUCCESS) { + return result; + } + out_f |= flag; + in_flags &= ~n; // clear this bit + } + } + + if (in_flags != 0) { + return UMF_RESULT_ERROR_INVALID_ARGUMENT; + } + + *out_flags = out_f; + return UMF_RESULT_SUCCESS; +} diff --git a/src/utils/utils_common.h b/src/utils/utils_common.h index 20206b1e4..a9796415f 100644 --- a/src/utils/utils_common.h +++ b/src/utils/utils_common.h @@ -15,11 +15,17 @@ #include #include +#include #ifdef __cplusplus extern "C" { #endif +typedef enum umf_purge_advise_t { + UMF_PURGE_LAZY, + UMF_PURGE_FORCE, +} umf_purge_advise_t; + #define DO_WHILE_EMPTY \ do { \ } while (0) @@ -89,6 +95,51 @@ umf_result_t utils_duplicate_fd(int pid, int fd_in, int *fd_out); int util_copy_path(const char *in_path, char out_path[], size_t path_max); +umf_result_t utils_translate_flags(unsigned in_flags, unsigned max, + umf_result_t (*translate_flag)(unsigned, + unsigned *), + unsigned *out_flags); + +umf_result_t utils_translate_mem_protection_flags(unsigned in_protection, + unsigned *out_protection); + +umf_result_t +utils_translate_mem_visibility_flag(umf_memory_visibility_t in_flag, + unsigned *out_flag); + +int utils_create_anonymous_fd(void); + +int utils_shm_create(const char *shm_name, size_t size); + +int utils_shm_open(const char *shm_name); + +int utils_shm_unlink(const char *shm_name); + +size_t get_max_file_size(void); + +int utils_get_file_size(int fd, size_t *size); + +int utils_set_file_size(int fd, size_t size); + +void *utils_mmap(void *hint_addr, size_t length, int prot, int flag, int fd, + size_t fd_offset); + +void *utils_devdax_mmap(void *hint_addr, size_t length, int prot, int fd); + +int utils_munmap(void *addr, size_t length); + +int utils_purge(void *addr, size_t length, int advice); + +void utils_strerror(int errnum, char *buf, size_t buflen); + +int utils_devdax_open(const char *path); + +int utils_file_open(const char *path); + +int utils_file_open_or_create(const char *path); + +int utils_fallocate(int fd, long offset, long len); + #ifdef __cplusplus } #endif diff --git a/src/provider/provider_os_memory_linux.c b/src/utils/utils_linux_common.c similarity index 82% rename from src/provider/provider_os_memory_linux.c rename to src/utils/utils_linux_common.c index 9a90e1145..1ee5cccc8 100644 --- a/src/provider/provider_os_memory_linux.c +++ b/src/utils/utils_linux_common.c @@ -1,9 +1,11 @@ /* + * * Copyright (C) 2023-2024 Intel Corporation * * Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -*/ + * + */ #include #include @@ -13,13 +15,15 @@ #include #include -#include +#include +#include -#include "provider_os_memory_internal.h" +#include "utils_common.h" #include "utils_log.h" -umf_result_t os_translate_mem_visibility_flag(umf_memory_visibility_t in_flag, - unsigned *out_flag) { +umf_result_t +utils_translate_mem_visibility_flag(umf_memory_visibility_t in_flag, + unsigned *out_flag) { switch (in_flag) { case UMF_MEM_MAP_PRIVATE: *out_flag = MAP_PRIVATE; @@ -31,8 +35,60 @@ umf_result_t os_translate_mem_visibility_flag(umf_memory_visibility_t in_flag, return UMF_RESULT_ERROR_INVALID_ARGUMENT; } +/* + * MMap a /dev/dax device. + * First try to mmap with (MAP_SHARED_VALIDATE | MAP_SYNC) flags + * which allows flushing from the user-space. If MAP_SYNC fails + * try to mmap with MAP_SHARED flag (without MAP_SYNC). + */ +void *utils_devdax_mmap(void *hint_addr, size_t length, int prot, int fd) { + void *ptr = utils_mmap(hint_addr, length, prot, + MAP_SHARED_VALIDATE | MAP_SYNC, fd, 0); + if (ptr) { + LOG_DEBUG( + "devdax mapped with the (MAP_SHARED_VALIDATE | MAP_SYNC) flags"); + return ptr; + } + + ptr = utils_mmap(hint_addr, length, prot, MAP_SHARED, fd, 0); + if (ptr) { + LOG_DEBUG("devdax mapped with the MAP_SHARED flag"); + return ptr; + } + + return NULL; +} + +int utils_get_file_size(int fd, size_t *size) { + struct stat statbuf; + int ret = fstat(fd, &statbuf); + if (ret) { + LOG_PERR("fstat(%i) failed", fd); + return ret; + } + + *size = statbuf.st_size; + return 0; +} + +int utils_set_file_size(int fd, size_t size) { + errno = 0; + int ret = ftruncate(fd, size); + if (ret) { + LOG_PERR("setting size %zu of a file failed", size); + } else { + LOG_DEBUG("set size of a file to %zu bytes", size); + } + + return ret; +} + +int utils_fallocate(int fd, long offset, long len) { + return posix_fallocate(fd, offset, len); +} + // create a shared memory file -int os_shm_create(const char *shm_name, size_t size) { +int utils_shm_create(const char *shm_name, size_t size) { if (shm_name == NULL) { LOG_ERR("empty name of a shared memory file"); return -1; @@ -46,7 +102,7 @@ int os_shm_create(const char *shm_name, size_t size) { return fd; } - int ret = os_set_file_size(fd, size); + int ret = utils_set_file_size(fd, size); if (ret) { LOG_ERR("setting size (%zu) of a file /dev/shm/%s failed", size, shm_name); @@ -59,7 +115,7 @@ int os_shm_create(const char *shm_name, size_t size) { } // open a shared memory file -int os_shm_open(const char *shm_name) { +int utils_shm_open(const char *shm_name) { if (shm_name == NULL) { LOG_ERR("empty name of a shared memory file"); return -1; @@ -74,7 +130,7 @@ int os_shm_open(const char *shm_name) { } // unlink a shared memory file -int os_shm_unlink(const char *shm_name) { return shm_unlink(shm_name); } +int utils_shm_unlink(const char *shm_name) { return shm_unlink(shm_name); } static int syscall_memfd_secret(void) { int fd = -1; @@ -109,7 +165,7 @@ static int syscall_memfd_create(void) { } // create an anonymous file descriptor -int os_create_anonymous_fd(void) { +int utils_create_anonymous_fd(void) { int fd = -1; if (!util_env_var_has_str("UMF_MEM_FD_FUNC", "memfd_create")) { @@ -133,55 +189,3 @@ int os_create_anonymous_fd(void) { return fd; } - -int os_get_file_size(int fd, size_t *size) { - struct stat statbuf; - int ret = fstat(fd, &statbuf); - if (ret) { - LOG_PERR("fstat(%i) failed", fd); - return ret; - } - - *size = statbuf.st_size; - return 0; -} - -int os_set_file_size(int fd, size_t size) { - errno = 0; - int ret = ftruncate(fd, size); - if (ret) { - LOG_PERR("setting size %zu of a file failed", size); - } else { - LOG_DEBUG("set size of a file to %zu bytes", size); - } - - return ret; -} - -/* - * MMap a /dev/dax device. - * First try to mmap with (MAP_SHARED_VALIDATE | MAP_SYNC) flags - * which allows flushing from the user-space. If MAP_SYNC fails - * try to mmap with MAP_SHARED flag (without MAP_SYNC). - */ -void *os_devdax_mmap(void *hint_addr, size_t length, int prot, int fd) { - void *ptr = - os_mmap(hint_addr, length, prot, MAP_SHARED_VALIDATE | MAP_SYNC, fd, 0); - if (ptr) { - LOG_DEBUG( - "devdax mapped with the (MAP_SHARED_VALIDATE | MAP_SYNC) flags"); - return ptr; - } - - ptr = os_mmap(hint_addr, length, prot, MAP_SHARED, fd, 0); - if (ptr) { - LOG_DEBUG("devdax mapped with the MAP_SHARED flag"); - return ptr; - } - - return NULL; -} - -int os_fallocate(int fd, long offset, long len) { - return posix_fallocate(fd, offset, len); -} diff --git a/src/provider/provider_os_memory_macosx.c b/src/utils/utils_macosx_common.c similarity index 56% rename from src/provider/provider_os_memory_macosx.c rename to src/utils/utils_macosx_common.c index 33835beac..1ab5c4c85 100644 --- a/src/provider/provider_os_memory_macosx.c +++ b/src/utils/utils_macosx_common.c @@ -1,17 +1,60 @@ /* + * * Copyright (C) 2023-2024 Intel Corporation * * Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -*/ + * + */ #include -#include +#include +#include -#include "provider_os_memory_internal.h" #include "utils_log.h" +umf_result_t +utils_translate_mem_visibility_flag(umf_memory_visibility_t in_flag, + unsigned *out_flag) { + switch (in_flag) { + case UMF_MEM_MAP_PRIVATE: + *out_flag = MAP_PRIVATE; + return UMF_RESULT_SUCCESS; + case UMF_MEM_MAP_SHARED: + return UMF_RESULT_ERROR_NOT_SUPPORTED; // not supported on MacOSX + } + return UMF_RESULT_ERROR_INVALID_ARGUMENT; +} + +void *utils_devdax_mmap(void *hint_addr, size_t length, int prot, int fd) { + (void)hint_addr; // unused + (void)length; // unused + (void)prot; // unused + (void)fd; // unused + return NULL; // not supported +} + +int utils_get_file_size(int fd, size_t *size) { + (void)fd; // unused + (void)size; // unused + return -1; // not supported on MacOSX +} + +int utils_set_file_size(int fd, size_t size) { + (void)fd; // unused + (void)size; // unused + return 0; // ignored on MacOSX +} + +int utils_fallocate(int fd, long offset, long len) { + (void)fd; // unused + (void)offset; // unused + (void)len; // unused + + return -1; +} + umf_result_t os_translate_mem_visibility_flag(umf_memory_visibility_t in_flag, unsigned *out_flag) { switch (in_flag) { @@ -25,26 +68,26 @@ umf_result_t os_translate_mem_visibility_flag(umf_memory_visibility_t in_flag, } // create a shared memory file -int os_shm_create(const char *shm_name, size_t size) { +int utils_shm_create(const char *shm_name, size_t size) { (void)shm_name; // unused (void)size; // unused return 0; // ignored on MacOSX } // open a shared memory file -int os_shm_open(const char *shm_name) { +int utils_shm_open(const char *shm_name) { (void)shm_name; // unused return 0; // ignored on MacOSX } // unlink a shared memory file -int os_shm_unlink(const char *shm_name) { +int utils_shm_unlink(const char *shm_name) { (void)shm_name; // unused return 0; // ignored on MacOSX } // create an anonymous file descriptor -int os_create_anonymous_fd(void) { +int utils_create_anonymous_fd(void) { return 0; // ignored on MacOSX } diff --git a/src/utils/utils_posix_common.c b/src/utils/utils_posix_common.c index 51049e613..42a5d06f1 100644 --- a/src/utils/utils_posix_common.c +++ b/src/utils/utils_posix_common.c @@ -8,14 +8,20 @@ */ #include +#include +#include #include #include +#include +#include #include +#include #include #include "utils_common.h" #include "utils_concurrency.h" #include "utils_log.h" +#include "utils_sanitizers.h" #ifndef __NR_pidfd_open #define __NR_pidfd_open 434 /* Syscall id */ @@ -24,6 +30,12 @@ #define __NR_pidfd_getfd 438 /* Syscall id */ #endif +// maximum value of the off_t type +#define OFF_T_MAX \ + (sizeof(off_t) == sizeof(long long) \ + ? LLONG_MAX \ + : (sizeof(off_t) == sizeof(long) ? LONG_MAX : INT_MAX)) + static UTIL_ONCE_FLAG Page_size_is_initialized = UTIL_ONCE_FLAG_INIT; static size_t Page_size; @@ -104,3 +116,153 @@ umf_result_t utils_duplicate_fd(int pid, int fd_in, int *fd_out) { return UMF_RESULT_SUCCESS; #endif } + +umf_result_t utils_translate_mem_protection_one_flag(unsigned in_protection, + unsigned *out_protection) { + switch (in_protection) { + case UMF_PROTECTION_NONE: + *out_protection = PROT_NONE; + return UMF_RESULT_SUCCESS; + case UMF_PROTECTION_READ: + *out_protection = PROT_READ; + return UMF_RESULT_SUCCESS; + case UMF_PROTECTION_WRITE: + *out_protection = PROT_WRITE; + return UMF_RESULT_SUCCESS; + case UMF_PROTECTION_EXEC: + *out_protection = PROT_EXEC; + return UMF_RESULT_SUCCESS; + } + return UMF_RESULT_ERROR_INVALID_ARGUMENT; +} + +size_t get_max_file_size(void) { return OFF_T_MAX; } + +umf_result_t utils_translate_mem_protection_flags(unsigned in_protection, + unsigned *out_protection) { + // translate protection - combination of 'umf_mem_protection_flags_t' flags + return utils_translate_flags(in_protection, UMF_PROTECTION_MAX, + utils_translate_mem_protection_one_flag, + out_protection); +} + +static int utils_translate_purge_advise(umf_purge_advise_t advise) { + switch (advise) { + case UMF_PURGE_LAZY: + return MADV_FREE; + case UMF_PURGE_FORCE: + return MADV_DONTNEED; + } + return -1; +} + +void *utils_mmap(void *hint_addr, size_t length, int prot, int flag, int fd, + size_t fd_offset) { + fd = (fd == 0) ? -1 : fd; + if (fd == -1) { + // MAP_ANONYMOUS - the mapping is not backed by any file + flag |= MAP_ANONYMOUS; + } + + void *ptr = mmap(hint_addr, length, prot, flag, fd, fd_offset); + if (ptr == MAP_FAILED) { + return NULL; + } + // this should be unnecessary but pairs of mmap/munmap do not reset + // asan's user-poisoning flags, leading to invalid error reports + // Bug 81619: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81619 + utils_annotate_memory_defined(ptr, length); + return ptr; +} + +int utils_munmap(void *addr, size_t length) { + // this should be unnecessary but pairs of mmap/munmap do not reset + // asan's user-poisoning flags, leading to invalid error reports + // Bug 81619: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81619 + utils_annotate_memory_defined(addr, length); + return munmap(addr, length); +} + +int utils_purge(void *addr, size_t length, int advice) { + return madvise(addr, length, utils_translate_purge_advise(advice)); +} + +void utils_strerror(int errnum, char *buf, size_t buflen) { +// 'strerror_r' implementation is XSI-compliant (returns 0 on success) +#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE + if (strerror_r(errnum, buf, buflen)) { +#else // 'strerror_r' implementation is GNU-specific (returns pointer on success) + if (!strerror_r(errnum, buf, buflen)) { +#endif + LOG_PERR("Retrieving error code description failed"); + } +} + +// open a devdax +int utils_devdax_open(const char *path) { + if (path == NULL) { + LOG_ERR("empty path"); + return -1; + } + + if (strstr(path, "/dev/dax") != path) { + LOG_ERR("path of the file \"%s\" does not start with \"/dev/dax\"", + path); + return -1; + } + + int fd = open(path, O_RDWR); + if (fd == -1) { + LOG_PERR("cannot open the file: %s", path); + return -1; + } + + struct stat statbuf; + int ret = stat(path, &statbuf); + if (ret) { + LOG_PERR("stat(%s) failed", path); + close(fd); + return -1; + } + + if (!S_ISCHR(statbuf.st_mode)) { + LOG_ERR("file %s is not a character device", path); + close(fd); + return -1; + } + + return fd; +} + +// open a file +int utils_file_open(const char *path) { + if (!path) { + LOG_ERR("empty path"); + return -1; + } + + int fd = open(path, O_RDWR); + if (fd == -1) { + LOG_PERR("cannot open the file: %s", path); + } + + return fd; +} + +// open a file or create +int utils_file_open_or_create(const char *path) { + if (!path) { + LOG_ERR("empty path"); + return -1; + } + + int fd = open(path, O_RDWR | O_CREAT, 0600); + if (fd == -1) { + LOG_PERR("cannot open/create the file: %s", path); + return -1; + } + + LOG_DEBUG("opened/created the file: %s", path); + + return fd; +} diff --git a/src/utils/utils_windows_common.c b/src/utils/utils_windows_common.c index 9358891ad..f33b29e1b 100644 --- a/src/utils/utils_windows_common.c +++ b/src/utils/utils_windows_common.c @@ -9,11 +9,16 @@ #include +#include #include #include +#include +#include +#include #include "utils_common.h" #include "utils_concurrency.h" +#include "utils_log.h" #define BUFFER_SIZE 1024 @@ -46,3 +51,163 @@ umf_result_t utils_duplicate_fd(int pid, int fd_in, int *fd_out) { (void)fd_out; // unused return UMF_RESULT_ERROR_NOT_SUPPORTED; } + +umf_result_t utils_translate_mem_protection_flags(unsigned in_protection, + unsigned *out_protection) { + switch (in_protection) { + case UMF_PROTECTION_NONE: + *out_protection = PAGE_NOACCESS; + return UMF_RESULT_SUCCESS; + case UMF_PROTECTION_EXEC: + *out_protection = PAGE_EXECUTE; + return UMF_RESULT_SUCCESS; + case (UMF_PROTECTION_EXEC | UMF_PROTECTION_READ): + *out_protection = PAGE_EXECUTE_READ; + return UMF_RESULT_SUCCESS; + case (UMF_PROTECTION_EXEC | UMF_PROTECTION_READ | UMF_PROTECTION_WRITE): + *out_protection = PAGE_EXECUTE_READWRITE; + return UMF_RESULT_SUCCESS; + case (UMF_PROTECTION_EXEC | UMF_PROTECTION_WRITE): + *out_protection = PAGE_EXECUTE_WRITECOPY; + return UMF_RESULT_SUCCESS; + case UMF_PROTECTION_READ: + *out_protection = PAGE_READONLY; + return UMF_RESULT_SUCCESS; + case (UMF_PROTECTION_READ | UMF_PROTECTION_WRITE): + *out_protection = PAGE_READWRITE; + return UMF_RESULT_SUCCESS; + case UMF_PROTECTION_WRITE: + *out_protection = PAGE_WRITECOPY; + return UMF_RESULT_SUCCESS; + } + LOG_ERR( + "utils_translate_mem_protection_flags(): unsupported protection flag: " + "%u", + in_protection); + return UMF_RESULT_ERROR_INVALID_ARGUMENT; +} + +umf_result_t +utils_translate_mem_visibility_flag(umf_memory_visibility_t in_flag, + unsigned *out_flag) { + switch (in_flag) { + case UMF_MEM_MAP_PRIVATE: + *out_flag = 0; // ignored on Windows + return UMF_RESULT_SUCCESS; + case UMF_MEM_MAP_SHARED: + return UMF_RESULT_ERROR_NOT_SUPPORTED; // not supported on Windows yet + } + return UMF_RESULT_ERROR_INVALID_ARGUMENT; +} + +// create a shared memory file +int utils_shm_create(const char *shm_name, size_t size) { + (void)shm_name; // unused + (void)size; // unused + return 0; // ignored on Windows +} + +// open a shared memory file +int utils_shm_open(const char *shm_name) { + (void)shm_name; // unused + return 0; // ignored on Windows +} + +// unlink a shared memory file +int utils_shm_unlink(const char *shm_name) { + (void)shm_name; // unused + return 0; // ignored on Windows +} + +int utils_create_anonymous_fd(void) { + return 0; // ignored on Windows +} + +size_t get_max_file_size(void) { return SIZE_MAX; } + +int utils_get_file_size(int fd, size_t *size) { + (void)fd; // unused + (void)size; // unused + return -1; // not supported on Windows +} + +int utils_set_file_size(int fd, size_t size) { + (void)fd; // unused + (void)size; // unused + return 0; // ignored on Windows +} + +void *utils_mmap(void *hint_addr, size_t length, int prot, int flag, int fd, + size_t fd_offset) { + (void)flag; // ignored on Windows + (void)fd; // ignored on Windows + (void)fd_offset; // ignored on Windows + return VirtualAlloc(hint_addr, length, MEM_RESERVE | MEM_COMMIT, prot); +} + +void *utils_devdax_mmap(void *hint_addr, size_t length, int prot, int fd) { + (void)hint_addr; // unused + (void)length; // unused + (void)prot; // unused + (void)fd; // unused + return NULL; // not supported on Windows +} + +int utils_munmap(void *addr, size_t length) { + // If VirtualFree() succeeds, the return value is nonzero. + // If VirtualFree() fails, the return value is 0 (zero). + (void)length; // unused + return (VirtualFree(addr, 0, MEM_RELEASE) == 0); +} + +int utils_purge(void *addr, size_t length, int advice) { + // If VirtualFree() succeeds, the return value is nonzero. + // If VirtualFree() fails, the return value is 0 (zero). + (void)advice; // unused + + // temporarily disable the C6250 warning as we intentionally use the + // MEM_DECOMMIT flag only +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 6250) +#endif // _MSC_VER + + return (VirtualFree(addr, length, MEM_DECOMMIT) == 0); + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif // _MSC_VER +} + +void utils_strerror(int errnum, char *buf, size_t buflen) { + strerror_s(buf, buflen, errnum); +} + +// open a devdax +int utils_devdax_open(const char *path) { + (void)path; // unused + + return -1; +} + +// open a file +int utils_file_open(const char *path) { + (void)path; // unused + + return -1; +} + +// open a file or create +int utils_file_open_or_create(const char *path) { + (void)path; // unused + + return -1; +} + +int utils_fallocate(int fd, long offset, long len) { + (void)fd; // unused + (void)offset; // unused + (void)len; // unused + + return -1; +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f2e1a4561..22599dad4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -114,10 +114,6 @@ endfunction() add_subdirectory(common) -add_umf_test(NAME base SRCS base.cpp) -add_umf_test(NAME memoryPool SRCS memoryPoolAPI.cpp malloc_compliance_tests.cpp) -add_umf_test(NAME memoryProvider SRCS memoryProviderAPI.cpp) - if(UMF_BUILD_SHARED_LIBRARY) # if build as shared library, utils symbols won't be visible in tests set(UMF_UTILS_FOR_TEST umf_utils) @@ -125,6 +121,14 @@ if(UMF_BUILD_SHARED_LIBRARY) set(UMF_UTILS_SOURCES ../src/utils/utils_common.c ../src/utils/utils_posix_common.c ../src/utils/utils_posix_concurrency.c) + if(LINUX) + set(UMF_UTILS_SOURCES ${UMF_UTILS_SOURCES} + ../src/utils/utils_linux_common.c) + set(UMF_LOGGER_LIBS rt) # librt for shm_open() + elseif(MACOSX) + set(UMF_UTILS_SOURCES ${UMF_UTILS_SOURCES} + ../src/utils/utils_macosx_common.c) + endif() elseif(WINDOWS) set(UMF_UTILS_SOURCES ../src/utils/utils_common.c ../src/utils/utils_windows_common.c @@ -132,7 +136,16 @@ if(UMF_BUILD_SHARED_LIBRARY) endif() endif() -add_umf_test(NAME logger SRCS utils/utils_log.cpp ${UMF_UTILS_SOURCES}) +add_umf_test(NAME base SRCS base.cpp) +add_umf_test( + NAME memoryPool + SRCS memoryPoolAPI.cpp malloc_compliance_tests.cpp + LIBS ${UMF_UTILS_FOR_TEST}) +add_umf_test(NAME memoryProvider SRCS memoryProviderAPI.cpp) +add_umf_test( + NAME logger + SRCS utils/utils_log.cpp ${UMF_UTILS_SOURCES} + LIBS ${UMF_LOGGER_LIBS}) add_umf_test( NAME utils_common diff --git a/test/utils/utils_log.cpp b/test/utils/utils_log.cpp index 3e899e685..f865b416b 100644 --- a/test/utils/utils_log.cpp +++ b/test/utils/utils_log.cpp @@ -107,7 +107,9 @@ const char *env_variable = ""; #define strerror_s(A, B, C) mock_strerror_windows(A, B, C) //getenv returns 'char *' not 'const char *' so we need explicit cast to drop const #define getenv(X) strstr(X, "UMF_LOG") ? (char *)env_variable : getenv(X) +#ifndef UMF_VERSION #define UMF_VERSION "test version" +#endif #include "utils/utils_log.c" #undef util_env_var #undef fopen