blob: 30e6041e7b15b8f88bb80e58552120be676b4772 [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sommelier-tracing.h" // NOLINT(build/include_directory)
#include <assert.h>
#include <fcntl.h>
#include <memory>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>
#include <vector>
#include <xcb/xproto.h>
#if defined(PERFETTO_TRACING)
PERFETTO_TRACK_EVENT_STATIC_STORAGE();
std::unique_ptr<perfetto::TracingSession> tracing_session;
void initialize_tracing(bool in_process_backend, bool system_backend) {
perfetto::TracingInitArgs args;
if (in_process_backend) {
args.backends |= perfetto::kInProcessBackend;
}
if (system_backend) {
args.backends |= perfetto::kSystemBackend;
}
perfetto::Tracing::Initialize(args);
perfetto::TrackEvent::Register();
}
void enable_tracing(bool create_session) {
perfetto::TraceConfig cfg;
cfg.add_buffers()->set_size_kb(1024); // Record up to 1 MiB.
auto* ds_cfg = cfg.add_data_sources()->mutable_config();
ds_cfg->set_name("track_event");
if (create_session) {
tracing_session = perfetto::Tracing::NewTrace();
tracing_session->Setup(cfg);
tracing_session->StartBlocking();
}
}
void dump_trace(const char* trace_filename) {
if (!trace_filename || !*trace_filename || !tracing_session) {
return;
}
std::vector<char> trace_data(tracing_session->ReadTraceBlocking());
// Write the trace into a file.
int fd = open(trace_filename, O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fd == -1) {
fprintf(stderr, "error: unable to open trace file %s: %s\n", trace_filename,
strerror(errno));
return;
}
size_t pos = 0;
do {
ssize_t ret = write(fd, &trace_data[pos], trace_data.size() - pos);
if (ret < 0) {
if (errno == EINTR || errno == EAGAIN) {
continue;
}
fprintf(stderr, "error: unable to write trace file %s: %s\n",
trace_filename, strerror(errno));
close(fd);
return;
}
pos += ret;
} while (pos < trace_data.size());
close(fd);
}
static const char* xcb_atom_to_string(uint32_t atom) {
switch (atom) {
case XCB_ATOM_NONE:
return "XCB_ATOM_NONE";
case XCB_ATOM_PRIMARY:
return "XCB_ATOM_PRIMARY";
case XCB_ATOM_SECONDARY:
return "XCB_ATOM_SECONDARY";
case XCB_ATOM_ARC:
return "XCB_ATOM_ARC";
case XCB_ATOM_ATOM:
return "XCB_ATOM_ATOM";
case XCB_ATOM_BITMAP:
return "XCB_ATOM_BITMAP";
case XCB_ATOM_CARDINAL:
return "XCB_ATOM_CARDINAL";
case XCB_ATOM_COLORMAP:
return "XCB_ATOM_COLORMAP";
case XCB_ATOM_CURSOR:
return "XCB_ATOM_CURSOR";
case XCB_ATOM_CUT_BUFFER0:
return "XCB_ATOM_CUT_BUFFER0";
case XCB_ATOM_CUT_BUFFER1:
return "XCB_ATOM_CUT_BUFFER1";
case XCB_ATOM_CUT_BUFFER2:
return "XCB_ATOM_CUT_BUFFER2";
case XCB_ATOM_CUT_BUFFER3:
return "XCB_ATOM_CUT_BUFFER3";
case XCB_ATOM_CUT_BUFFER4:
return "XCB_ATOM_CUT_BUFFER4";
case XCB_ATOM_CUT_BUFFER5:
return "XCB_ATOM_CUT_BUFFER5";
case XCB_ATOM_CUT_BUFFER6:
return "XCB_ATOM_CUT_BUFFER6";
case XCB_ATOM_CUT_BUFFER7:
return "XCB_ATOM_CUT_BUFFER7";
case XCB_ATOM_DRAWABLE:
return "XCB_ATOM_DRAWABLE";
case XCB_ATOM_FONT:
return "XCB_ATOM_FONT";
case XCB_ATOM_INTEGER:
return "XCB_ATOM_INTEGER";
case XCB_ATOM_PIXMAP:
return "XCB_ATOM_PIXMAP";
case XCB_ATOM_POINT:
return "XCB_ATOM_POINT";
case XCB_ATOM_RECTANGLE:
return "XCB_ATOM_RECTANGLE";
case XCB_ATOM_RESOURCE_MANAGER:
return "XCB_ATOM_RESOURCE_MANAGER";
case XCB_ATOM_RGB_COLOR_MAP:
return "XCB_ATOM_RGB_COLOR_MAP";
case XCB_ATOM_RGB_BEST_MAP:
return "XCB_ATOM_RGB_BEST_MAP";
case XCB_ATOM_RGB_BLUE_MAP:
return "XCB_ATOM_RGB_BLUE_MAP";
case XCB_ATOM_RGB_DEFAULT_MAP:
return "XCB_ATOM_RGB_DEFAULT_MAP";
case XCB_ATOM_RGB_GRAY_MAP:
return "XCB_ATOM_RGB_GRAY_MAP";
case XCB_ATOM_RGB_GREEN_MAP:
return "XCB_ATOM_RGB_GREEN_MAP";
case XCB_ATOM_RGB_RED_MAP:
return "XCB_ATOM_RGB_RED_MAP";
case XCB_ATOM_STRING:
return "XCB_ATOM_STRING";
case XCB_ATOM_VISUALID:
return "XCB_ATOM_VISUALID";
case XCB_ATOM_WINDOW:
return "XCB_ATOM_WINDOW";
case XCB_ATOM_WM_COMMAND:
return "XCB_ATOM_WM_COMMAND";
case XCB_ATOM_WM_HINTS:
return "XCB_ATOM_WM_HINTS";
case XCB_ATOM_WM_CLIENT_MACHINE:
return "XCB_ATOM_WM_CLIENT_MACHINE";
case XCB_ATOM_WM_ICON_NAME:
return "XCB_ATOM_WM_ICON_NAME";
case XCB_ATOM_WM_ICON_SIZE:
return "XCB_ATOM_WM_ICON_SIZE";
case XCB_ATOM_WM_NAME:
return "XCB_ATOM_WM_NAME";
case XCB_ATOM_WM_NORMAL_HINTS:
return "XCB_ATOM_WM_NORMAL_HINTS";
case XCB_ATOM_WM_SIZE_HINTS:
return "XCB_ATOM_WM_SIZE_HINTS";
case XCB_ATOM_WM_ZOOM_HINTS:
return "XCB_ATOM_WM_ZOOM_HINTS";
case XCB_ATOM_MIN_SPACE:
return "XCB_ATOM_MIN_SPACE";
case XCB_ATOM_NORM_SPACE:
return "XCB_ATOM_NORM_SPACE";
case XCB_ATOM_MAX_SPACE:
return "XCB_ATOM_MAX_SPACE";
case XCB_ATOM_END_SPACE:
return "XCB_ATOM_END_SPACE";
case XCB_ATOM_SUPERSCRIPT_X:
return "XCB_ATOM_SUPERSCRIPT_X";
case XCB_ATOM_SUPERSCRIPT_Y:
return "XCB_ATOM_SUPERSCRIPT_Y";
case XCB_ATOM_SUBSCRIPT_X:
return "XCB_ATOM_SUBSCRIPT_X";
case XCB_ATOM_SUBSCRIPT_Y:
return "XCB_ATOM_SUBSCRIPT_Y";
case XCB_ATOM_UNDERLINE_POSITION:
return "XCB_ATOM_UNDERLINE_POSITION";
case XCB_ATOM_UNDERLINE_THICKNESS:
return "XCB_ATOM_UNDERLINE_THICKNESS";
case XCB_ATOM_STRIKEOUT_ASCENT:
return "XCB_ATOM_STRIKEOUT_ASCENT";
case XCB_ATOM_STRIKEOUT_DESCENT:
return "XCB_ATOM_STRIKEOUT_DESCENT";
case XCB_ATOM_ITALIC_ANGLE:
return "XCB_ATOM_ITALIC_ANGLE";
case XCB_ATOM_X_HEIGHT:
return "XCB_ATOM_X_HEIGHT";
case XCB_ATOM_QUAD_WIDTH:
return "XCB_ATOM_QUAD_WIDTH";
case XCB_ATOM_WEIGHT:
return "XCB_ATOM_WEIGHT";
case XCB_ATOM_POINT_SIZE:
return "XCB_ATOM_POINT_SIZE";
case XCB_ATOM_RESOLUTION:
return "XCB_ATOM_RESOLUTION";
case XCB_ATOM_COPYRIGHT:
return "XCB_ATOM_COPYRIGHT";
case XCB_ATOM_NOTICE:
return "XCB_ATOM_NOTICE";
case XCB_ATOM_FONT_NAME:
return "XCB_ATOM_FONT_NAME";
case XCB_ATOM_FAMILY_NAME:
return "XCB_ATOM_FAMILY_NAME";
case XCB_ATOM_FULL_NAME:
return "XCB_ATOM_FULL_NAME";
case XCB_ATOM_CAP_HEIGHT:
return "XCB_ATOM_CAP_HEIGHT";
case XCB_ATOM_WM_CLASS:
return "XCB_ATOM_WM_CLASS";
case XCB_ATOM_WM_TRANSIENT_FOR:
return "XCB_ATOM_WM_TRANSIENT_FOR";
default:
return "<unknown>";
}
}
void perfetto_annotate_xcb_atom(const perfetto::EventContext& event,
const char* name,
xcb_atom_t atom_int) {
auto* dbg = event.event()->add_debug_annotations();
dbg->set_name(name);
const char* atom = xcb_atom_to_string(atom_int);
if (atom) {
dbg->set_string_value(atom, strlen(atom));
} else {
static const std::string unknown("<unknown>");
dbg->set_string_value(unknown);
}
}
void perfetto_annotate_xcb_property_state(const perfetto::EventContext& event,
const char* name,
unsigned int state) {
auto* dbg = event.event()->add_debug_annotations();
dbg->set_name(name);
if (state == XCB_PROPERTY_NEW_VALUE) {
static const std::string prop_new("XCB_PROPERTY_NEW_VALUE");
dbg->set_string_value(prop_new);
} else if (state == XCB_PROPERTY_DELETE) {
static const std::string prop_delete("XCB_PROPERTY_DELETE");
dbg->set_string_value(prop_delete);
} else {
static const std::string unknown("<unknown>");
dbg->set_string_value(unknown);
}
}
#else
// Stubs.
void initialize_tracing(bool in_process_backend, bool system_backend) {}
void enable_tracing(bool create_session) {}
void dump_trace(const char* trace_filename) {}
#endif // PERFETTO_TRACING