Skip to content

Commit a484603

Browse files
committed
[XPTI] Added new class xpti::framework::tracepoint_t
+ 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]>
1 parent 7d8ef08 commit a484603

File tree

7 files changed

+301
-10
lines changed

7 files changed

+301
-10
lines changed

xpti/include/xpti_data_types.h

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ enum class payload_flag_t {
9292
ColumnInfoAvailable = 1 << 4,
9393
/// Caller/Callee stack trace available when source/kernel info not available
9494
StackTraceAvailable = 1 << 5,
95+
/// Payload has been registered with the framework
96+
PayloadRegistered = 1 << 15,
9597
// A 64-bit hash is already available for this payload
9698
HashAvailable = 2 << 16
9799
};
@@ -172,7 +174,9 @@ struct payload_t {
172174
source_file = nullptr; ///< Invalid source file string pointer
173175
line_no = invalid_id; ///< Invalid line number
174176
column_no = invalid_id; ///< Invalid column number
175-
flags = (uint64_t)payload_flag_t::CodePointerAvailable;
177+
if (codeptr) {
178+
flags = (uint64_t)payload_flag_t::CodePointerAvailable;
179+
}
176180
}
177181

178182
// If neither an address or the fully identifyable source file name and
@@ -184,15 +188,21 @@ struct payload_t {
184188
code_ptr_va = nullptr;
185189
name = func_name; ///< Invalid name string pointer
186190
source_file = nullptr; ///< Invalid source file string pointer
187-
flags = (uint64_t)(payload_flag_t::NameAvailable);
191+
if (func_name) {
192+
flags = (uint64_t)(payload_flag_t::NameAvailable);
193+
}
188194
}
189195

190196
payload_t(const char *func_name, void *codeptr) {
191197
code_ptr_va = codeptr;
192198
name = func_name; ///< Invalid name string pointer
193199
source_file = nullptr; ///< Invalid source file string pointer
194-
flags = (uint64_t)payload_flag_t::NameAvailable |
195-
(uint64_t)payload_flag_t::CodePointerAvailable;
200+
if (func_name) {
201+
flags = (uint64_t)(payload_flag_t::NameAvailable);
202+
}
203+
if (codeptr) {
204+
flags |= (uint64_t)payload_flag_t::CodePointerAvailable;
205+
}
196206
}
197207

198208
// When the end user opts out of preserving the code location information and
@@ -228,11 +238,17 @@ struct payload_t {
228238
source_file = sf;
229239
line_no = line;
230240
column_no = col;
231-
flags = (uint64_t)payload_flag_t::NameAvailable |
232-
(uint64_t)payload_flag_t::SourceFileAvailable |
233-
(uint64_t)payload_flag_t::LineInfoAvailable |
234-
(uint64_t)payload_flag_t::ColumnInfoAvailable |
235-
(uint64_t)payload_flag_t::CodePointerAvailable;
241+
if (kname) {
242+
flags = (uint64_t)payload_flag_t::NameAvailable;
243+
}
244+
if (sf) {
245+
flags |= (uint64_t)payload_flag_t::SourceFileAvailable |
246+
(uint64_t)payload_flag_t::LineInfoAvailable |
247+
(uint64_t)payload_flag_t::ColumnInfoAvailable;
248+
}
249+
if (codeptr) {
250+
flags |= (uint64_t)payload_flag_t::CodePointerAvailable;
251+
}
236252
}
237253

238254
int32_t name_sid() const { return (int32_t)(uid.p2 & 0x00000000ffffffff); }

xpti/include/xpti_trace_framework.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,17 @@ XPTI_EXPORT_API xpti::string_id_t xptiRegisterString(const char *string,
9696
/// @return A reference to the string identified by the string ID.
9797
XPTI_EXPORT_API const char *xptiLookupString(xpti::string_id_t id);
9898

99+
/// @brief Register a payload with the framework
100+
/// @details Since a payload may contain multiple strings that may have been
101+
/// defined on the stack, it is recommended the payload object is registered
102+
/// with the system as soon as possible. The framework will register all the
103+
/// strings in the payload in the string table and replace the pointers to
104+
/// strings on the stack with the pointers from the string table that should be
105+
/// valid for the lifetime of the application.
106+
/// @param payload The payload object that is registered with the system.
107+
/// @return The unique hash value for the payload.
108+
XPTI_EXPORT_API uint64_t xptiRegisterPayload(xpti::payload_t *payload);
109+
99110
/// @brief Register a stream by its name and get a stream ID
100111
/// @details When events in a given stream have to be notified to the
101112
/// subscribers, the stream ID to which the events belong to is required. This
@@ -252,6 +263,14 @@ XPTI_EXPORT_API const xpti::trace_event_data_t *xptiFindEvent(uint64_t uid);
252263
XPTI_EXPORT_API const xpti::payload_t *
253264
xptiQueryPayload(xpti::trace_event_data_t *lookup_object);
254265

266+
/// @brief Retrieves the payload information associated with an universal ID
267+
/// @details An universal ID references the unique payload it represents and
268+
/// this function allows you to query the payload with the universal ID.
269+
///
270+
/// @param uid The universal ID for which the payload is to be retrieved.
271+
/// @return The payload data structure pointer for the event.
272+
XPTI_EXPORT_API const xpti::payload_t *xptiQueryPayloadByUID(uint64_t uid);
273+
255274
/// @brief Registers a callback for a trace point type
256275
/// @details Subscribers receive notifications to the trace point types they
257276
/// register a callback with. This function allows subscribers to register the
@@ -400,6 +419,7 @@ typedef void (*xpti_finalize_t)(const char *);
400419
typedef uint64_t (*xpti_get_unique_id_t)();
401420
typedef xpti::string_id_t (*xpti_register_string_t)(const char *, char **);
402421
typedef const char *(*xpti_lookup_string_t)(xpti::string_id_t);
422+
typedef uint64_t (*xpti_register_payload_t)(xpti::payload_t *);
403423
typedef uint8_t (*xpti_register_stream_t)(const char *);
404424
typedef xpti::result_t (*xpti_unregister_stream_t)(const char *);
405425
typedef uint16_t (*xpti_register_user_defined_tp_t)(const char *, uint8_t);
@@ -410,6 +430,7 @@ typedef xpti::trace_event_data_t *(*xpti_make_event_t)(
410430
typedef const xpti::trace_event_data_t *(*xpti_find_event_t)(int64_t);
411431
typedef const xpti::payload_t *(*xpti_query_payload_t)(
412432
xpti::trace_event_data_t *);
433+
typedef const xpti::payload_t *(*xpti_query_payload_by_uid_t)(uint64_t uid);
413434
typedef xpti::result_t (*xpti_register_cb_t)(uint8_t, uint16_t,
414435
xpti::tracepoint_callback_api_t);
415436
typedef xpti::result_t (*xpti_unregister_cb_t)(uint8_t, uint16_t,

xpti/include/xpti_trace_framework.hpp

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
//
88
#pragma once
99
#include <cstdint>
10+
#include <memory>
1011
#include <sstream>
12+
#include <thread>
1113

1214
#include "xpti_data_types.h"
1315
#include "xpti_trace_framework.h"
@@ -269,6 +271,7 @@ class PlatformHelper {
269271
} // namespace utils
270272

271273
namespace framework {
274+
static thread_local uint64_t g_tls_uid = xpti::invalid_uid;
272275
constexpr uint16_t signal = (uint16_t)xpti::trace_point_type_t::signal;
273276
constexpr uint16_t graph_create =
274277
(uint16_t)xpti::trace_point_type_t::graph_create;
@@ -317,5 +320,112 @@ class scoped_notify {
317320
const void *m_user_data;
318321
uint64_t m_instance;
319322
};
323+
324+
// --------------- Requires checks from OSPDT ----------------
325+
// github.com/bombela/backward-cpp/blob/master/backward.hpp
326+
//------------------------------------------------------------
327+
// #include "backward.hpp"
328+
// class backtrace_t {
329+
// public:
330+
// backtrace_t(int levels = 2) {
331+
// m_st.load_here(levels);
332+
// m_tr.load_stacktrace(m_st);
333+
// m_parent = m_tr.resolve(m_st[1]);
334+
// m_curr = m_tr.resolve(m_st[0]);
335+
// if(m_parent.source.filename) {
336+
// m_payload = xpti::payload_t(m_curr.source.function,
337+
// m_parent.source.filename, m_parent.source.line, 0, m_curr.addr);
338+
// }
339+
// else {
340+
// m_packed_string = m_parent.source.function + std::string("::") +
341+
// m_curr.source.function; m_payload =
342+
// xpti::payload_t(m_curr.source.function, m_packed_string.c_str(),
343+
// m_curr.addr);
344+
// }
345+
// }
346+
//
347+
// xpti::payload_t *payload() { return &m_payload;}
348+
// private:
349+
// backward::StackTrace m_st;
350+
// backward::TraceResolver m_tr;
351+
// backward::ResolvedTrace m_curr, m_parent;
352+
// std::string m_packed_string;
353+
// xpti::payload_t m_payload;
354+
// };
355+
356+
/// @brief Tracepoint data type allows the construction of Universal ID
357+
/// @details The tracepoint data type builds on the payload data type by
358+
/// combining the functionality of payload and xpti::makeEvent() to create the
359+
/// unique Universal ID and stash it in the TLS for use by downstream layers in
360+
/// the SW stack.
361+
///
362+
/// Usage:-
363+
/// #ifdef XPTI_TRACE_ENABLED
364+
/// xpti::payload_t p, *payload = &p;
365+
/// #ifdef SYCL_TOOL_PROFILE
366+
/// // sycl::detail::code_location cLoc =
367+
/// // sycl::detail::code_location::current();
368+
/// if(cLoc.valid())
369+
/// p = xpti::payload_t(cLoc.functionname(), cLoc.fileName(),
370+
/// cLoc.lineNumber(), cLoc.columnNumber(), codeptr);
371+
/// else
372+
/// p = xpti::payload_t(KernelInfo.funcName(), KernelInfo.sourceFileName(),
373+
/// KernelInfo.lineNo(), KernelInfor.columnNo(), codeptr);
374+
/// #else
375+
/// xpti::framework::backtrace_t b;
376+
/// payload = b.payload();
377+
/// #endif
378+
/// xpti::tracepoint_t t(payload);
379+
/// #endif
380+
///
381+
/// See also: xptiTracePointTest in xpti_correctness_tests.cpp
382+
class tracepoint_t {
383+
public:
384+
// Constructor that makes calls to xpti API layer to register strings and
385+
// create the Universal ID that is stored in the TLS entry for lookup
386+
tracepoint_t(xpti::payload_t *p) : m_payload(nullptr), m_top(false) {
387+
if (p) {
388+
// We expect the payload input has been populated with the information
389+
// available at that time
390+
uint64_t uid = g_tls_uid;
391+
if (uid != xpti::invalid_uid) {
392+
// We already have a parent SW layer that has a tracepoint defined
393+
m_payload = xptiQueryPayloadByUID(uid);
394+
} else {
395+
m_top = true;
396+
uid = xptiRegisterPayload(p);
397+
if (uid != xpti::invalid_uid) {
398+
g_tls_uid = uid;
399+
m_payload = xptiQueryPayloadByUID(uid);
400+
}
401+
}
402+
}
403+
}
404+
~tracepoint_t() {
405+
if (m_top) {
406+
g_tls_uid = xpti::invalid_uid;
407+
}
408+
}
409+
410+
// The payload object that is returned will have the UID object populated and
411+
// can be looked up in the xpti lookup APIs or be used to make an event.
412+
const payload_t *payload() { return m_payload; }
413+
414+
uint64_t universal_id() {
415+
if (m_payload &&
416+
(m_payload->flags &
417+
static_cast<uint64_t>(xpti::payload_flag_t::HashAvailable))) {
418+
return m_payload->internal;
419+
} else {
420+
return xpti::invalid_uid;
421+
}
422+
}
423+
424+
private:
425+
/// The payload data structure that is prepared from code_location(),
426+
/// caller_callee string or kernel name/codepointer based on the opt-in flag.
427+
const payload_t *m_payload;
428+
bool m_top;
429+
};
320430
} // namespace framework
321431
} // namespace xpti

xpti/src/xpti_proxy.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ enum functions_t {
3131
XPTI_ADD_METADATA,
3232
XPTI_QUERY_METADATA,
3333
XPTI_TRACE_ENABLED,
34+
XPTI_REGISTER_PAYLOAD,
35+
XPTI_QUERY_PAYLOAD_BY_UID,
3436

3537
// All additional functions need to appear before
3638
// the XPTI_FW_API_COUNT enum
@@ -45,13 +47,15 @@ class ProxyLoader {
4547
{XPTI_GET_UNIQUE_ID, "xptiGetUniqueId"},
4648
{XPTI_REGISTER_STRING, "xptiRegisterString"},
4749
{XPTI_LOOKUP_STRING, "xptiLookupString"},
50+
{XPTI_REGISTER_PAYLOAD, "xptiRegisterPayload"},
4851
{XPTI_REGISTER_STREAM, "xptiRegisterStream"},
4952
{XPTI_UNREGISTER_STREAM, "xptiUnregisterStream"},
5053
{XPTI_REGISTER_USER_DEFINED_TP, "xptiRegisterUserDefinedTracePoint"},
5154
{XPTI_REGISTER_USER_DEFINED_ET, "xptiRegisterUserDefinedEventType"},
5255
{XPTI_MAKE_EVENT, "xptiMakeEvent"},
5356
{XPTI_FIND_EVENT, "xptiFindEvent"},
5457
{XPTI_QUERY_PAYLOAD, "xptiQueryPayload"},
58+
{XPTI_QUERY_PAYLOAD_BY_UID, "xptiQueryPayloadByUID"},
5559
{XPTI_REGISTER_CALLBACK, "xptiRegisterCallback"},
5660
{XPTI_UNREGISTER_CALLBACK, "xptiUnregisterCallback"},
5761
{XPTI_NOTIFY_SUBSCRIBERS, "xptiNotifySubscribers"},
@@ -203,6 +207,16 @@ XPTI_EXPORT_API const char *xptiLookupString(xpti::string_id_t id) {
203207
return nullptr;
204208
}
205209

210+
XPTI_EXPORT_API uint64_t xptiRegisterPayload(xpti::payload_t *payload) {
211+
if (xpti::g_loader.noErrors()) {
212+
auto f = xpti::g_loader.functionByIndex(XPTI_REGISTER_PAYLOAD);
213+
if (f) {
214+
return (*(xpti_register_payload_t)f)(payload);
215+
}
216+
}
217+
return xpti::invalid_uid;
218+
}
219+
206220
XPTI_EXPORT_API uint8_t xptiRegisterStream(const char *stream_name) {
207221
if (xpti::g_loader.noErrors()) {
208222
auto f = xpti::g_loader.functionByIndex(XPTI_REGISTER_STREAM);
@@ -256,6 +270,16 @@ xptiQueryPayload(xpti::trace_event_data_t *lookup_object) {
256270
return nullptr;
257271
}
258272

273+
XPTI_EXPORT_API const xpti::payload_t *xptiQueryPayloadByUID(uint64_t uid) {
274+
if (xpti::g_loader.noErrors()) {
275+
auto f = xpti::g_loader.functionByIndex(XPTI_QUERY_PAYLOAD_BY_UID);
276+
if (f) {
277+
return (*(xpti_query_payload_by_uid_t)f)(uid);
278+
}
279+
}
280+
return nullptr;
281+
}
282+
259283
XPTI_EXPORT_API xpti::result_t
260284
xptiRegisterCallback(uint8_t stream_id, uint16_t trace_type,
261285
xpti::tracepoint_callback_api_t cb) {

0 commit comments

Comments
 (0)