diff --git a/sycl/cmake/modules/BuildUnifiedRuntime.cmake b/sycl/cmake/modules/BuildUnifiedRuntime.cmake index e0fce1bf48ad0..73e52e59f2be3 100644 --- a/sycl/cmake/modules/BuildUnifiedRuntime.cmake +++ b/sycl/cmake/modules/BuildUnifiedRuntime.cmake @@ -16,6 +16,9 @@ set(UR_BUILD_EXAMPLES "${SYCL_UR_BUILD_TESTS}" CACHE BOOL "" FORCE) option(SYCL_UR_FORMAT_CPP_STYLE "Format code style of UR C++ sources" OFF) set(UR_FORMAT_CPP_STYLE "${SYCL_UR_FORMAT_CPP_STYLE}" CACHE BOOL "" FORCE) +option(SYCL_UR_ENABLE_ASSERTIONS "Enable assertions for all UR build types" OFF) +set(UR_ENABLE_ASSERTIONS "${SYCL_UR_ENABLE_ASSERTIONS}" CACHE BOOL "" FORCE) + # Here we override the defaults to unified-runtime set(UR_BUILD_XPTI_LIBS OFF CACHE BOOL "") set(UR_ENABLE_SYMBOLIZER ON CACHE BOOL "Enable symbolizer for sanitizer layer.") diff --git a/unified-runtime/cmake/Assertions.cmake b/unified-runtime/cmake/Assertions.cmake index 9d8f6c0f2650f..637e71dd62daf 100644 --- a/unified-runtime/cmake/Assertions.cmake +++ b/unified-runtime/cmake/Assertions.cmake @@ -8,6 +8,7 @@ if(UR_ENABLE_ASSERTIONS) # MSVC doesn't like _DEBUG on release builds if( NOT MSVC ) add_compile_definitions(_DEBUG) + add_compile_definitions(UR_DASSERT_ENABLED) endif() # On non-Debug builds cmake automatically defines NDEBUG, so we # explicitly undefine it: diff --git a/unified-runtime/source/adapters/level_zero/adapter.cpp b/unified-runtime/source/adapters/level_zero/adapter.cpp index 9de4138f7e433..ec178d271f73f 100644 --- a/unified-runtime/source/adapters/level_zero/adapter.cpp +++ b/unified-runtime/source/adapters/level_zero/adapter.cpp @@ -569,6 +569,7 @@ ur_adapter_handle_t_::ur_adapter_handle_t_() if (err == UR_RESULT_SUCCESS) { Platforms = std::move(platforms); } else { + UR_LOG(ERR, "Failed to initialize Platforms"); throw err; } } diff --git a/unified-runtime/source/adapters/level_zero/common.hpp b/unified-runtime/source/adapters/level_zero/common.hpp index d6e973e3c8be5..15c4afe82047d 100644 --- a/unified-runtime/source/adapters/level_zero/common.hpp +++ b/unified-runtime/source/adapters/level_zero/common.hpp @@ -218,8 +218,11 @@ void zeParseError(ze_result_t ZeError, const char *&ErrorString); #define ZE2UR_CALL_THROWS(ZeName, ZeArgs) \ { \ ze_result_t ZeResult = ZeName ZeArgs; \ - if (auto Result = ZeCall().doCall(ZeResult, #ZeName, #ZeArgs, true)) \ + if (auto Result = ZeCall().doCall(ZeResult, #ZeName, #ZeArgs, true)) { \ + UR_DFAILURE("failed ZE call " #ZeName " with " #ZeArgs ", with result:" \ + << Result); \ throw ze2urResult(Result); \ + } \ } // Perform traced call to L0 without checking for errors diff --git a/unified-runtime/source/adapters/level_zero/v2/command_list_cache.cpp b/unified-runtime/source/adapters/level_zero/v2/command_list_cache.cpp index 4e6e2e5f3b7d8..9c867c9dc9a52 100644 --- a/unified-runtime/source/adapters/level_zero/v2/command_list_cache.cpp +++ b/unified-runtime/source/adapters/level_zero/v2/command_list_cache.cpp @@ -109,6 +109,7 @@ command_list_cache_t::createCommandList(const command_list_descriptor_t &desc) { if (!ZeMutableCmdListExtentionSupported && IsMutable) { UR_LOG(INFO, "Mutable command lists were requested but are not supported " "by the driver."); + UR_DFAILURE("Mutable command lists unsupported"); throw UR_RESULT_ERROR_UNSUPPORTED_FEATURE; } ZeStruct CmdListDesc; diff --git a/unified-runtime/source/adapters/level_zero/v2/command_list_manager.cpp b/unified-runtime/source/adapters/level_zero/v2/command_list_manager.cpp index 3561d84ae3962..7876e7fa945db 100644 --- a/unified-runtime/source/adapters/level_zero/v2/command_list_manager.cpp +++ b/unified-runtime/source/adapters/level_zero/v2/command_list_manager.cpp @@ -715,6 +715,7 @@ static void *getGlobalPointerFromModule(ze_module_handle_t hModule, ZE2UR_CALL_THROWS(zeModuleGetGlobalPointer, (hModule, name, &globalVarSize, &globalVarPtr)); if (globalVarSize < offset + count) { + UR_DFAILURE("Write device global variable is out of range"); setErrorMessage("Write device global variable is out of range.", UR_RESULT_ERROR_INVALID_VALUE, static_cast(ZE_RESULT_ERROR_INVALID_ARGUMENT)); @@ -820,8 +821,7 @@ ur_result_t ur_command_list_manager::appendUSMAllocHelper( commandType = UR_COMMAND_ENQUEUE_USM_SHARED_ALLOC_EXP; break; default: - UR_LOG(ERR, "enqueueUSMAllocHelper: unsupported USM type"); - throw UR_RESULT_ERROR_INVALID_ARGUMENT; + UR_FFAILURE("enqueueUSMAllocHelper: unsupported USM type:" << type); } auto zeSignalEvent = getSignalEvent(phEvent, commandType); diff --git a/unified-runtime/source/adapters/level_zero/v2/common.hpp b/unified-runtime/source/adapters/level_zero/v2/common.hpp index a13a655df5017..e6a2baf2718c1 100644 --- a/unified-runtime/source/adapters/level_zero/v2/common.hpp +++ b/unified-runtime/source/adapters/level_zero/v2/common.hpp @@ -69,8 +69,10 @@ struct ze_handle_wrapper { ZE_CALL_NOCHECK_NAME(destroy, (handle), destroyName); // Gracefully handle the case that L0 was already unloaded. if (zeResult && (zeResult != ZE_RESULT_ERROR_UNINITIALIZED && - zeResult != ZE_RESULT_ERROR_UNKNOWN)) + zeResult != ZE_RESULT_ERROR_UNKNOWN)) { + UR_DFAILURE("destroy failed in L0 with" << zeResult); throw ze2urResult(zeResult); + } if (zeResult == ZE_RESULT_ERROR_UNKNOWN) { zeResult = ZE_RESULT_ERROR_UNINITIALIZED; } diff --git a/unified-runtime/source/adapters/level_zero/v2/context.hpp b/unified-runtime/source/adapters/level_zero/v2/context.hpp index b1500092a727b..88351db825777 100644 --- a/unified-runtime/source/adapters/level_zero/v2/context.hpp +++ b/unified-runtime/source/adapters/level_zero/v2/context.hpp @@ -56,10 +56,8 @@ struct ur_context_handle_t_ : ur_object { return eventPoolCacheImmediate; case PoolCacheType::Regular: return eventPoolCacheRegular; - default: - assert(false && "Requested invalid event pool cache type"); - throw UR_RESULT_ERROR_INVALID_VALUE; } + UR_FFAILURE("Requested invalid event pool cache type"); } // Checks if Device is covered by this context. // For that the Device or its root devices need to be in the context. diff --git a/unified-runtime/source/adapters/level_zero/v2/kernel.cpp b/unified-runtime/source/adapters/level_zero/v2/kernel.cpp index 173b51ffc42a5..7e54cfeef5324 100644 --- a/unified-runtime/source/adapters/level_zero/v2/kernel.cpp +++ b/unified-runtime/source/adapters/level_zero/v2/kernel.cpp @@ -84,6 +84,7 @@ ur_kernel_handle_t_::ur_kernel_handle_t_( ze_kernel_handle_t zeKernel = ur_cast(hNativeKernel); if (!zeKernel) { + UR_DFAILURE("could not create kernel"); throw UR_RESULT_ERROR_INVALID_KERNEL; } @@ -136,6 +137,7 @@ void ur_kernel_handle_t_::completeInitialization() { size_t ur_kernel_handle_t_::deviceIndex(ur_device_handle_t hDevice) const { if (!hDevice) { + UR_DFAILURE("invalid handle:" << hDevice); throw UR_RESULT_ERROR_INVALID_DEVICE; } @@ -145,6 +147,7 @@ size_t ur_kernel_handle_t_::deviceIndex(ur_device_handle_t hDevice) const { } if (!deviceKernels[hDevice->Id.value()].has_value()) { + UR_DFAILURE("invalid device:" << hDevice << ", not found in deviceKernels"); throw UR_RESULT_ERROR_INVALID_DEVICE; } diff --git a/unified-runtime/source/adapters/level_zero/v2/memory.cpp b/unified-runtime/source/adapters/level_zero/v2/memory.cpp index 1b6855e630994..a5a8ee3387d3e 100644 --- a/unified-runtime/source/adapters/level_zero/v2/memory.cpp +++ b/unified-runtime/source/adapters/level_zero/v2/memory.cpp @@ -302,6 +302,7 @@ static void migrateMemory(ze_command_list_handle_t cmdList, void *src, void *dst, size_t size, wait_list_view &waitListView) { if (!cmdList) { + UR_DFAILURE("invalid handle in migrateMemory"); throw UR_RESULT_ERROR_INVALID_NULL_HANDLE; } ZE2UR_CALL_THROWS(zeCommandListAppendMemoryCopy, @@ -356,6 +357,7 @@ void ur_discrete_buffer_handle_t::unmapHostPtr(void *pMappedPtr, }); if (hostAlloc == hostAllocations.end()) { + UR_DFAILURE("could not find pMappedPtr:" << pMappedPtr); throw UR_RESULT_ERROR_INVALID_ARGUMENT; } @@ -507,11 +509,15 @@ static void verifyImageRegion([[maybe_unused]] ze_image_desc_t &zeImageDesc, (zeImageDesc.format.layout == ZE_IMAGE_FORMAT_LAYOUT_16_16_16_16 && rowPitch == 4 * 2 * zeRegion.width) || (zeImageDesc.format.layout == ZE_IMAGE_FORMAT_LAYOUT_8_8_8_8 && - rowPitch == 4 * zeRegion.width))) + rowPitch == 4 * zeRegion.width))) { + UR_DFAILURE("image size is invalid"); throw UR_RESULT_ERROR_INVALID_IMAGE_SIZE; + } #endif - if (!(slicePitch == 0 || slicePitch == rowPitch * zeRegion.height)) + if (!(slicePitch == 0 || slicePitch == rowPitch * zeRegion.height)) { + UR_DFAILURE("image size is invalid"); throw UR_RESULT_ERROR_INVALID_IMAGE_SIZE; + } } std::pair diff --git a/unified-runtime/source/adapters/level_zero/v2/queue_immediate_out_of_order.cpp b/unified-runtime/source/adapters/level_zero/v2/queue_immediate_out_of_order.cpp index 2fbe7fa5a1f57..dae2e42f93069 100644 --- a/unified-runtime/source/adapters/level_zero/v2/queue_immediate_out_of_order.cpp +++ b/unified-runtime/source/adapters/level_zero/v2/queue_immediate_out_of_order.cpp @@ -68,6 +68,7 @@ ur_result_t ur_queue_immediate_out_of_order_t::queueGetInfo( } else if (status == ZE_RESULT_NOT_READY) { return false; } else { + UR_DFAILURE("getting queue info failed with: " << status); throw ze2urResult(status); } }; diff --git a/unified-runtime/source/adapters/level_zero/v2/usm.cpp b/unified-runtime/source/adapters/level_zero/v2/usm.cpp index 080ab75afb0bb..9774ff7e212e6 100644 --- a/unified-runtime/source/adapters/level_zero/v2/usm.cpp +++ b/unified-runtime/source/adapters/level_zero/v2/usm.cpp @@ -20,6 +20,8 @@ static inline void UMF_CALL_THROWS(umf_result_t res) { if (res != UMF_RESULT_SUCCESS) { + UR_DFAILURE("some umf call in v2 L0 adapter returned " + << res << " instead of success"); throw res; } } @@ -80,9 +82,10 @@ inline umf_usm_memory_type_t urToUmfMemoryType(ur_usm_type_t type) { return UMF_MEMORY_TYPE_SHARED; case UR_USM_TYPE_HOST: return UMF_MEMORY_TYPE_HOST; - default: - throw UR_RESULT_ERROR_INVALID_ARGUMENT; + case UR_USM_TYPE_UNKNOWN: + case UR_USM_TYPE_FORCE_UINT32:; // silence warning, fail below } + UR_FFAILURE("invalid memory type: " << type); } static usm::DisjointPoolMemType @@ -93,14 +96,14 @@ descToDisjoinPoolMemType(const usm::pool_descriptor &desc) { case UR_USM_TYPE_SHARED: { if (desc.deviceReadOnly) return usm::DisjointPoolMemType::SharedReadOnly; - else - return usm::DisjointPoolMemType::Shared; + return usm::DisjointPoolMemType::Shared; } case UR_USM_TYPE_HOST: return usm::DisjointPoolMemType::Host; - default: - throw UR_RESULT_ERROR_INVALID_ARGUMENT; + case UR_USM_TYPE_UNKNOWN: + case UR_USM_TYPE_FORCE_UINT32:; // silence warning, fail below } + UR_FFAILURE("invalid memory type: " << desc.type); } static umf::provider_unique_handle_t @@ -143,6 +146,7 @@ makeProvider(usm::pool_descriptor poolDescriptor) { auto [ret, provider] = umf::providerMakeUniqueFromOps(umfLevelZeroMemoryProviderOps(), hParams); if (ret != UMF_RESULT_SUCCESS) { + UR_DFAILURE("umf::providerMakeUniqueFromOps failed with " << ret); throw umf::umf2urResult(ret); } diff --git a/unified-runtime/source/common/CMakeLists.txt b/unified-runtime/source/common/CMakeLists.txt index ee768db54c1b3..9657bfc5f620c 100644 --- a/unified-runtime/source/common/CMakeLists.txt +++ b/unified-runtime/source/common/CMakeLists.txt @@ -22,6 +22,8 @@ endif() add_ur_library(ur_common STATIC ur_util.cpp ur_util.hpp + logger/ur_logger.cpp + logger/ur_logger.hpp latency_tracker.hpp offload_bundle_parser.cpp offload_bundle_parser.hpp @@ -29,6 +31,29 @@ add_ur_library(ur_common STATIC $<$:linux/ur_lib_loader.cpp> ) +# link validation backtrace dependencies +if(UNIX) + find_package(Libbacktrace) +endif() +if (VAL_USE_LIBBACKTRACE_BACKTRACE AND LIBBACKTRACE_FOUND) + message(STATUS "Using libbacktrace backtrace") + + target_sources(ur_common PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/backtrace_libbacktrace.cpp) + target_link_libraries(ur_common PRIVATE Libbacktrace) +else() + message(STATUS "Using default backtrace") + + if(WIN32) + target_sources(ur_common PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/backtrace_win.cpp) + target_link_libraries(ur_common PRIVATE dbghelp) + else() + target_sources(ur_common PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/backtrace_lin.cpp) + endif() +endif() + add_library(${PROJECT_NAME}::common ALIAS ur_common) target_include_directories(ur_common PUBLIC diff --git a/unified-runtime/source/loader/layers/validation/backtrace.hpp b/unified-runtime/source/common/backtrace.hpp similarity index 72% rename from unified-runtime/source/loader/layers/validation/backtrace.hpp rename to unified-runtime/source/common/backtrace.hpp index 1224177fa17de..30850277c7a71 100644 --- a/unified-runtime/source/loader/layers/validation/backtrace.hpp +++ b/unified-runtime/source/common/backtrace.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2023 Intel Corporation +// Copyright (C) 2023-2025 Intel Corporation // Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM // Exceptions. See LICENSE.TXT // @@ -6,15 +6,16 @@ #ifndef UR_BACKTRACE_H #define UR_BACKTRACE_H 1 -#include "ur_validation_layer.hpp" +#include +#include #define MAX_BACKTRACE_FRAMES 64 -namespace ur_validation_layer { +namespace ur { using BacktraceLine = std::string; std::vector getCurrentBacktrace(); -} // namespace ur_validation_layer +} // namespace ur #endif /* UR_BACKTRACE_H */ diff --git a/unified-runtime/source/loader/layers/validation/backtrace_libbacktrace.cpp b/unified-runtime/source/common/backtrace_libbacktrace.cpp similarity index 95% rename from unified-runtime/source/loader/layers/validation/backtrace_libbacktrace.cpp rename to unified-runtime/source/common/backtrace_libbacktrace.cpp index be5918c859c1d..9a6804955b4cc 100644 --- a/unified-runtime/source/loader/layers/validation/backtrace_libbacktrace.cpp +++ b/unified-runtime/source/common/backtrace_libbacktrace.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2023 Intel Corporation + * Copyright (C) 2023-2025 Intel Corporation * * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM * Exceptions. See LICENSE.TXT @@ -15,7 +15,7 @@ #include #include -namespace ur_validation_layer { +namespace ur { void filter_after_occurence(std::vector &backtrace, std::string substring) { @@ -92,4 +92,4 @@ std::vector getCurrentBacktrace() { return backtrace; } -} // namespace ur_validation_layer +} // namespace ur diff --git a/unified-runtime/source/loader/layers/validation/backtrace_lin.cpp b/unified-runtime/source/common/backtrace_lin.cpp similarity index 72% rename from unified-runtime/source/loader/layers/validation/backtrace_lin.cpp rename to unified-runtime/source/common/backtrace_lin.cpp index 77d30d4f21d10..8606660100510 100644 --- a/unified-runtime/source/loader/layers/validation/backtrace_lin.cpp +++ b/unified-runtime/source/common/backtrace_lin.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2023 Intel Corporation + * Copyright (C) 2023-2025 Intel Corporation * * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM * Exceptions. See LICENSE.TXT @@ -9,17 +9,15 @@ * */ #include "backtrace.hpp" - #include -#include -namespace ur_validation_layer { +namespace ur { std::vector getCurrentBacktrace() { void *backtraceFrames[MAX_BACKTRACE_FRAMES]; - int frameCount = backtrace(backtraceFrames, MAX_BACKTRACE_FRAMES); - char **backtraceStr = backtrace_symbols(backtraceFrames, frameCount); - + int frameCount = ::backtrace(backtraceFrames, MAX_BACKTRACE_FRAMES); + char **backtraceStr = ::backtrace_symbols(backtraceFrames, frameCount); + // TODO: implement getting demangled symbols using abi::__cxa_demangle if (backtraceStr == nullptr) { return std::vector(1, "Failed to acquire a backtrace"); } @@ -39,4 +37,4 @@ std::vector getCurrentBacktrace() { return backtrace; } -} // namespace ur_validation_layer +} // namespace ur diff --git a/unified-runtime/source/loader/layers/validation/backtrace_win.cpp b/unified-runtime/source/common/backtrace_win.cpp similarity index 92% rename from unified-runtime/source/loader/layers/validation/backtrace_win.cpp rename to unified-runtime/source/common/backtrace_win.cpp index 7566da2221929..ea8c22776572c 100644 --- a/unified-runtime/source/loader/layers/validation/backtrace_win.cpp +++ b/unified-runtime/source/common/backtrace_win.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2023 Intel Corporation + * Copyright (C) 2023-2025 Intel Corporation * * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM * Exceptions. See LICENSE.TXT @@ -15,7 +15,7 @@ #include #include -namespace ur_validation_layer { +namespace ur { std::vector getCurrentBacktrace() { HANDLE process = GetCurrentProcess(); @@ -55,4 +55,4 @@ std::vector getCurrentBacktrace() { return backtrace; } -} // namespace ur_validation_layer +} // namespace ur diff --git a/unified-runtime/source/common/logger/ur_logger.cpp b/unified-runtime/source/common/logger/ur_logger.cpp new file mode 100644 index 0000000000000..454f9723f001d --- /dev/null +++ b/unified-runtime/source/common/logger/ur_logger.cpp @@ -0,0 +1,115 @@ +/* + * + * Copyright (C) 2022-2025 Intel Corporation + * + * Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM + * Exceptions. See LICENSE.TXT + * + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + */ + +#include + +#include "../backtrace.hpp" +#include "ur_logger.hpp" + +namespace logger { + +void print_backtrace() { + for (auto btLine : ur::getCurrentBacktrace()) { + std::cerr << btLine << std::endl; + } +} + +static bool str_to_bool(const std::string &str) { + if (!str.empty()) { + std::string lower_value = str; + std::transform(lower_value.begin(), lower_value.end(), lower_value.begin(), + [](unsigned char c) { return std::tolower(c); }); + const std::initializer_list true_str = {"y", "yes", "t", + "true", "1"}; + return std::find(true_str.begin(), true_str.end(), lower_value) != + true_str.end(); + } + return false; +} + +Logger create_logger(std::string logger_name, bool skip_prefix, + bool skip_linebreak, ur_logger_level_t default_log_level) { + std::transform(logger_name.begin(), logger_name.end(), logger_name.begin(), + ::toupper); + + const std::string env_var_name = "UR_LOG_" + logger_name; + const auto default_flush_level = UR_LOGGER_LEVEL_ERROR; + const std::string default_output = "stderr"; + const bool default_fileline = false; + auto flush_level = default_flush_level; + ur_logger_level_t level = default_log_level; + bool fileline = default_fileline; + std::unique_ptr sink; + + try { + auto map = getenv_to_map(env_var_name.c_str()); + if (!map.has_value()) { + return Logger(default_log_level, + std::make_unique( + std::move(logger_name), skip_prefix, skip_linebreak)); + } + + auto kv = map->find("level"); + if (kv != map->end()) { + auto value = kv->second.front(); + level = str_to_level(std::move(value)); + map->erase(kv); + } + + kv = map->find("flush"); + if (kv != map->end()) { + auto value = kv->second.front(); + flush_level = str_to_level(std::move(value)); + map->erase(kv); + } + + kv = map->find("fileline"); + if (kv != map->end()) { + auto value = kv->second.front(); + fileline = str_to_bool(std::move(value)); + map->erase(kv); + } + + std::vector values = {default_output}; + kv = map->find("output"); + if (kv != map->end()) { + values = kv->second; + map->erase(kv); + } + + if (!map->empty()) { + std::cerr << "Wrong logger environment variable parameter: '" + << map->begin()->first << "'. Default logger options are set."; + return Logger(default_log_level, + std::make_unique( + std::move(logger_name), skip_prefix, skip_linebreak)); + } + + sink = values.size() == 2 ? sink_from_str(logger_name, values[0], values[1], + skip_prefix, skip_linebreak) + : sink_from_str(logger_name, values[0], "", + skip_prefix, skip_linebreak); + } catch (const std::invalid_argument &e) { + std::cerr << "Error when creating a logger instance from the '" + << env_var_name << "' environment variable:\n" + << e.what() << std::endl; + return Logger(default_log_level, + std::make_unique( + std::move(logger_name), skip_prefix, skip_linebreak)); + } + + sink->setFlushLevel(flush_level); + sink->setFileLine(fileline); + + return Logger(level, std::move(sink)); +} + +} // namespace logger diff --git a/unified-runtime/source/common/logger/ur_logger.hpp b/unified-runtime/source/common/logger/ur_logger.hpp index fc41445aff6a2..5f6023545066a 100644 --- a/unified-runtime/source/common/logger/ur_logger.hpp +++ b/unified-runtime/source/common/logger/ur_logger.hpp @@ -6,14 +6,63 @@ #ifndef UR_LOGGER_HPP #define UR_LOGGER_HPP 1 -#include -#include - #include "ur_logger_details.hpp" #include "ur_util.hpp" namespace logger { +void print_backtrace(); + +#define UR_FASSERT(expr, msg) \ + if (!(expr)) { \ + std::cerr << "ASSERTION FAILED at " __FILE__ ":" << __LINE__ \ + << " ((" #expr ")) " << msg << '\n'; \ + logger::print_backtrace(); \ + UR_LOG(ERR, "ASSERTION FAILED at " __FILE__ ":{} ((" #expr "))", \ + __LINE__); \ + abort(); \ + } + +#ifdef UR_DASSERT_ENABLED +#define UR_DASSERT(expr, msg) UR_FASSERT(expr, msg) +#else +#define UR_DASSERT(expr, msg) \ + { \ + while (0) { \ + } \ + }; +#endif + +// a fatal failure - always aborts program +#define UR_FFAILURE(msg) UR_FASSERT(false, msg) +// a debug failure - aborts program in debug mode or with assertions enabled +#define UR_DFAILURE(msg) UR_DASSERT(false, msg) + +/// @brief Create an instance of the logger with parameters obtained from the +/// respective +/// environment variable or with default configuration if the env var is +/// empty, not set, or has the wrong format. Logger env vars are in the +/// format: UR_LOG_*, ie.: +/// - UR_LOG_LOADER (logger for loader library), +/// - UR_LOG_NULL (logger for null adapter). +/// Example of env var for setting up a loader library logger with +/// logging level set to `info`, flush level set to `warning`, and output +/// set to the `out.log` file: +/// UR_LOG_LOADER="level:info;flush:warning;output:file,out.log" +/// @param logger_name name that should be appended to the `UR_LOG_` prefix to +/// get the proper environment variable, ie. "loader" +/// @param default_log_level provides the default logging configuration when the +/// environment +/// variable is not provided or cannot be parsed +/// @return an instance of a logger::Logger. In case of failure in the parsing +/// of +/// the environment variable, returns a default logger with the +/// following options: +/// - log level: quiet, meaning no messages are printed +/// - flush level: error, meaning that only error messages are +/// guaranteed +/// to be printed immediately as they occur +/// - output: stderr Logger create_logger(std::string logger_name, bool skip_prefix = false, bool skip_linebreak = false, @@ -46,126 +95,16 @@ inline void setFlushLevel(ur_logger_level_t level) { get_logger().setFlushLevel(level); } -template inline std::string toHex(T t) { - std::stringstream s; +template std::string toHex(T &&t) { + std::ostringstream s; s << std::hex << t; return s.str(); } -inline bool str_to_bool(const std::string &str) { - if (!str.empty()) { - std::string lower_value = str; - std::transform(lower_value.begin(), lower_value.end(), lower_value.begin(), - [](unsigned char c) { return std::tolower(c); }); - const std::initializer_list true_str = {"y", "yes", "t", - "true", "1"}; - return std::find(true_str.begin(), true_str.end(), lower_value) != - true_str.end(); - } - - return false; -} - -/// @brief Create an instance of the logger with parameters obtained from the -/// respective -/// environment variable or with default configuration if the env var is -/// empty, not set, or has the wrong format. Logger env vars are in the -/// format: UR_LOG_*, ie.: -/// - UR_LOG_LOADER (logger for loader library), -/// - UR_LOG_NULL (logger for null adapter). -/// Example of env var for setting up a loader library logger with -/// logging level set to `info`, flush level set to `warning`, and output -/// set to the `out.log` file: -/// UR_LOG_LOADER="level:info;flush:warning;output:file,out.log" -/// @param logger_name name that should be appended to the `UR_LOG_` prefix to -/// get the proper environment variable, ie. "loader" -/// @param default_log_level provides the default logging configuration when the -/// environment -/// variable is not provided or cannot be parsed -/// @return an instance of a logger::Logger. In case of failure in the parsing -/// of -/// the environment variable, returns a default logger with the -/// following options: -/// - log level: quiet, meaning no messages are printed -/// - flush level: error, meaning that only error messages are -/// guaranteed -/// to be printed immediately as they occur -/// - output: stderr -inline Logger create_logger(std::string logger_name, bool skip_prefix, - bool skip_linebreak, - ur_logger_level_t default_log_level) { - std::transform(logger_name.begin(), logger_name.end(), logger_name.begin(), - ::toupper); - const std::string env_var_name = "UR_LOG_" + logger_name; - const auto default_flush_level = UR_LOGGER_LEVEL_ERROR; - const std::string default_output = "stderr"; - const bool default_fileline = false; - auto flush_level = default_flush_level; - ur_logger_level_t level = default_log_level; - bool fileline = default_fileline; - std::unique_ptr sink; - - try { - auto map = getenv_to_map(env_var_name.c_str()); - if (!map.has_value()) { - return Logger(default_log_level, - std::make_unique( - std::move(logger_name), skip_prefix, skip_linebreak)); - } - - auto kv = map->find("level"); - if (kv != map->end()) { - auto value = kv->second.front(); - level = str_to_level(std::move(value)); - map->erase(kv); - } - - kv = map->find("flush"); - if (kv != map->end()) { - auto value = kv->second.front(); - flush_level = str_to_level(std::move(value)); - map->erase(kv); - } - - kv = map->find("fileline"); - if (kv != map->end()) { - auto value = kv->second.front(); - fileline = str_to_bool(std::move(value)); - map->erase(kv); - } - - std::vector values = {default_output}; - kv = map->find("output"); - if (kv != map->end()) { - values = kv->second; - map->erase(kv); - } - - if (!map->empty()) { - std::cerr << "Wrong logger environment variable parameter: '" - << map->begin()->first << "'. Default logger options are set."; - return Logger(default_log_level, - std::make_unique( - std::move(logger_name), skip_prefix, skip_linebreak)); - } - - sink = values.size() == 2 ? sink_from_str(logger_name, values[0], values[1], - skip_prefix, skip_linebreak) - : sink_from_str(logger_name, values[0], "", - skip_prefix, skip_linebreak); - } catch (const std::invalid_argument &e) { - std::cerr << "Error when creating a logger instance from the '" - << env_var_name << "' environment variable:\n" - << e.what() << std::endl; - return Logger(default_log_level, - std::make_unique( - std::move(logger_name), skip_prefix, skip_linebreak)); - } - - sink->setFlushLevel(flush_level); - sink->setFileLine(fileline); - - return Logger(level, std::move(sink)); +template std::string makeStringFromStreamable(T &&obj) { + std::ostringstream s; + s << obj; + return s.str(); } } // namespace logger diff --git a/unified-runtime/source/loader/CMakeLists.txt b/unified-runtime/source/loader/CMakeLists.txt index 15dc3127d3d0a..a331e10e34a8d 100644 --- a/unified-runtime/source/loader/CMakeLists.txt +++ b/unified-runtime/source/loader/CMakeLists.txt @@ -226,30 +226,6 @@ if(UR_ENABLE_SANITIZER) ) endif() - -# link validation backtrace dependencies -if(UNIX) - find_package(Libbacktrace) -endif() -if (VAL_USE_LIBBACKTRACE_BACKTRACE AND LIBBACKTRACE_FOUND) - message(STATUS "Using libbacktrace backtrace for validation") - - target_sources(ur_loader PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/layers/validation/backtrace_libbacktrace.cpp) - target_link_libraries(ur_loader PRIVATE Libbacktrace) -else() - message(STATUS "Using default backtrace for validation") - - if(WIN32) - target_sources(ur_loader PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/layers/validation/backtrace_win.cpp) - target_link_libraries(ur_loader PRIVATE dbghelp) - else() - target_sources(ur_loader PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/layers/validation/backtrace_lin.cpp) - endif() -endif() - if(WIN32) target_sources(ur_loader PRIVATE diff --git a/unified-runtime/source/loader/layers/validation/ur_leak_check.hpp b/unified-runtime/source/loader/layers/validation/ur_leak_check.hpp index 35b625bb3d1d3..d53d4f57f24d6 100644 --- a/unified-runtime/source/loader/layers/validation/ur_leak_check.hpp +++ b/unified-runtime/source/loader/layers/validation/ur_leak_check.hpp @@ -23,10 +23,10 @@ struct RefCountContext { struct RefRuntimeInfo { int64_t refCount; std::type_index type; - std::vector backtrace; + std::vector backtrace; RefRuntimeInfo(int64_t refCount, std::type_index type, - std::vector backtrace) + std::vector backtrace) : refCount(refCount), type(type), backtrace(std::move(backtrace)) {} }; @@ -54,7 +54,7 @@ struct RefCountContext { if (it == counts.end()) { std::tie(it, std::ignore) = counts.emplace( ptr, RefRuntimeInfo{1, std::type_index(typeid(handle)), - getCurrentBacktrace()}); + ur::getCurrentBacktrace()}); if (isAdapterHandle) { adapterCount++; } @@ -66,7 +66,7 @@ struct RefCountContext { if (it == counts.end()) { std::tie(it, std::ignore) = counts.emplace( ptr, RefRuntimeInfo{1, std::type_index(typeid(handle)), - getCurrentBacktrace()}); + ur::getCurrentBacktrace()}); } else { getContext()->logger.log(UR_LOGGER_LEVEL_ERROR, __FILE__, UR_STR_(__LINE__), "Handle {} already exists", @@ -88,7 +88,7 @@ struct RefCountContext { if (it == counts.end()) { std::tie(it, std::ignore) = counts.emplace( ptr, RefRuntimeInfo{-1, std::type_index(typeid(handle)), - getCurrentBacktrace()}); + ur::getCurrentBacktrace()}); } else { it->second.refCount--; } diff --git a/unified-runtime/source/ur/ur.hpp b/unified-runtime/source/ur/ur.hpp index 5b0914868777a..4ccbbd92e4f20 100644 --- a/unified-runtime/source/ur/ur.hpp +++ b/unified-runtime/source/ur/ur.hpp @@ -29,7 +29,9 @@ #include "logger/ur_logger.hpp" #include "ur_util.hpp" -// Helper for one-liner validation +// Helper for one-liner validation. Not really an assertion. To be renamed. +// For assertion that abort program use UR_DASSERT or UR_FASSERT from +// ur_logger.hpp #define UR_ASSERT(condition, error) \ if (!(condition)) \ return error;