diff --git a/xpti/include/xpti/xpti_data_types.h b/xpti/include/xpti/xpti_data_types.h index 2e2c378357c18..fe469390b7464 100644 --- a/xpti/include/xpti/xpti_data_types.h +++ b/xpti/include/xpti/xpti_data_types.h @@ -358,7 +358,7 @@ enum class payload_flag_t { // using trace_point_t = uint16_t; using event_type_t = uint16_t; -using string_id_t = int32_t; +using string_id_t = uint32_t; using object_id_t = int32_t; using safe_flag_t = std::atomic; @@ -455,60 +455,105 @@ struct payload_t { payload_t() = default; - // If the address of the kernel/function name is provided, we mark it as - // valid since we can potentially reconstruct the name and the source file - // information during post-processing step of symbol resolution; this - // indicates a partial but valid payload. + /// + /// @brief Constructs a payload_t with only a code pointer. + /// + /// @details + /// Initializes the payload with the provided code pointer address. All other + /// fields (name, source file, line number, column number) are set to invalid + /// or null values. If a valid code pointer is provided, the corresponding + /// flag is set to indicate its availability. + /// + /// If the address of the kernel/function name is provided, we mark it as + /// valid since we can potentially reconstruct the name and the source file + /// information during post-processing step of symbol resolution; this + /// indicates a partial but valid payload. + /// + /// @param codeptr Pointer to the code location associated with this payload. + /// payload_t(const void *codeptr) { - code_ptr_va = codeptr; - name = nullptr; ///< Invalid name string pointer - source_file = nullptr; ///< Invalid source file string pointer - line_no = invalid_id<>; ///< Invalid line number - column_no = invalid_id<>; ///< Invalid column number + code_ptr_va = codeptr; ///< Override the default initialization + // If the incoming code ptr is null, we ensure that the flags are set + // correctly if (codeptr) { flags = (uint64_t)payload_flag_t::CodePointerAvailable; } } - // If neither an address or the fully identifyable source file name and - // location are not available, we take in the name of the - // function/task/user-defined name as input and create a hash from it. We - // mark it as valid since we can display the name in a timeline view, but - // the payload is considered to be a partial but valid payload. + /// + /// @brief Constructs a payload_t with only a function or kernel name. + /// + /// @details + /// Initializes the payload with the provided function or kernel name. + /// If neither an address or the fully identifyable source file name and + /// location are not available, we take in the name of the + /// function/task/user-defined name as input and create a hash from it. We + /// mark it as valid since we can display the name in a timeline view, but + /// the payload is considered to be a partial but valid payload. + /// + /// @param func_name Name of the function, kernel, or user-defined entity. + /// payload_t(const char *func_name) { - code_ptr_va = nullptr; - name = func_name; ///< Invalid name string pointer - source_file = nullptr; ///< Invalid source file string pointer + name = func_name; ///< Override the default initialization + // If the incoming name is null, we ensure that the flags are set correctly if (func_name) { flags = (uint64_t)(payload_flag_t::NameAvailable); } } + /// + /// @brief Constructs a payload_t with a function or kernel name and code + /// pointer. + /// + /// @details + /// Initializes the payload with the provided function or kernel name and code + /// pointer. The source file is set to null. Flags are set to indicate which + /// fields are available. The payload is considered partial, but valid. + /// + /// @param func_name Name of the function, kernel, or user-defined entity. + /// @param codeptr Pointer to the code location associated with this payload. + /// payload_t(const char *func_name, const void *codeptr) { - code_ptr_va = codeptr; - name = func_name; ///< Invalid name string pointer - source_file = nullptr; ///< Invalid source file string pointer + code_ptr_va = codeptr; ///< Override the default initialization + name = func_name; ///< Override the default initialization + // If the incoming name is null, we ensure that the flags are set correctly if (func_name) { flags = (uint64_t)(payload_flag_t::NameAvailable); } + // If the incoming code ptr is null, we ensure that the flags are set + // correctly if (codeptr) { flags |= (uint64_t)payload_flag_t::CodePointerAvailable; } } - // When the end user opts out of preserving the code location information and - // the KernelInfo is not available from the given entry point, we will rely - // on dynamic backtrace as a possibility. In this case, we send in the - // caller/callee information as a string in the form "caller->callee" that - // will be used to generate the unique ID. + /// + /// @brief Constructs a payload_t with a name, stack trace, and code pointer. + /// + /// @details + /// Used when code location information is not preserved and dynamic backtrace + /// is used. Initializes the payload with the provided kernel name, + /// caller-callee stack trace, and code pointer. Sets flags to indicate which + /// fields are available. + /// + /// When the end user opts out of preserving the code location information and + /// the KernelInfo is not available from the given entry point, we will rely + /// on dynamic backtrace as a possibility. In this case, we send in the + /// caller/callee information as a string in the form "caller->callee" that + /// will be used to generate the unique ID. + /// + /// @param kname Name of the kernel or function. + /// @param caller_callee String representing the caller->callee relationship. + /// @param codeptr Pointer to the code location associated with this payload. + /// payload_t(const char *kname, const char *caller_callee, const void *codeptr) { if (codeptr) { - code_ptr_va = codeptr; + code_ptr_va = codeptr; ///< Override the default initialization flags |= (uint64_t)payload_flag_t::CodePointerAvailable; } - /// Capture the rest of the parameters + // If the incoming name is null, we ensure that the flags are set correctly if (kname) { - name = kname; + name = kname; ///< Override the default initialization flags |= (uint64_t)payload_flag_t::NameAvailable; } if (caller_callee) { @@ -517,34 +562,69 @@ struct payload_t { } } - // We need the payload to contain at the very least, the code pointer - // information of the kernel or function. In the full payload case, we will - // also have the function name and source file name along with the line and - // column number of the trace point that forms the payload. + /// + /// @brief Constructs a fully populated payload_t. + /// + /// @details + /// Initializes the payload with the provided kernel name, source file, line + /// number, column number, and optionally a code pointer. Sets flags to + /// indicate which fields are available. This would constitute a fully + /// populated payload. + /// + /// @param kname Name of the kernel or function. + /// @param sf Source file name. + /// @param line Line number in the source file. + /// @param col Column number in the source file. + /// @param codeptr (Optional) Pointer to the code location associated with + /// this payload. + /// payload_t(const char *kname, const char *sf, int line, int col, const void *codeptr = nullptr) { - code_ptr_va = codeptr; - /// Capture the rest of the parameters - name = kname; - source_file = sf; - line_no = static_cast(line); - column_no = static_cast(col); + code_ptr_va = codeptr; ///< Override the default initialization + name = kname; ///< Override the default initialization + source_file = sf; ///< Override the default initialization + line_no = + static_cast(line); ///< Override the default initialization + column_no = + static_cast(col); ///< Override the default initialization + // If the incoming name is null, we ensure that the flags are set correctly if (kname && kname[0] != '\0') { flags = (uint64_t)payload_flag_t::NameAvailable; } + // If the incoming source file name is null, we ensure that the flags are + // set correctly if (sf && sf[0] != '\0') { flags |= (uint64_t)payload_flag_t::SourceFileAvailable | (uint64_t)payload_flag_t::LineInfoAvailable | (uint64_t)payload_flag_t::ColumnInfoAvailable; } + // If the incoming code ptr is null, we ensure that the flags are set + // correctly if (codeptr) { flags |= (uint64_t)payload_flag_t::CodePointerAvailable; } } - int32_t name_sid() const { return (int32_t)(uid.p2 & 0x00000000ffffffff); } - int32_t stacktrace_sid() const { return (int32_t)(uid.p2 >> 32); } - int32_t source_file_sid() const { return (int32_t)(uid.p1 >> 32); } + /// @brief Retrieves the string ID (SID) for the name. + /// @details Extracts the lower 32 bits of the uid.p2 member, which represents + /// the xpti::string_id_t in legacy implementations or XPTI_USE_STRICT_HASH + /// mode and contains the FNV1a hash value associated with the name. + /// @return The 32-bit name string ID. + uint32_t name_sid() const { return (uint32_t)(uid.p2 & 0x00000000ffffffff); } + + /// @brief Retrieves the string ID (SID) for the stack trace. + /// @details Extracts the upper 32 bits of the uid.p2 member, which represents + /// the xpti::string_id_t in legacy implementations or XPTI_USE_STRICT_HASH + /// mode and contains the FNV1a hash value associated with the stack trace. + /// @return The 32-bit stack trace string ID. + uint32_t stacktrace_sid() const { return (uint32_t)(uid.p2 >> 32); } + + /// @brief Retrieves the string ID (SID) for the source file. + /// @details Extracts the upper 32 bits of the uid.p1 member, which represents + /// the xpti::string_id_t in legacy implementations or XPTI_USE_STRICT_HASH + /// mode and contains the FNV1a hash value associated with the source file. + /// @return The 32-bit source file string ID. + uint32_t source_file_sid() const { return (uint32_t)(uid.p1 >> 32); } }; /// A data structure that holds information about an API function call and its diff --git a/xpti/include/xpti/xpti_trace_framework.h b/xpti/include/xpti/xpti_trace_framework.h index 6cc0a48622774..a9d206933798a 100644 --- a/xpti/include/xpti/xpti_trace_framework.h +++ b/xpti/include/xpti/xpti_trace_framework.h @@ -696,6 +696,11 @@ XPTI_EXPORT_API const xpti_trace_event_t *xptiLookupEvent(uint64_t uid); /// @param column_no A uint32_t value representing the column number on the /// specified line where the tracepoint is located. This provides the most /// precise location of the tracepoint. +/// @param code_ptr_va A void pointer representing the virtual address of the +/// code where the tracepoint is located. This can be used to associate the +/// tracepoint with a specific code location in memory, which is particularly +/// useful for debugging and performance analysis. If not provided, it defaults +/// to nullptr, indicating that the code pointer is not specified. /// /// @return A pointer to the created `xpti_tracepoint_t` structure, which /// represents the tracepoint. If the tracepoint cannot be created, the function @@ -704,10 +709,10 @@ XPTI_EXPORT_API const xpti_trace_event_t *xptiLookupEvent(uint64_t uid); /// @note In order to preserve ABI compatibility, an interface pointer to /// `xpti_tracepoint_t` is returned. -XPTI_EXPORT_API xpti_tracepoint_t *xptiCreateTracepoint(const char *func_name, - const char *file_name, - uint32_t line_no, - uint32_t column_no); +XPTI_EXPORT_API xpti_tracepoint_t * +xptiCreateTracepoint(const char *func_name, const char *file_name, + uint32_t line_no, uint32_t column_no, + void *code_ptr_va = nullptr); /// @brief Deletes a tracepoint object. /// @@ -916,12 +921,16 @@ XPTI_EXPORT_API void xptiUnsetTracepointScopeData(); /// @param columnNo The column number in the source file where the trace point /// is defined. If column information is not available, this can /// be set to 0. +/// @param codePtrVa The code pointer value associated with the trace point. +/// If code pointer information is not available, this can +/// be set to nullptr. /// @return Returns a pointer to the registered `xpti_tracepoint_t` structure if /// the registration is successful; otherwise, returns NULL. The /// returned pointer should not be freed by the caller. XPTI_EXPORT_API const xpti_tracepoint_t * xptiRegisterTracepointScope(const char *funcName, const char *fileName, - uint32_t lineNo, uint32_t columnNo); + uint32_t lineNo, uint32_t columnNo, + void *codePtrVa = nullptr); /// @brief Retrieves the default stream ID. /// @details This function is used to get the default stream ID that is @@ -1042,7 +1051,8 @@ typedef xpti::result_t (*xpti_make_key_from_payload_t)(xpti::payload_t *, xpti::uid128_t *); typedef const xpti_tracepoint_t *(*xpti_get_trace_point_scope_data_t)(); typedef const xpti_tracepoint_t *(*xpti_register_tracepoint_scope_t)( - const char *func, const char *file, uint32_t line, uint32_t col); + const char *func, const char *file, uint32_t line, uint32_t col, + void *code_ptr_va); typedef xpti::result_t (*xpti_set_trace_point_scope_data_t)( xpti_tracepoint_t *); typedef void (*xpti_unset_trace_point_scope_data_t)(); @@ -1059,6 +1069,6 @@ typedef const xpti_payload_t *(*xpti_lookup_payload_t)(uint64_t); typedef const xpti_trace_event_t *(*xpti_lookup_event_t)(uint64_t); typedef xpti_tracepoint_t *(*xpti_create_tracepoint_t)(const char *, const char *, uint32_t, - uint32_t); + uint32_t, void *); typedef xpti::result_t (*xpti_delete_tracepoint_t)(xpti_tracepoint_t *); } diff --git a/xpti/include/xpti/xpti_trace_framework.hpp b/xpti/include/xpti/xpti_trace_framework.hpp index 0509e32efe462..3e7145bbaf823 100644 --- a/xpti/include/xpti/xpti_trace_framework.hpp +++ b/xpti/include/xpti/xpti_trace_framework.hpp @@ -56,6 +56,8 @@ typedef void *xpti_plugin_function_t; #endif namespace xpti { +constexpr const char *g_unknown_function = ""; +constexpr const char *g_unknown_file = ""; namespace utils { /// @class StringHelper /// @brief A helper class for string manipulations. @@ -575,12 +577,28 @@ inline std::string readMetadata(const metadata_t::value_type &MD) { inline bool is_valid_payload(const xpti::payload_t *Payload) { if (!Payload) return false; - else - return (Payload->flags != 0) && - ((Payload->flags & - static_cast(payload_flag_t::SourceFileAvailable) || - (Payload->flags & - static_cast(payload_flag_t::NameAvailable)))); + else { + bool isValid = false; + bool hasSourceFile = + (Payload->flags & + static_cast(payload_flag_t::SourceFileAvailable)) && + Payload->source_file; + bool hasName = (Payload->flags & + static_cast(payload_flag_t::NameAvailable)) && + Payload->name; + bool hasCodePtrVa = + (Payload->flags & + static_cast(payload_flag_t::CodePointerAvailable)) && + Payload->code_ptr_va; + bool hasLineInfo = + (Payload->flags & + static_cast(payload_flag_t::LineInfoAvailable)) && + Payload->line_no != xpti::invalid_id; + // We ignore checking for column info as it may not always be available + isValid = ((hasSourceFile && hasLineInfo) || hasName || hasCodePtrVa); + + return isValid; + } } /// @brief Generates a default payload object with unknown details. @@ -595,11 +613,11 @@ inline bool is_valid_payload(const xpti::payload_t *Payload) { /// /// @return A `xpti::payload_t` object with its members set to represent an /// unknown or unspecified payload. This includes setting the function name and -/// file name to "unknown", line and column numbers to 0, and the module handle -/// to nullptr. +/// file name to "" and "" respectively, line +/// and column numbers to 0, and the module handle to nullptr. /// inline xpti::payload_t unknown_payload() { - xpti::payload_t Payload("unknown", "unknown-file", 0, 0, nullptr); + xpti::payload_t Payload(g_unknown_function, g_unknown_file, 0, 0, nullptr); return Payload; } @@ -951,7 +969,8 @@ class tracepoint_scope_t { /// @note MSFT compiler 2019/2022 support __builtin_FUNCTION() macro /// tracepoint_scope_t(const char *fileName, const char *funcName, int line, - int column, bool selfNotify = false, + int column, void *codePtrVa = nullptr, + bool selfNotify = false, const char *callerFuncName = __builtin_FUNCTION()) : MTop(false), MSelfNotify(selfNotify), MCallerFuncName(callerFuncName) { if (!xptiTraceEnabled()) @@ -962,9 +981,9 @@ class tracepoint_scope_t { if (!MData) { if (funcName && fileName) init(funcName, fileName, static_cast(line), - static_cast(column)); + static_cast(column), codePtrVa); else - init(callerFuncName, nullptr, 0u, 0u); + init(callerFuncName, nullptr, 0u, 0u, codePtrVa); } else { MTraceEvent = MData->event_ref(); } @@ -1014,11 +1033,11 @@ class tracepoint_scope_t { /// tracepoint data. /// void init(const char *FuncName, const char *FileName, uint32_t LineNo, - uint32_t ColumnNo) { + uint32_t ColumnNo, void *CodePtrVa) { // Register the payload and prepare the tracepoint data. The function // returns a UID, associated payload and trace event - MData = const_cast( - xptiRegisterTracepointScope(FuncName, FileName, LineNo, ColumnNo)); + MData = const_cast(xptiRegisterTracepointScope( + FuncName, FileName, LineNo, ColumnNo, CodePtrVa)); if (MData) { // Set the tracepoint scope with the prepared data so all nested functions // will have access to it; this call also sets the Universal ID separately diff --git a/xpti/src/xpti_proxy.cpp b/xpti/src/xpti_proxy.cpp index 378fe6e8aacb6..a735ecb283977 100644 --- a/xpti/src/xpti_proxy.cpp +++ b/xpti/src/xpti_proxy.cpp @@ -588,16 +588,15 @@ XPTI_EXPORT_API bool xptiCheckTracepointScopeNotification() { return false; } -XPTI_EXPORT_API xpti_tracepoint_t *xptiCreateTracepoint(const char *name, - const char *source_file, - uint32_t line_no, - uint32_t column_no) { +XPTI_EXPORT_API xpti_tracepoint_t * +xptiCreateTracepoint(const char *name, const char *source_file, + uint32_t line_no, uint32_t column_no, void *code_ptr_va) { if (xpti::ProxyLoader::instance().noErrors()) { auto f = xpti::ProxyLoader::instance().functionByIndex(XPTI_CREATE_TRACEPOINT); if (f) { return (*(xpti_create_tracepoint_t)f)(name, source_file, line_no, - column_no); + column_no, code_ptr_va); } } return nullptr; @@ -669,13 +668,14 @@ XPTI_EXPORT_API void xptiUnsetTracepointScopeData() { XPTI_EXPORT_API const xpti_tracepoint_t * xptiRegisterTracepointScope(const char *FuncName, const char *FileName, - uint32_t LineNo, uint32_t ColumnNo) { + uint32_t LineNo, uint32_t ColumnNo, + void *CodePtrVa) { if (xpti::ProxyLoader::instance().noErrors()) { auto f = xpti::ProxyLoader::instance().functionByIndex( XPTI_REGISTER_TRACEPOINT_SCOPE); if (f) { return (*(xpti_register_tracepoint_scope_t)f)(FuncName, FileName, LineNo, - ColumnNo); + ColumnNo, CodePtrVa); } } return nullptr; diff --git a/xptifw/include/xpti_string_table.hpp b/xptifw/include/xpti_string_table.hpp index 79e622f93a907..bd48df01921b1 100644 --- a/xptifw/include/xpti_string_table.hpp +++ b/xptifw/include/xpti_string_table.hpp @@ -5,12 +5,14 @@ // #pragma once +#include "parallel_hashmap/phmap.h" #include "xpti/xpti_data_types.h" #include #include #include #include +#include #ifdef XPTI_STATISTICS #include @@ -25,8 +27,14 @@ namespace xpti { /// implementation used STL containers protected with std::mutex. class StringTable { public: - using st_forward_t = std::unordered_map; + using st_forward_t = phmap::node_hash_map; + /// Performance tests were conducted to determine if std::vector was faster + /// than emhash7::HashMap and so far emhash appears to be better +#ifndef XPTI_USE_VECTOR_LOOKUP using st_reverse_t = emhash7::HashMap; +#else + using st_reverse_t = std::vector; +#endif StringTable(int size = 65536) : MStringToID(size), MIDToString(size) { MIds = 1; @@ -111,6 +119,9 @@ class StringTable { // When we insert a new entry into the table, we also need to build // the reverse lookup; { +#ifdef XPTI_USE_VECTOR_LOOKUP + MIDToString[StrID] = Entry.first->first.c_str(); +#else auto IDLoc = MIDToString.find(StrID); if (IDLoc == MIDToString.end()) { // An entry does not exist, so we will add it to the reverse @@ -128,6 +139,7 @@ class StringTable { return xpti::invalid_id; } +#endif } } else { @@ -149,6 +161,7 @@ class StringTable { // may have been cached somewhere. const char *query(xpti::string_id_t id) { std::shared_lock lock(MMutex); +#ifndef XPTI_USE_VECTOR_LOOKUP auto Loc = MIDToString.find(id); if (Loc != MIDToString.end()) { #ifdef XPTI_STATISTICS @@ -157,6 +170,15 @@ class StringTable { return Loc->second; } else return nullptr; +#else + if (id > 0 && id < MIDToString.size()) { +#ifdef XPTI_STATISTICS + MRetrievals++; +#endif + return MIDToString[id]; + } else + return nullptr; +#endif } int32_t count() { return (int32_t)MStrings; } @@ -187,7 +209,7 @@ class StringTable { } private: - safe_int32_t MIds; ///< Thread-safe ID generator + safe_uint32_t MIds; ///< Thread-safe ID generator st_forward_t MStringToID; ///< Forward lookup hash map st_reverse_t MIDToString; ///< Reverse lookup hash map mutable std::shared_mutex MMutex; ///< Mutex required for double-check pattern diff --git a/xptifw/samples/basic_collector/basic_collector.cpp b/xptifw/samples/basic_collector/basic_collector.cpp index 29685b943938f..b325a48b3eb96 100644 --- a/xptifw/samples/basic_collector/basic_collector.cpp +++ b/xptifw/samples/basic_collector/basic_collector.cpp @@ -122,7 +122,7 @@ XPTI_CALLBACK_API void tpCallback(uint16_t TraceType, uint32_t CPU = M.cpu(); std::string Name; - if (Payload->name_sid() != xpti::invalid_id) { + if (xpti::is_valid_payload(Payload) && Payload->name) { Name = truncate(Payload->name); } else { Name = ""; @@ -143,7 +143,7 @@ XPTI_CALLBACK_API void tpCallback(uint16_t TraceType, std::cout << xpti::readMetadata(Item) << "\n"; } - if (Payload->source_file_sid() != xpti::invalid_id && Payload->line_no > 0) { + if (xpti::is_valid_payload(Payload)) { printf("---[Source file:line no] %s:%d\n", Payload->source_file, Payload->line_no); } diff --git a/xptifw/src/xpti_trace_framework.cpp b/xptifw/src/xpti_trace_framework.cpp index f3c9272655f21..750f858696d58 100644 --- a/xptifw/src/xpti_trace_framework.cpp +++ b/xptifw/src/xpti_trace_framework.cpp @@ -92,7 +92,34 @@ static std::once_flag g_initialize_default_stream_flag; /// thread-safe manner. static std::once_flag g_finalize_default_stream_flag; +/// @brief Flag to ensure strict hash mode is initialized only once. +/// @details +/// Used with std::call_once to initialize the strict hash mode in a thread-safe +/// manner. +static std::once_flag g_use_strict_hash_flag; + +/// @brief Global flag indicating whether strict hash mode is enabled. +/// @details +/// When set to true, the framework uses strict hash checking for payloads or +/// events. Defaults to false. +static bool g_use_strict_hash = false; + namespace xpti { +namespace hash { +/// @brief Computes the FNV-1a hash for a std::string. +/// @param str The input string. +/// @return The 32-bit FNV-1a hash value. +uint32_t fnv1a(const std::string &str) { + constexpr uint32_t INIT_VALUE = 2166136261u; + constexpr uint32_t LARGE_PRIME = 16777619u; + uint32_t hash = INIT_VALUE; + for (char c : str) { + hash ^= static_cast(c); + hash *= LARGE_PRIME; + } + return hash; +} +} // namespace hash /// @var env_subscribers /// @brief A constant character pointer initialized with the string /// "XPTI_SUBSCRIBERS". This variable represents the environment variable name @@ -151,6 +178,7 @@ struct PayloadReferenceImpl : xpti_payload_t { MPayload.source_file = Payload->source_file; MPayload.line_no = Payload->line_no; MPayload.column_no = Payload->column_no; + MPayload.code_ptr_va = Payload->code_ptr_va; MPayload.internal = Payload->internal; MPayload.flags = Payload->flags; MPayload.uid.p1 = Payload->uid.p1; @@ -204,9 +232,9 @@ struct TracePointImpl : xpti_payload_t, /// @brief Event data for the trace point. xpti::trace_event_data_t MEvent; /// @brief Cached Function string ID for the trace point. - int32_t MFuncID = xpti::invalid_id<>; + uint32_t MFuncID = xpti::invalid_id<>; /// @brief Cached File string ID for the trace point. - int32_t MFileID = xpti::invalid_id<>; + uint32_t MFileID = xpti::invalid_id<>; /// @brief Iterator for the metadata associated with the trace point. xpti::metadata_t::iterator MCurr; @@ -234,17 +262,19 @@ struct TracePointImpl : xpti_payload_t, if (!Payload || !xpti::is_valid_payload(Payload) || (UID.p1 == 0 && UID.p2 == 0)) return; - MUId = UID; + MUId.p1 = UID.p1; + MUId.p2 = UID.p2; + MUId.instance = UID.instance; MPayload.name = Payload->name; MPayload.source_file = Payload->source_file; MPayload.line_no = Payload->line_no; MPayload.column_no = Payload->column_no; + MPayload.code_ptr_va = Payload->code_ptr_va; MPayload.flags = Payload->flags; - xpti::framework::uid_object_t UidHelper(MUId); + xpti::framework::uid_object_t UidHelper(UID); MFuncID = UidHelper.functionId(); MFileID = UidHelper.fileId(); - MPayload.uid.p1 = Payload->uid.p1 = XPTI_PACK32_RET64(MFileID, MPayload.line_no); MPayload.uid.p2 = Payload->uid.p2 = XPTI_PACK32_RET64(0, MFuncID); @@ -574,11 +604,16 @@ class Subscribers { /// This is a single point for managing tracepoints. class Tracepoints { public: + struct PayloadCache { + xpti::payload_t Payload; + std::string Function; + std::string File; + }; /// @typedef uid_entry_t /// @brief A type alias for a pair containing an xpti::payload_t and an /// xpti::safe_uint64_t. This type is used to store a payload and a /// thread-safe unsigned 64-bit integer that tracks the instance. - using uid_entry_t = std::pair; + using uid_entry_t = std::pair; /// @typedef uid_payload_lut /// @brief A type alias for an unordered map from uid_t to uid_entry_t. @@ -586,7 +621,7 @@ class Tracepoints { /// identifiers (uids) to their corresponding payload entries. Since we plan /// to keep the payload information until the end of the application lifetime, /// we should be able to use the references. - using uid_payload_lut = std::unordered_map; + using uid_payload_lut = phmap::node_hash_map; /// @typedef uid_instances_t /// @brief Defines a hash map for managing tracepoint instances by their @@ -1027,17 +1062,41 @@ class Tracepoints { // provided, then we will have Key.p1 populated. std::unique_lock Lock(MPayloadMutex); auto &PayloadEntry = MPayloads[Key]; - if (PayloadEntry.first.flags == 0) { + if (PayloadEntry.first.Payload.flags == 0) { #ifdef XPTI_STATISTICS MInsertions++; #endif // We are seeing this UID for the first time, so we can update the // Payload information and set the instance to 1 - PayloadEntry.first = *Payload; - PayloadEntry.first.uid.p3 = 1; - PayloadEntry.first.internal = xpti::invalid_uid; + if (g_use_strict_hash) { + // If we are using the strict hash, then we will copy the payload + // information into the payload entry and set the payload pointer to the + // payload entry as the function name and the file name have been + // registered in the staring table and we have the invariant string + // associated with it. + PayloadEntry.first.Payload = *Payload; + } else { + if (Payload->name) { + PayloadEntry.first.Function = Payload->name; + PayloadEntry.first.Payload.name = PayloadEntry.first.Function.c_str(); + } + + if (Payload->source_file) { + PayloadEntry.first.File = Payload->source_file; + PayloadEntry.first.Payload.source_file = + PayloadEntry.first.File.c_str(); + } + + PayloadEntry.first.Payload.line_no = Payload->line_no; + PayloadEntry.first.Payload.column_no = Payload->column_no; + PayloadEntry.first.Payload.flags = Payload->flags; + PayloadEntry.first.Payload.uid.p1 = Payload->uid.p1; + PayloadEntry.first.Payload.uid.p2 = Payload->uid.p2; + } + PayloadEntry.first.Payload.uid.p3 = 1; + PayloadEntry.first.Payload.internal = xpti::invalid_uid; Key.instance = PayloadEntry.second = 1; - PayloadEntry.first.flags |= + PayloadEntry.first.Payload.flags |= static_cast(xpti::payload_flag_t::PayloadRegistered); Payload->flags |= static_cast(xpti::payload_flag_t::PayloadRegistered); @@ -1047,7 +1106,7 @@ class Tracepoints { } // Now, we need to create the actually payload for this instance that we // will be passing back to the caller - return PayloadInstance{Key, &PayloadEntry.first}; + return PayloadInstance{Key, &PayloadEntry.first.Payload}; } /// @brief Registers a new tracepoint with the given payload. @@ -1179,25 +1238,57 @@ class Tracepoints { uint64_t FileId = 0, FuncId = 0; int LineNo = 0, ColNo = 0; - // If the payload's function name is available, add it to the string table - // and get its id - if ((Payload->flags & - static_cast(xpti::payload_flag_t::NameAvailable))) { - // Add the kernel name/function name to the string table - FuncId = MStringTableRef.add(Payload->name, &Payload->name); - } + if (g_use_strict_hash) { + // If the payload's function name is available, add it to the string table + // and get its id + if ((Payload->flags & + static_cast(xpti::payload_flag_t::NameAvailable))) { + // Add the kernel name/function name to the string table + FuncId = MStringTableRef.add(Payload->name, &Payload->name); + } - // If the payload's source file is available, add it to the string table - // and get its id Also, get the line number and column number from the - // payload - if ((Payload->flags & - static_cast(xpti::payload_flag_t::SourceFileAvailable))) { - // Add source file information ot string table - FileId = MStringTableRef.add(Payload->source_file, &Payload->source_file); - LineNo = Payload->line_no; - ColNo = Payload->column_no; - } + // If the payload's source file is available, add it to the string table + // and get its id + if ((Payload->flags & + static_cast(xpti::payload_flag_t::SourceFileAvailable))) { + // Add source file information ot string table + FileId = + MStringTableRef.add(Payload->source_file, &Payload->source_file); + } + } else { + // If the payload's function name is available, generate a fast hash as + // its ID; Since reverse lookup is not necessary for callback functions, + // we have avoided using the string tables + if ((Payload->flags & + static_cast(xpti::payload_flag_t::NameAvailable))) { + // Add the kernel name/function name to the string table + FuncId = xpti::hash::fnv1a(Payload->name); + } else { + Payload->name = xpti::g_unknown_function; + Payload->flags |= + static_cast(xpti::payload_flag_t::NameAvailable); + // If the function name is not available, we will use the global unknown + FuncId = xpti::hash::fnv1a(Payload->name); + } + // If the payload's source file is available, generate a fast hash as its + // ID; Since reverse lookup is not necessary for callback functions, we + // have avoided using the string tables + if ((Payload->flags & + static_cast(xpti::payload_flag_t::SourceFileAvailable))) { + // Add source file information ot string table + FileId = xpti::hash::fnv1a(Payload->source_file); + } else { + Payload->source_file = xpti::g_unknown_file; + Payload->flags |= + static_cast(xpti::payload_flag_t::SourceFileAvailable); + // If the source file is not available, we will use the global unknown + FileId = xpti::hash::fnv1a(Payload->source_file); + } + } + // Get the line number and column number from the payload + LineNo = Payload->line_no; + ColNo = Payload->column_no; UId = xpti::make_uid128(FileId, FuncId, LineNo, ColNo); // Update the fields of Payload that will remain invariant and is for use // by legacy API that deals with 64-bit universal IDs @@ -1854,6 +1945,7 @@ class Framework { Framework() : MUniversalIDs(1), MTracepoints(MStringTableRef), MTraceEnabled(false) { // Load all subscribers on construction + MSubscribers.loadFromEnvironmentVariable(); MTraceEnabled = (g_helper.checkTraceEnv() && MSubscribers.hasValidSubscribers()); @@ -2037,7 +2129,26 @@ class Framework { return MTracepoints.addMetadata(Event, Key, ValueID); } - /// @brief Wrapper for creating a trace event + /// + /// @brief Creates a new trace event with the specified payload and + /// attributes. + /// + /// @details + /// This function allocates and initializes a new trace event using the + /// provided payload, instance number, event type, and activity type. It sets + /// the appropriate flags to indicate the availability of event and activity + /// types. If the payload or instance number is invalid, or if event creation + /// fails, the function returns nullptr. + /// + /// @param Payload Pointer to the payload describing the tracepoint context. + /// @param InstanceNo Pointer to a variable holding the instance number for + /// the event. This value is returned to the caller and can be used to + /// identify the specific occurrence of the event. + /// @param EventType The type of the event (e.g., algorithm, barrier, etc.). + /// @param ActivityType The activity type associated with the event. + /// @return Pointer to the newly created trace event data, or nullptr on + /// failure. + /// xpti::trace_event_data_t *newEvent(const xpti::payload_t *Payload, uint64_t *InstanceNo, uint16_t EventType, xpti::trace_activity_type_t ActivityType) { @@ -2062,6 +2173,19 @@ class Framework { MTracepoints.releaseEvent(event); } + /// + /// @brief Finds and returns a trace event by its universal ID. + /// + /// @details + /// This function attempts to locate a trace event associated with the given + /// 64-bit universal ID. If the ID is invalid or does not correspond to a + /// valid trace point, the function returns nullptr. Otherwise, it returns a + /// pointer to the associated trace event data. + /// + /// @param UniversalID The 64-bit universal identifier for the trace event. + /// @return Pointer to the associated trace_event_data_t if found and valid, + /// nullptr otherwise. + /// inline const xpti::trace_event_data_t *findEvent(uint64_t UniversalID) { if (UniversalID == xpti::invalid_uid) return nullptr; @@ -2078,10 +2202,39 @@ class Framework { return nullptr; } + /// + /// @brief Looks up and returns a trace event by its universal ID. + /// + /// @details + /// Searches for a trace event associated with the specified 64-bit universal + /// ID. If the ID is valid and corresponds to an existing trace event, a + /// pointer to the associated xpti_trace_event_t is returned. Otherwise, + /// nullptr is returned. + /// + /// @param UId The 64-bit universal identifier for the trace event. + /// @return Pointer to the associated xpti_trace_event_t if found, nullptr + /// otherwise. + /// inline const xpti_trace_event_t *lookupEvent(uint64_t UId) { return MTracepoints.lookupEventData(UId); } + /// + /// @brief Initializes a trace stream with the specified parameters. + /// + /// @details + /// Sets up the subscriber infrastructure for the given stream name and + /// version information. If either the stream name or version string is null, + /// the function returns XPTI_RESULT_INVALIDARG. Otherwise, it initializes the + /// subscribers for the stream and returns XPTI_RESULT_SUCCESS. + /// + /// @param Stream Name of the stream to initialize. + /// @param MajorRevision Major version number of the stream interface. + /// @param MinorRevision Minor version number of the stream interface. + /// @param VersionString Version string describing the stream. + /// @return xpti::result_t XPTI_RESULT_SUCCESS on success, + /// XPTI_RESULT_INVALIDARG on invalid arguments. + /// xpti::result_t initializeStream(const char *Stream, uint32_t MajorRevision, uint32_t MinorRevision, const char *VersionString) { @@ -2097,11 +2250,23 @@ class Framework { return (uint8_t)MStreamStringTable.add(StreamName); } + /// + /// @brief Closes all active trace streams. + /// + /// @details + /// Iterates through all currently open trace streams and performs the + /// necessary cleanup and resource deallocation for each. After this function + /// is called, no trace streams will remain open. + /// void closeAllStreams() { auto Table = MStreamStringTable.table(); StringTable::st_reverse_t::iterator it; for (it = Table.begin(); it != Table.end(); ++it) { +#ifndef XPTI_USE_VECTOR_LOOKUP xptiFinalize(it->second); +#else + xptiFinalize(*it); +#endif } } @@ -2127,7 +2292,7 @@ class Framework { } const char *lookupString(string_id_t ID) { - if (ID < 0) + if (ID == xpti::invalid_id) return nullptr; return MStringTableRef.query(ID); } @@ -2174,8 +2339,8 @@ class Framework { xpti_tracepoint_t *registerTracepoint(const char *FuncName, const char *FileName, uint32_t LineNo, - uint32_t ColumnNo) { - xpti::payload_t Payload(FuncName, FileName, LineNo, ColumnNo, nullptr); + uint32_t ColumnNo, void *CodePtrVa) { + xpti::payload_t Payload(FuncName, FileName, LineNo, ColumnNo, CodePtrVa); if (!xpti::is_valid_payload(&Payload)) Payload = xpti::unknown_payload(); @@ -2195,12 +2360,11 @@ class Framework { return MTracepoints.deleteTracepoint(Tracepoint); } - const xpti_tracepoint_t *registerTracepointScope(const char *FuncName, - const char *FileName, - uint32_t LineNo, - uint32_t ColumnNo) { + const xpti_tracepoint_t * + registerTracepointScope(const char *FuncName, const char *FileName, + uint32_t LineNo, uint32_t ColumnNo, void *CodePtrVa) { g_tls_temp_scope_data = - registerTracepoint(FuncName, FileName, LineNo, ColumnNo); + registerTracepoint(FuncName, FileName, LineNo, ColumnNo, CodePtrVa); return g_tls_temp_scope_data; } @@ -2310,6 +2474,14 @@ class Framework { TmpFramework = new Framework(); std::atomic_thread_fence(std::memory_order_release); MInstance.store(TmpFramework, std::memory_order_relaxed); + // Get the environment variable for strict hash usage + // This is done only once, so we use std::call_once to ensure thread + // safety and avoid multiple evaluations. + std::call_once(g_use_strict_hash_flag, [&]() { + auto strict_hash = + g_helper.getEnvironmentVariable("XPTI_USE_STRICT_HASH"); + g_use_strict_hash = strict_hash.size() > 0; + }); } } @@ -2847,7 +3019,7 @@ XPTI_EXPORT_API xpti::result_t xptiUnregisterStream(const char *StreamName) { /// (such as a loop or function) or a task, with the framework. Once registered, /// the payload can be associated with various performance events or traces, /// enabling detailed performance analysis and debugging. This will however be -/// deprecated in favor od xptiCreateTracepoint() which combines +/// deprecated in favor of xptiCreateTracepoint() which combines /// xptiRegisterPayload and xptiMakeEvent to ensure data consistency in the new /// architecture. /// @@ -2898,6 +3070,11 @@ XPTI_EXPORT_API uint64_t xptiRegisterPayload(xpti::payload_t *payload) { /// the line specified by LineNo where the tracepoint is created. This offers /// even more precise location information within the code. /// +/// @param CodePtrVa A pointer to the virtual address of the code where the +/// tracepoint is created. This is useful for low-level tracing and debugging, +/// allowing tools to directly reference the code location in memory. This +/// pointer can be null if the code pointer is not available or not needed. +/// /// @return Returns a pointer to the created `xpti_tracepoint_t` structure, /// which contains the metadata for the tracepoint. If the tracepoint cannot be /// created (e.g., due to memory constraints), a null pointer is returned. @@ -2908,12 +3085,11 @@ XPTI_EXPORT_API uint64_t xptiRegisterPayload(xpti::payload_t *payload) { /// scoped classes such as tracepoint_scope_t will automatically create a trace /// point and delete it when it goes out of scope. /// -XPTI_EXPORT_API xpti_tracepoint_t *xptiCreateTracepoint(const char *FuncName, - const char *FileName, - uint32_t LineNo, - uint32_t ColumnNo) { +XPTI_EXPORT_API xpti_tracepoint_t * +xptiCreateTracepoint(const char *FuncName, const char *FileName, + uint32_t LineNo, uint32_t ColumnNo, void *CodePtrVa) { auto &FW = xpti::Framework::instance(); - return FW.registerTracepoint(FuncName, FileName, LineNo, ColumnNo); + return FW.registerTracepoint(FuncName, FileName, LineNo, ColumnNo, CodePtrVa); } /// @brief Deletes a tracepoint that was previously created. @@ -3260,20 +3436,64 @@ XPTI_EXPORT_API void xptiForceSetTraceEnabled(bool YesOrNo) { xpti::Framework::instance().setTraceEnabled(YesOrNo); } +/// @brief Looks up and returns a trace event by its universal ID. +/// +/// @details +/// Retrieves a pointer to the trace event associated with the specified 64-bit +/// universal ID. Returns nullptr if the ID does not correspond to a valid +/// event. +/// +/// @param UId The 64-bit universal identifier for the trace event. +/// @return Pointer to the associated xpti_trace_event_t if found, nullptr +/// otherwise. + XPTI_EXPORT_API const xpti_trace_event_t *xptiLookupEvent(uint64_t UId) { auto &FW = xpti::Framework::instance(); return FW.lookupEvent(UId); } +/// @brief Looks up and returns a payload by its universal ID. +/// +/// @details +/// Retrieves a pointer to the payload associated with the specified 64-bit +/// universal ID. Returns nullptr if the ID does not correspond to a valid +/// payload. +/// +/// @param uid The 64-bit universal identifier for the payload. +/// @return Pointer to the associated xpti_payload_t if found, nullptr +/// otherwise. + XPTI_EXPORT_API const xpti_payload_t *xptiLookupPayload(uint64_t uid) { auto &FW = xpti::Framework::instance(); return FW.lookupPayload(uid); } +/// @brief Retrieves the current thread-local tracepoint scope data. +/// +/// @details +/// Returns a pointer to the thread-local tracepoint scope data structure, which +/// may be used for managing scope-specific tracing information in the current +/// thread. +/// +/// @return Pointer to the current thread-local xpti_tracepoint_t, or nullptr if +/// not set. + XPTI_EXPORT_API const xpti_tracepoint_t *xptiGetTracepointScopeData() { return g_tls_tracepoint_scope_data; } +/// @brief Sets the thread-local tracepoint scope data. +/// +/// @details +/// Associates the provided tracepoint scope data with the current thread. This +/// function is typically used to manage scope-specific tracing information on a +/// per-thread basis. +/// +/// @param Data Pointer to the xpti_tracepoint_t structure to set as the current +/// thread's scope data. +/// @return xpti::result_t Returns XPTI_RESULT_SUCCESS on success, or an +/// appropriate error code on failure. + XPTI_EXPORT_API xpti::result_t xptiSetTracepointScopeData(xpti_tracepoint_t *Data) { if (!Data) @@ -3287,31 +3507,99 @@ xptiSetTracepointScopeData(xpti_tracepoint_t *Data) { return xpti::result_t::XPTI_RESULT_SUCCESS; } +/// @brief Unsets the thread-local tracepoint scope data. +/// +/// @details +/// Clears the current thread's tracepoint scope data by resetting the +/// thread-local tracepoint pointer to nullptr and the thread-local universal ID +/// to an invalid value. This is typically used to clean up or reset tracing +/// state for the current thread. + XPTI_EXPORT_API void xptiUnsetTracepointScopeData() { g_tls_uid = xpti::invalid_uid; g_tls_tracepoint_scope_data = nullptr; } +/// @brief Registers a new tracepoint scope with the provided source location +/// information. +/// +/// @details +/// Creates and registers a tracepoint scope using the specified function name, +/// source file name, line number, column number, and code pointer address. This +/// information is used to uniquely identify and track the scope of traced code +/// regions for profiling or debugging purposes. +/// +/// @param FuncName Name of the function or kernel associated with the +/// tracepoint. +/// @param FileName Name of the source file where the tracepoint is located. +/// @param LineNo Line number in the source file. +/// @param ColumnNo Column number in the source file. +/// @param CodePtrVa Pointer to the code location (virtual address) associated +/// with this tracepoint. +/// @return Pointer to the registered xpti_tracepoint_t structure, or nullptr on +/// failure. + XPTI_EXPORT_API const xpti_tracepoint_t * xptiRegisterTracepointScope(const char *FuncName, const char *FileName, - uint32_t LineNo, uint32_t ColumnNo) { - return xpti::Framework::instance().registerTracepointScope(FuncName, FileName, - LineNo, ColumnNo); + uint32_t LineNo, uint32_t ColumnNo, + void *CodePtrVa) { + return xpti::Framework::instance().registerTracepointScope( + FuncName, FileName, LineNo, ColumnNo, CodePtrVa); } +/// @brief Enables or disables tracepoint scope self-notification. +/// +/// @details +/// Sets a global flag to control whether tracepoints notify themselves when +/// hit. When enabled, tracepoints will generate notifications for their own +/// scope, which can be useful for debugging or generating detailed trace +/// information. +/// +/// @param enableOrDisable Set to true to enable self-notification, false to +/// disable. + XPTI_EXPORT_API void xptiEnableTracepointScopeNotification(bool enableOrDisable) { xpti::g_tracepoint_self_notify = enableOrDisable; } +/// @brief Checks if tracepoint scope self-notification is enabled. +/// +/// @details +/// Returns the current state of the global flag controlling tracepoint scope +/// self-notification. If enabled, tracepoints will notify themselves when hit, +/// which can be useful for debugging or generating detailed trace information. +/// +/// @return true if self-notification is enabled, false otherwise. + XPTI_EXPORT_API bool xptiCheckTracepointScopeNotification() { return xpti::g_tracepoint_self_notify; } +/// @brief Retrieves the default stream ID used by the XPTI framework. +/// +/// @details +/// Returns the unique identifier associated with the default trace stream. +/// This ID is used internally to distinguish the default stream from other +/// user-defined or vendor-defined streams. +/// +/// @return The default stream ID as an 8-bit unsigned integer. + XPTI_EXPORT_API uint8_t xptiGetDefaultStreamID() { return xpti::g_default_stream_id; } +/// @brief Sets the default stream ID used by the XPTI framework. +/// +/// @details +/// Updates the global default stream identifier to the specified value. This ID +/// will be used as the default for trace events and streams unless explicitly +/// overridden elsewhere. +/// +/// @param DefaultStreamId The new default stream ID to set. +/// @return xpti::result_t Returns XPTI_RESULT_SUCCESS on success, or an +/// appropriate error code on failure. + XPTI_EXPORT_API xpti::result_t xptiSetDefaultStreamID(uint8_t DefaultStreamId) { if ((int8_t)DefaultStreamId < 0) return xpti::result_t::XPTI_RESULT_INVALIDARG; @@ -3319,10 +3607,27 @@ XPTI_EXPORT_API xpti::result_t xptiSetDefaultStreamID(uint8_t DefaultStreamId) { xpti::g_default_stream_id = DefaultStreamId; return xpti::result_t::XPTI_RESULT_SUCCESS; } +/// @brief Retrieves the default event type used by the XPTI framework. +/// +/// @details +/// Returns the default event type that is used when no specific event type is +/// provided during event creation. This type is used to categorize events into +/// different types for easier management and analysis. + XPTI_EXPORT_API xpti::trace_event_type_t xptiGetDefaultEventType() { return xpti::g_default_event_type; } +/// @brief Sets the default event type used by the XPTI framework. +/// @details +/// Updates the global default event type to the specified value. This type will +/// be used as the default for trace events unless explicitly overridden during +/// event creation. +/// @param DefaultEventType The new default event type to set. +/// @return xpti::result_t Returns XPTI_RESULT_SUCCESS on success, or an +/// appropriate error code on failure. If the provided event type is invalid, +/// it returns XPTI_RESULT_INVALIDARG. + XPTI_EXPORT_API xpti::result_t xptiSetDefaultEventType(xpti::trace_event_type_t DefaultEventType) { if (DefaultEventType == xpti::trace_event_type_t::unknown_event) @@ -3332,10 +3637,25 @@ xptiSetDefaultEventType(xpti::trace_event_type_t DefaultEventType) { return xpti::result_t::XPTI_RESULT_SUCCESS; } +/// @brief Retrieves the default trace type used by the XPTI framework. +/// @details +/// Returns the default trace type that is used when no specific trace type is +/// provided during event creation. This type is used to categorize trace events +/// into different types for easier management and analysis. XPTI_EXPORT_API xpti::trace_point_type_t xptiGetDefaultTraceType() { return xpti::g_default_trace_type; } +/// @brief Sets the default trace type used by the XPTI framework. +/// @details +/// Updates the global default trace type to the specified value. This type will +/// be used as the default for trace events unless explicitly overridden during +/// event creation. +/// @param DefaultTraceType The new default trace type to set. +/// @return xpti::result_t Returns XPTI_RESULT_SUCCESS on success, or an +/// appropriate error code on failure. If the provided trace type is invalid, +/// it returns XPTI_RESULT_INVALIDARG. + XPTI_EXPORT_API xpti::result_t xptiSetDefaultTraceType(xpti::trace_point_type_t DefaultTraceType) { if (DefaultTraceType == xpti::trace_point_type_t::unknown_type) @@ -3345,6 +3665,14 @@ xptiSetDefaultTraceType(xpti::trace_point_type_t DefaultTraceType) { return xpti::result_t::XPTI_RESULT_SUCCESS; } +/// @brief Releases a trace event data structure. +/// @details +/// This function is used to release a trace event data structure that was +/// previously created or retrieved. It is important to call this function to +/// properly manage memory and avoid leaks in the XPTI framework. +/// @param Event A pointer to the `xpti::trace_event_data_t` structure to be +/// released. + XPTI_EXPORT_API void xptiReleaseEvent(xpti::trace_event_data_t *Event) { return xpti::Framework::instance().releaseEvent(Event); } diff --git a/xptifw/unit_test/xpti_api_tests.cpp b/xptifw/unit_test/xpti_api_tests.cpp index 343b7f72c5931..d41258eda17f5 100644 --- a/xptifw/unit_test/xpti_api_tests.cpp +++ b/xptifw/unit_test/xpti_api_tests.cpp @@ -32,18 +32,18 @@ TEST_F(xptiApiTest, xptiRegisterStringBadInput) { char *TStr; auto ID = xptiRegisterString(nullptr, nullptr); - EXPECT_EQ(ID, xpti::invalid_id); + EXPECT_EQ(ID, xpti::invalid_id); ID = xptiRegisterString(nullptr, &TStr); - EXPECT_EQ(ID, xpti::invalid_id); + EXPECT_EQ(ID, xpti::invalid_id); ID = xptiRegisterString("foo", nullptr); - EXPECT_EQ(ID, xpti::invalid_id); + EXPECT_EQ(ID, xpti::invalid_id); } TEST_F(xptiApiTest, xptiRegisterStringGoodInput) { char *TStr = nullptr; auto ID = xptiRegisterString("foo", &TStr); - EXPECT_NE(ID, xpti::invalid_id); + EXPECT_NE(ID, xpti::invalid_id<>); EXPECT_NE(TStr, nullptr); EXPECT_STREQ("foo", TStr); } @@ -59,7 +59,7 @@ TEST_F(xptiApiTest, xptiLookupStringGoodInput) { char *TStr = nullptr; auto ID = xptiRegisterString("foo", &TStr); - EXPECT_NE(ID, xpti::invalid_id); + EXPECT_NE(ID, xpti::invalid_id<>); EXPECT_NE(TStr, nullptr); EXPECT_STREQ("foo", TStr); @@ -120,7 +120,8 @@ TEST_F(xptiApiTest, xptiPayloadBadInput) { EXPECT_NE(NewEv, nullptr); EXPECT_NE(NewEv->reserved.payload->name, nullptr); - EXPECT_EQ(std::string(NewEv->reserved.payload->name), std::string("unknown")); + EXPECT_EQ(std::string(NewEv->reserved.payload->name), + std::string("")); } TEST_F(xptiApiTest, xptiGetUniqueId) { @@ -316,12 +317,12 @@ TEST_F(xptiApiTest, xptiQueryLookupPayloadBadInput) { TEST_F(xptiApiTest, xptiRegisterStreamBadInput) { auto ID = xptiRegisterStream(nullptr); - EXPECT_EQ(ID, (uint8_t)xpti::invalid_id); + EXPECT_EQ(ID, (uint8_t)xpti::invalid_id<>); } TEST_F(xptiApiTest, xptiRegisterStreamGoodInput) { auto ID = xptiRegisterStream("foo"); - EXPECT_NE(ID, xpti::invalid_id); + EXPECT_NE(ID, xpti::invalid_id<>); auto NewID = xptiRegisterStream("foo"); EXPECT_EQ(ID, NewID); } @@ -333,7 +334,7 @@ TEST_F(xptiApiTest, xptiUnregisterStreamBadInput) { TEST_F(xptiApiTest, xptiUnregisterStreamGoodInput) { auto ID = xptiRegisterStream("foo"); - EXPECT_NE(ID, xpti::invalid_id); + EXPECT_NE(ID, xpti::invalid_id<>); auto Result = xptiUnregisterStream("NoSuchStream"); EXPECT_EQ(Result, xpti::result_t::XPTI_RESULT_NOTFOUND); // Event though stream exists, no callbacks registered @@ -376,8 +377,8 @@ TEST_F(xptiApiTest, xptiCreateTracepointBadInput) { EXPECT_NE(Result, nullptr); auto Payload = Result->payload_ref(); EXPECT_NE(Payload->name, nullptr); - EXPECT_EQ(std::string(Payload->name), std::string("unknown")); - EXPECT_EQ(std::string(Payload->source_file), std::string("unknown-file")); + EXPECT_EQ(std::string(Payload->name), std::string("")); + EXPECT_EQ(std::string(Payload->source_file), std::string("")); EXPECT_EQ(Payload->line_no, 0); EXPECT_EQ(Payload->column_no, 0); } diff --git a/xptifw/unit_test/xpti_correctness_tests.cpp b/xptifw/unit_test/xpti_correctness_tests.cpp index a226173d1cde7..29144c0c4ed7d 100644 --- a/xptifw/unit_test/xpti_correctness_tests.cpp +++ b/xptifw/unit_test/xpti_correctness_tests.cpp @@ -64,7 +64,7 @@ TEST_F(xptiCorrectnessTest, xptiMakeEvent) { TEST_F(xptiCorrectnessTest, xptiUnregisterStream) { xptiForceSetTraceEnabled(true); auto ID = xptiRegisterStream("foo1"); - EXPECT_NE(ID, xpti::invalid_id); + EXPECT_NE(ID, xpti::invalid_id<>); auto Result = xptiUnregisterStream("foo2"); EXPECT_EQ(Result, xpti::result_t::XPTI_RESULT_NOTFOUND); // Event though stream exists, no callbacks registered @@ -72,7 +72,7 @@ TEST_F(xptiCorrectnessTest, xptiUnregisterStream) { EXPECT_EQ(NewResult, xpti::result_t::XPTI_RESULT_NOTFOUND); // Register again ID = xptiRegisterStream("foo1"); - EXPECT_NE(ID, xpti::invalid_id); + EXPECT_NE(ID, xpti::invalid_id<>); Result = xptiRegisterCallback( ID, (uint16_t)xpti::trace_point_type_t::graph_create, tpCallback); EXPECT_EQ(Result, xpti::result_t::XPTI_RESULT_SUCCESS); @@ -184,7 +184,7 @@ TEST_F(xptiCorrectnessTest, xptiCreateTracepoint) { TEST_F(xptiCorrectnessTest, xptiRegisterString) { char *TStr = nullptr; auto ID = xptiRegisterString("foo", &TStr); - EXPECT_NE(ID, xpti::invalid_id); + EXPECT_NE(ID, xpti::invalid_id<>); EXPECT_NE(TStr, nullptr); EXPECT_STREQ("foo", TStr); @@ -255,9 +255,7 @@ TEST_F(xptiCorrectnessTest, xptiTracePointTest) { void nestedScopeTest(xpti::payload_t *p, std::vector &uids) { xpti::framework::tracepoint_scope_t t(p->name, p->source_file, p->line_no, - p->column_no, false); - xpti::hash_t Hash; - + p->column_no, nullptr, false); auto Tuid = t.uid64(); uids.push_back(Tuid); @@ -298,7 +296,7 @@ TEST_F(xptiCorrectnessTest, xptiTracePointScopeTest) { uint64_t uid; { xpti::framework::tracepoint_scope_t t(p1.name, p1.source_file, p1.line_no, - p1.column_no, false); + p1.column_no, nullptr, false); uid = t.uid64(); EXPECT_NE(t.traceEvent(), nullptr); auto ScopeData = xptiGetTracepointScopeData();