blob: 1e67765228c94590e0b0ea8b6668d8fa9ba052e5 [file] [log] [blame]
/*
* Copyright 2018 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 "hal_adapter/camera_trace_event.h"
#include <cstdio>
#include <fcntl.h>
#include <string>
#include <sys/syscall.h>
#include <unistd.h>
#include <base/files/file.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <base/synchronization/lock.h>
#include "cros-camera/common.h"
namespace cros {
namespace tracer {
namespace {
pid_t gettid() {
return syscall(SYS_gettid);
}
} // namespace
const char kTraceMarkerPath[] = "/sys/kernel/debug/tracing/trace_marker";
EventTracer::EventTracer() = default;
EventTracer* EventTracer::GetInstance() {
static EventTracer* instance = new EventTracer();
return instance;
}
void EventTracer::SetEnabled(bool enabled) {
base::AutoLock l(event_tracer_lock_);
tracing_enabled_ = enabled;
begun_tid_.clear();
if (!tracing_enabled_) {
trace_file_.Close();
} else {
trace_file_ = base::File(base::FilePath(kTraceMarkerPath),
base::File::FLAG_OPEN | base::File::FLAG_APPEND);
}
}
void EventTracer::BeginTrace(base::StringPiece name, base::StringPiece args) {
VLOGF_ENTER();
base::AutoLock l(event_tracer_lock_);
if (!tracing_enabled_) {
return;
}
// We use %.*s here because TotW [1] and the comment of
// StringPiece.data() [2] say that data() may not return a null
// terminated buffer.
// [1] go/totw/1
// [2] https://cs.chromium.org/chromium/src/base/strings/string_piece.h?l=204
TracePrintf("B|%d|%.*s|%.*s|camera", getpid(), static_cast<int>(name.size()),
name.data(), static_cast<int>(args.size()), args.data());
if (!begun_tid_.insert(gettid()).second) {
LOGF(WARNING) << "Begin a tracing event " << name
<< " while pervious event isn't finished."
<< " Pervious event will be canceled.";
}
}
void EventTracer::EndTrace(base::StringPiece name, base::StringPiece args) {
VLOGF_ENTER();
base::AutoLock l(event_tracer_lock_);
if (!tracing_enabled_) {
return;
}
TracePrintf("E|%d|%.*s|%.*s|camera", getpid(), static_cast<int>(name.size()),
name.data(), static_cast<int>(args.size()), args.data());
if (!begun_tid_.erase(gettid())) {
LOGF(WARNING) << "Tracing event " << name
<< " not exists or was canceled by other event.";
}
}
void EventTracer::AsyncBeginTrace(base::StringPiece name,
int cookie,
base::StringPiece args) {
VLOGF_ENTER();
base::AutoLock l(event_tracer_lock_);
if (!tracing_enabled_) {
return;
}
TracePrintf("S|%d|%.*s|%d|%.*s|camera", getpid(),
static_cast<int>(name.size()), name.data(), cookie,
static_cast<int>(args.size()), args.data());
}
void EventTracer::AsyncEndTrace(base::StringPiece name,
int cookie,
base::StringPiece args) {
VLOGF_ENTER();
base::AutoLock l(event_tracer_lock_);
if (!tracing_enabled_) {
return;
}
TracePrintf("F|%d|%.*s|%d|%.*s|camera", getpid(),
static_cast<int>(name.size()), name.data(), cookie,
static_cast<int>(args.size()), args.data());
}
void EventTracer::Counter(base::StringPiece name, int value) {
VLOGF_ENTER();
base::AutoLock l(event_tracer_lock_);
if (!tracing_enabled_) {
return;
}
TracePrintf("C|%d|%.*s|%d|camera", getpid(), static_cast<int>(name.size()),
name.data(), value);
}
void EventTracer::TracePrintf(_Printf_format_string_ const char* format, ...) {
va_list args;
va_start(args, format);
if (trace_file_.IsValid()) {
if (vdprintf(trace_file_.GetPlatformFile(), format, args) < 0) {
LOGF(WARNING) << "vdprintf error.";
}
} else {
LOGF(WARNING) << "Trace file is invaild.";
}
va_end(args);
}
} // namespace tracer
} // namespace cros