summaryrefslogtreecommitdiff
path: root/runtime/trace.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/trace.cc')
-rw-r--r--runtime/trace.cc36
1 files changed, 22 insertions, 14 deletions
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 9d9360e9cb..2add955f8e 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -54,6 +54,7 @@ static constexpr size_t TraceActionBits = MinimumBitsToStore(
static_cast<size_t>(kTraceMethodActionMask));
static constexpr uint8_t kOpNewMethod = 1U;
static constexpr uint8_t kOpNewThread = 2U;
+static constexpr uint8_t kOpTraceSummary = 3U;
class BuildStackTraceVisitor : public StackVisitor {
public:
@@ -700,20 +701,19 @@ void Trace::FinishTracing() {
std::string header(os.str());
if (trace_output_mode_ == TraceOutputMode::kStreaming) {
- File file(streaming_file_name_ + ".sec", O_CREAT | O_WRONLY, true);
- if (!file.IsOpened()) {
- LOG(WARNING) << "Could not open secondary trace file!";
- return;
- }
- if (!file.WriteFully(header.c_str(), header.length())) {
- file.Erase();
- std::string detail(StringPrintf("Trace data write failed: %s", strerror(errno)));
- PLOG(ERROR) << detail;
- ThrowRuntimeException("%s", detail.c_str());
- }
- if (file.FlushCloseOrErase() != 0) {
- PLOG(ERROR) << "Could not write secondary file";
- }
+ MutexLock mu(Thread::Current(), *streaming_lock_); // To serialize writing.
+ // Write a special token to mark the end of trace records and the start of
+ // trace summary.
+ uint8_t buf[7];
+ Append2LE(buf, 0);
+ buf[2] = kOpTraceSummary;
+ Append4LE(buf + 3, static_cast<uint32_t>(header.length()));
+ WriteToBuf(buf, sizeof(buf));
+ // Write the trace summary. The summary is identical to the file header when
+ // the output mode is not streaming (except for methods).
+ WriteToBuf(reinterpret_cast<const uint8_t*>(header.c_str()), header.length());
+ // Flush the buffer, which may include some trace records before the summary.
+ FlushBuf();
} else {
if (trace_file_.get() == nullptr) {
iovec iov[2];
@@ -894,6 +894,14 @@ void Trace::WriteToBuf(const uint8_t* src, size_t src_size) {
memcpy(buf_.get() + old_offset, src, src_size);
}
+void Trace::FlushBuf() {
+ int32_t offset = cur_offset_.LoadRelaxed();
+ if (!trace_file_->WriteFully(buf_.get(), offset)) {
+ PLOG(WARNING) << "Failed flush the remaining data in streaming.";
+ }
+ cur_offset_.StoreRelease(0);
+}
+
void Trace::LogMethodTraceEvent(Thread* thread, ArtMethod* method,
instrumentation::Instrumentation::InstrumentationEvent event,
uint32_t thread_clock_diff, uint32_t wall_clock_diff) {