Skip to content

Commit

Permalink
[XPTI] Add new class xpti::framework::tracepoint_t (#4462)
Browse files Browse the repository at this point in the history
+ Supports the creation of universal IDs and posting
  them to TLS storage. Public entry points will need
  to use the new approach to propagate Universal IDs
  through multiple layers of the SW Stack.
+ Added tests to ensure the correctness of new APIs
  to support this feature and the functionality of
  the tracepoint object.
+ New methods added to the spec:
  - xptiRegisterPayload
  - xptiQueryPayloadByUID

Signed-off-by: Vasanth Tovinkere <[email protected]>
  • Loading branch information
tovinkere authored Sep 5, 2021
1 parent d21082f commit e61dcc6
Show file tree
Hide file tree
Showing 7 changed files with 306 additions and 10 deletions.
34 changes: 25 additions & 9 deletions xpti/include/xpti_data_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ enum class payload_flag_t {
ColumnInfoAvailable = 1 << 4,
/// Caller/Callee stack trace available when source/kernel info not available
StackTraceAvailable = 1 << 5,
/// Payload has been registered with the framework
PayloadRegistered = 1 << 15,
// A 64-bit hash is already available for this payload
HashAvailable = 2 << 16
};
Expand Down Expand Up @@ -172,7 +174,9 @@ struct payload_t {
source_file = nullptr; ///< Invalid source file string pointer
line_no = invalid_id; ///< Invalid line number
column_no = invalid_id; ///< Invalid column number
flags = (uint64_t)payload_flag_t::CodePointerAvailable;
if (codeptr) {
flags = (uint64_t)payload_flag_t::CodePointerAvailable;
}
}

// If neither an address or the fully identifyable source file name and
Expand All @@ -184,15 +188,21 @@ struct payload_t {
code_ptr_va = nullptr;
name = func_name; ///< Invalid name string pointer
source_file = nullptr; ///< Invalid source file string pointer
flags = (uint64_t)(payload_flag_t::NameAvailable);
if (func_name) {
flags = (uint64_t)(payload_flag_t::NameAvailable);
}
}

payload_t(const char *func_name, void *codeptr) {
code_ptr_va = codeptr;
name = func_name; ///< Invalid name string pointer
source_file = nullptr; ///< Invalid source file string pointer
flags = (uint64_t)payload_flag_t::NameAvailable |
(uint64_t)payload_flag_t::CodePointerAvailable;
if (func_name) {
flags = (uint64_t)(payload_flag_t::NameAvailable);
}
if (codeptr) {
flags |= (uint64_t)payload_flag_t::CodePointerAvailable;
}
}

// When the end user opts out of preserving the code location information and
Expand Down Expand Up @@ -228,11 +238,17 @@ struct payload_t {
source_file = sf;
line_no = line;
column_no = col;
flags = (uint64_t)payload_flag_t::NameAvailable |
(uint64_t)payload_flag_t::SourceFileAvailable |
(uint64_t)payload_flag_t::LineInfoAvailable |
(uint64_t)payload_flag_t::ColumnInfoAvailable |
(uint64_t)payload_flag_t::CodePointerAvailable;
if (kname) {
flags = (uint64_t)payload_flag_t::NameAvailable;
}
if (sf) {
flags |= (uint64_t)payload_flag_t::SourceFileAvailable |
(uint64_t)payload_flag_t::LineInfoAvailable |
(uint64_t)payload_flag_t::ColumnInfoAvailable;
}
if (codeptr) {
flags |= (uint64_t)payload_flag_t::CodePointerAvailable;
}
}

int32_t name_sid() const { return (int32_t)(uid.p2 & 0x00000000ffffffff); }
Expand Down
21 changes: 21 additions & 0 deletions xpti/include/xpti_trace_framework.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,17 @@ XPTI_EXPORT_API xpti::string_id_t xptiRegisterString(const char *string,
/// @return A reference to the string identified by the string ID.
XPTI_EXPORT_API const char *xptiLookupString(xpti::string_id_t id);

/// @brief Register a payload with the framework
/// @details Since a payload may contain multiple strings that may have been
/// defined on the stack, it is recommended the payload object is registered
/// with the system as soon as possible. The framework will register all the
/// strings in the payload in the string table and replace the pointers to
/// strings on the stack with the pointers from the string table that should be
/// valid for the lifetime of the application.
/// @param payload The payload object that is registered with the system.
/// @return The unique hash value for the payload.
XPTI_EXPORT_API uint64_t xptiRegisterPayload(xpti::payload_t *payload);

/// @brief Register a stream by its name and get a stream ID
/// @details When events in a given stream have to be notified to the
/// subscribers, the stream ID to which the events belong to is required. This
Expand Down Expand Up @@ -252,6 +263,14 @@ XPTI_EXPORT_API const xpti::trace_event_data_t *xptiFindEvent(uint64_t uid);
XPTI_EXPORT_API const xpti::payload_t *
xptiQueryPayload(xpti::trace_event_data_t *lookup_object);

/// @brief Retrieves the payload information associated with an universal ID
/// @details An universal ID references the unique payload it represents and
/// this function allows you to query the payload with the universal ID.
///
/// @param uid The universal ID for which the payload is to be retrieved.
/// @return The payload data structure pointer for the event.
XPTI_EXPORT_API const xpti::payload_t *xptiQueryPayloadByUID(uint64_t uid);

/// @brief Registers a callback for a trace point type
/// @details Subscribers receive notifications to the trace point types they
/// register a callback with. This function allows subscribers to register the
Expand Down Expand Up @@ -400,6 +419,7 @@ typedef void (*xpti_finalize_t)(const char *);
typedef uint64_t (*xpti_get_unique_id_t)();
typedef xpti::string_id_t (*xpti_register_string_t)(const char *, char **);
typedef const char *(*xpti_lookup_string_t)(xpti::string_id_t);
typedef uint64_t (*xpti_register_payload_t)(xpti::payload_t *);
typedef uint8_t (*xpti_register_stream_t)(const char *);
typedef xpti::result_t (*xpti_unregister_stream_t)(const char *);
typedef uint16_t (*xpti_register_user_defined_tp_t)(const char *, uint8_t);
Expand All @@ -410,6 +430,7 @@ typedef xpti::trace_event_data_t *(*xpti_make_event_t)(
typedef const xpti::trace_event_data_t *(*xpti_find_event_t)(int64_t);
typedef const xpti::payload_t *(*xpti_query_payload_t)(
xpti::trace_event_data_t *);
typedef const xpti::payload_t *(*xpti_query_payload_by_uid_t)(uint64_t uid);
typedef xpti::result_t (*xpti_register_cb_t)(uint8_t, uint16_t,
xpti::tracepoint_callback_api_t);
typedef xpti::result_t (*xpti_unregister_cb_t)(uint8_t, uint16_t,
Expand Down
115 changes: 115 additions & 0 deletions xpti/include/xpti_trace_framework.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
//
#pragma once
#include <cstdint>
#include <memory>
#include <sstream>
#include <thread>

#include "xpti_data_types.h"
#include "xpti_trace_framework.h"
Expand Down Expand Up @@ -269,6 +271,7 @@ class PlatformHelper {
} // namespace utils

namespace framework {
static thread_local uint64_t g_tls_uid = xpti::invalid_uid;
constexpr uint16_t signal = (uint16_t)xpti::trace_point_type_t::signal;
constexpr uint16_t graph_create =
(uint16_t)xpti::trace_point_type_t::graph_create;
Expand Down Expand Up @@ -317,5 +320,117 @@ class scoped_notify {
const void *m_user_data;
uint64_t m_instance;
};

// --------------- Commented section of the code -------------
//
// github.com/bombela/backward-cpp/blob/master/backward.hpp
//
// Need to figure out the process for considering 3rd party
// code that helps with addressing the gaps when the developer
// doesn't opt-in.
//------------------------------------------------------------
// #include "backward.hpp"
// class backtrace_t {
// public:
// backtrace_t(int levels = 2) {
// m_st.load_here(levels);
// m_tr.load_stacktrace(m_st);
// m_parent = m_tr.resolve(m_st[1]);
// m_curr = m_tr.resolve(m_st[0]);
// if(m_parent.source.filename) {
// m_payload = xpti::payload_t(m_curr.source.function,
// m_parent.source.filename, m_parent.source.line, 0, m_curr.addr);
// }
// else {
// m_packed_string = m_parent.source.function + std::string("::") +
// m_curr.source.function; m_payload =
// xpti::payload_t(m_curr.source.function, m_packed_string.c_str(),
// m_curr.addr);
// }
// }
//
// xpti::payload_t *payload() { return &m_payload;}
// private:
// backward::StackTrace m_st;
// backward::TraceResolver m_tr;
// backward::ResolvedTrace m_curr, m_parent;
// std::string m_packed_string;
// xpti::payload_t m_payload;
// };

/// @brief Tracepoint data type allows the construction of Universal ID
/// @details The tracepoint data type builds on the payload data type by
/// combining the functionality of payload and xpti::makeEvent() to create the
/// unique Universal ID and stash it in the TLS for use by downstream layers in
/// the SW stack.
///
/// Usage:-
/// #ifdef XPTI_TRACE_ENABLED
/// xpti::payload_t p, *payload = &p;
/// #ifdef SYCL_TOOL_PROFILE
/// // sycl::detail::code_location cLoc =
/// // sycl::detail::code_location::current();
/// if(cLoc.valid())
/// p = xpti::payload_t(cLoc.functionname(), cLoc.fileName(),
/// cLoc.lineNumber(), cLoc.columnNumber(), codeptr);
/// else
/// p = xpti::payload_t(KernelInfo.funcName(), KernelInfo.sourceFileName(),
/// KernelInfo.lineNo(), KernelInfor.columnNo(), codeptr);
/// #else
/// xpti::framework::backtrace_t b;
/// payload = b.payload();
/// #endif
/// xpti::tracepoint_t t(payload);
/// #endif
///
/// See also: xptiTracePointTest in xpti_correctness_tests.cpp
class tracepoint_t {
public:
// Constructor that makes calls to xpti API layer to register strings and
// create the Universal ID that is stored in the TLS entry for lookup
tracepoint_t(xpti::payload_t *p) : m_payload(nullptr), m_top(false) {
if (p) {
// We expect the payload input has been populated with the information
// available at that time
uint64_t uid = g_tls_uid;
if (uid != xpti::invalid_uid) {
// We already have a parent SW layer that has a tracepoint defined
m_payload = xptiQueryPayloadByUID(uid);
} else {
m_top = true;
uid = xptiRegisterPayload(p);
if (uid != xpti::invalid_uid) {
g_tls_uid = uid;
m_payload = xptiQueryPayloadByUID(uid);
}
}
}
}
~tracepoint_t() {
if (m_top) {
g_tls_uid = xpti::invalid_uid;
}
}

// The payload object that is returned will have the UID object populated and
// can be looked up in the xpti lookup APIs or be used to make an event.
const payload_t *payload() { return m_payload; }

uint64_t universal_id() {
if (m_payload &&
(m_payload->flags &
static_cast<uint64_t>(xpti::payload_flag_t::HashAvailable))) {
return m_payload->internal;
} else {
return xpti::invalid_uid;
}
}

private:
/// The payload data structure that is prepared from code_location(),
/// caller_callee string or kernel name/codepointer based on the opt-in flag.
const payload_t *m_payload;
bool m_top;
};
} // namespace framework
} // namespace xpti
24 changes: 24 additions & 0 deletions xpti/src/xpti_proxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ enum functions_t {
XPTI_ADD_METADATA,
XPTI_QUERY_METADATA,
XPTI_TRACE_ENABLED,
XPTI_REGISTER_PAYLOAD,
XPTI_QUERY_PAYLOAD_BY_UID,

// All additional functions need to appear before
// the XPTI_FW_API_COUNT enum
Expand All @@ -45,13 +47,15 @@ class ProxyLoader {
{XPTI_GET_UNIQUE_ID, "xptiGetUniqueId"},
{XPTI_REGISTER_STRING, "xptiRegisterString"},
{XPTI_LOOKUP_STRING, "xptiLookupString"},
{XPTI_REGISTER_PAYLOAD, "xptiRegisterPayload"},
{XPTI_REGISTER_STREAM, "xptiRegisterStream"},
{XPTI_UNREGISTER_STREAM, "xptiUnregisterStream"},
{XPTI_REGISTER_USER_DEFINED_TP, "xptiRegisterUserDefinedTracePoint"},
{XPTI_REGISTER_USER_DEFINED_ET, "xptiRegisterUserDefinedEventType"},
{XPTI_MAKE_EVENT, "xptiMakeEvent"},
{XPTI_FIND_EVENT, "xptiFindEvent"},
{XPTI_QUERY_PAYLOAD, "xptiQueryPayload"},
{XPTI_QUERY_PAYLOAD_BY_UID, "xptiQueryPayloadByUID"},
{XPTI_REGISTER_CALLBACK, "xptiRegisterCallback"},
{XPTI_UNREGISTER_CALLBACK, "xptiUnregisterCallback"},
{XPTI_NOTIFY_SUBSCRIBERS, "xptiNotifySubscribers"},
Expand Down Expand Up @@ -203,6 +207,16 @@ XPTI_EXPORT_API const char *xptiLookupString(xpti::string_id_t id) {
return nullptr;
}

XPTI_EXPORT_API uint64_t xptiRegisterPayload(xpti::payload_t *payload) {
if (xpti::g_loader.noErrors()) {
auto f = xpti::g_loader.functionByIndex(XPTI_REGISTER_PAYLOAD);
if (f) {
return (*(xpti_register_payload_t)f)(payload);
}
}
return xpti::invalid_uid;
}

XPTI_EXPORT_API uint8_t xptiRegisterStream(const char *stream_name) {
if (xpti::g_loader.noErrors()) {
auto f = xpti::g_loader.functionByIndex(XPTI_REGISTER_STREAM);
Expand Down Expand Up @@ -256,6 +270,16 @@ xptiQueryPayload(xpti::trace_event_data_t *lookup_object) {
return nullptr;
}

XPTI_EXPORT_API const xpti::payload_t *xptiQueryPayloadByUID(uint64_t uid) {
if (xpti::g_loader.noErrors()) {
auto f = xpti::g_loader.functionByIndex(XPTI_QUERY_PAYLOAD_BY_UID);
if (f) {
return (*(xpti_query_payload_by_uid_t)f)(uid);
}
}
return nullptr;
}

XPTI_EXPORT_API xpti::result_t
xptiRegisterCallback(uint8_t stream_id, uint16_t trace_type,
xpti::tracepoint_callback_api_t cb) {
Expand Down
Loading

0 comments on commit e61dcc6

Please sign in to comment.