Merge "Disable features that fail in Chromium builds"
diff --git a/include/perfetto/base/time.h b/include/perfetto/base/time.h
index f41f245..d1895c1 100644
--- a/include/perfetto/base/time.h
+++ b/include/perfetto/base/time.h
@@ -46,6 +46,8 @@
return TimeNanos(ts.tv_sec * 1000000000LL + ts.tv_nsec);
}
+void SleepMicroseconds(unsigned interval_us);
+
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
TimeNanos GetWallTimeNs();
diff --git a/src/base/time.cc b/src/base/time.cc
index c371eb6..8e22d59 100644
--- a/src/base/time.cc
+++ b/src/base/time.cc
@@ -19,10 +19,15 @@
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <Windows.h>
+#else
+#include <unistd.h>
+#endif
namespace perfetto {
namespace base {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
TimeNanos GetWallTimeNs() {
LARGE_INTEGER freq;
::QueryPerformanceFrequency(&freq);
@@ -44,7 +49,21 @@
return TimeNanos((kernel_time + user_time) * 100);
}
-} // namespace base
-} // namespace perfetto
+void SleepMicroseconds(unsigned interval_us) {
+ // The Windows Sleep function takes a millisecond count. Round up so that
+ // short sleeps don't turn into a busy wait. Note that the sleep granularity
+ // on Windows can dynamically vary from 1 ms to ~16 ms, so don't count on this
+ // being a short sleep.
+ ::Sleep(static_cast<DWORD>((interval_us + 999) / 1000));
+}
+
+#else // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+void SleepMicroseconds(unsigned interval_us) {
+ ::usleep(static_cast<useconds_t>(interval_us));
+}
#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+
+} // namespace base
+} // namespace perfetto
diff --git a/src/ftrace_reader/cpu_reader.cc b/src/ftrace_reader/cpu_reader.cc
index fa173f3..936cf54 100644
--- a/src/ftrace_reader/cpu_reader.cc
+++ b/src/ftrace_reader/cpu_reader.cc
@@ -173,7 +173,7 @@
worker_thread_ =
std::thread(std::bind(&RunWorkerThread, cpu_, *trace_fd_,
- *staging_write_fd_, on_data_available));
+ *staging_write_fd_, on_data_available, &exiting_));
}
CpuReader::~CpuReader() {
@@ -183,17 +183,18 @@
// trace fd (which prevents another splice from starting), raise SIGPIPE and
// wait for the worker to exit (i.e., to guarantee no splice is in progress)
// and only then close the staging pipe.
+ exiting_ = true;
trace_fd_.reset();
pthread_kill(worker_thread_.native_handle(), SIGPIPE);
worker_thread_.join();
}
// static
-void CpuReader::RunWorkerThread(
- size_t cpu,
- int trace_fd,
- int staging_write_fd,
- const std::function<void()>& on_data_available) {
+void CpuReader::RunWorkerThread(size_t cpu,
+ int trace_fd,
+ int staging_write_fd,
+ const std::function<void()>& on_data_available,
+ std::atomic<bool>* exiting) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
// This thread is responsible for moving data from the trace pipe into the
@@ -220,11 +221,12 @@
// The kernel ftrace code has its own splice() implementation that can
// occasionally fail with transient errors not reported in man 2 splice.
// Just try again if we see these.
- if (errno == ENOMEM || errno == EBUSY) {
+ if (errno == ENOMEM || errno == EBUSY || (errno == EINTR && !*exiting)) {
PERFETTO_DPLOG("Transient splice failure -- retrying");
usleep(100 * 1000);
continue;
}
+ PERFETTO_DPLOG("Stopping CPUReader loop for CPU %zd.", cpu);
PERFETTO_DCHECK(errno == EPIPE || errno == EINTR || errno == EBADF);
break; // ~CpuReader is waiting to join this thread.
}
diff --git a/src/ftrace_reader/cpu_reader.h b/src/ftrace_reader/cpu_reader.h
index 563758c..ce9a014 100644
--- a/src/ftrace_reader/cpu_reader.h
+++ b/src/ftrace_reader/cpu_reader.h
@@ -21,6 +21,7 @@
#include <string.h>
#include <array>
+#include <atomic>
#include <memory>
#include <set>
#include <thread>
@@ -202,7 +203,8 @@
static void RunWorkerThread(size_t cpu,
int trace_fd,
int staging_write_fd,
- const std::function<void()>& on_data_available);
+ const std::function<void()>& on_data_available,
+ std::atomic<bool>* exiting);
uint8_t* GetBuffer();
CpuReader(const CpuReader&) = delete;
@@ -215,6 +217,7 @@
base::ScopedFile staging_write_fd_;
base::PageAllocator::UniquePtr buffer_;
std::thread worker_thread_;
+ std::atomic<bool> exiting_{false};
PERFETTO_THREAD_CHECKER(thread_checker_)
};
diff --git a/src/tracing/core/service_impl.cc b/src/tracing/core/service_impl.cc
index 028c0d4..b67eb56 100644
--- a/src/tracing/core/service_impl.cc
+++ b/src/tracing/core/service_impl.cc
@@ -16,12 +16,17 @@
#include "src/tracing/core/service_impl.h"
+#include "perfetto/base/build_config.h"
+
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <string.h>
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <sys/uio.h>
#include <unistd.h>
+#endif
#include <algorithm>
@@ -64,6 +69,33 @@
// These apply only if enable_extra_guardrails is true.
constexpr uint64_t kMaxTracingDurationMillis = 24 * kMillisPerHour;
constexpr uint64_t kMaxTracingBufferSizeKb = 32 * 1024;
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+struct iovec {
+ void *iov_base; // Address
+ size_t iov_len; // Block size
+};
+
+// Simple implementation of writev. Note that this does not give the atomicity
+// guarantees of a real writev, but we don't depend on these (we aren't writing
+// to the same file from another thread).
+ssize_t writev(int fd, const struct iovec *iov, int iovcnt) {
+ ssize_t total_size = 0;
+ for (int i = 0; i < iovcnt; ++i) {
+ ssize_t current_size = write(fd, iov[i].iov_base, iov[i].iov_len);
+ if (current_size != static_cast<ssize_t>(iov[i].iov_len))
+ return -1;
+ total_size += current_size;
+ }
+ return total_size;
+}
+
+#define IOV_MAX 1024 // Linux compatible limit.
+
+// uid checking is a NOP on Windows.
+uid_t getuid() { return 0; }
+uid_t geteuid() { return 0; }
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
} // namespace
// These constants instead are defined in the header because are used by tests.
@@ -1009,7 +1041,7 @@
protos::TrustedPacket packet;
protos::ClockSnapshot* clock_snapshot = packet.mutable_clock_snapshot();
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) && !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
struct {
clockid_t id;
protos::ClockSnapshot::Clock::Type type;
diff --git a/src/tracing/core/shared_memory_abi.cc b/src/tracing/core/shared_memory_abi.cc
index 11ef1a1..c2ac74e 100644
--- a/src/tracing/core/shared_memory_abi.cc
+++ b/src/tracing/core/shared_memory_abi.cc
@@ -15,7 +15,12 @@
*/
#include "perfetto/tracing/core/shared_memory_abi.h"
+#include "perfetto/base/build_config.h"
+#include "perfetto/base/time.h"
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <sys/mman.h>
+#endif
#include "perfetto/base/utils.h"
#include "perfetto/tracing/core/basic_types.h"
@@ -30,7 +35,7 @@
if (attempt < kRetryAttempts / 2) {
std::this_thread::yield();
} else {
- usleep((useconds_t(attempt) / 10) * 1000);
+ base::SleepMicroseconds((unsigned(attempt) / 10) * 1000);
}
}
@@ -299,6 +304,7 @@
void SharedMemoryABI::ReleaseAllChunksAsFree(size_t page_idx) {
PageHeader* phdr = page_header(page_idx);
phdr->layout.store(0, std::memory_order_release);
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
uint8_t* page_start = start_ + page_idx * page_size_;
// TODO(fmayer): On Linux/Android this should be MADV_REMOVE if we use
// memfd_create() and tmpfs supports hole punching (need to consult kernel
@@ -306,6 +312,7 @@
int ret = madvise(reinterpret_cast<uint8_t*>(page_start), page_size_,
MADV_DONTNEED);
PERFETTO_DCHECK(ret == 0);
+#endif
}
SharedMemoryABI::Chunk::Chunk() = default;
diff --git a/src/tracing/core/shared_memory_arbiter_impl.cc b/src/tracing/core/shared_memory_arbiter_impl.cc
index f0960f8..1618b41 100644
--- a/src/tracing/core/shared_memory_arbiter_impl.cc
+++ b/src/tracing/core/shared_memory_arbiter_impl.cc
@@ -18,6 +18,7 @@
#include "perfetto/base/logging.h"
#include "perfetto/base/task_runner.h"
+#include "perfetto/base/time.h"
#include "perfetto/tracing/core/commit_data_request.h"
#include "perfetto/tracing/core/shared_memory.h"
#include "src/tracing/core/null_trace_writer.h"
@@ -62,8 +63,8 @@
size_t size_hint) {
PERFETTO_DCHECK(size_hint == 0); // Not implemented yet.
int stall_count = 0;
- useconds_t stall_interval_us = 0;
- static const useconds_t kMaxStallIntervalUs = 100000;
+ unsigned stall_interval_us = 0;
+ static const unsigned kMaxStallIntervalUs = 100000;
static const int kLogAfterNStalls = 3;
for (;;) {
@@ -123,7 +124,7 @@
// SMB.
FlushPendingCommitDataRequests();
}
- usleep(stall_interval_us);
+ base::SleepMicroseconds(stall_interval_us);
stall_interval_us =
std::min(kMaxStallIntervalUs, (stall_interval_us + 1) * 8);
}
diff --git a/src/tracing/core/trace_buffer.cc b/src/tracing/core/trace_buffer.cc
index 605be74..1e80012 100644
--- a/src/tracing/core/trace_buffer.cc
+++ b/src/tracing/core/trace_buffer.cc
@@ -16,7 +16,6 @@
#include "src/tracing/core/trace_buffer.h"
-#include <sys/mman.h>
#include <limits>
#include "perfetto/base/logging.h"
diff --git a/test/configs/BUILD.gn b/test/configs/BUILD.gn
index 01e149e..1505529 100644
--- a/test/configs/BUILD.gn
+++ b/test/configs/BUILD.gn
@@ -26,6 +26,7 @@
sources = [
"atrace.cfg",
"ftrace.cfg",
+ "ftrace_largebuffer.cfg",
"long_trace.cfg",
"processes.cfg",
"summary.cfg",
diff --git a/test/configs/ftrace_largebuffer.cfg b/test/configs/ftrace_largebuffer.cfg
new file mode 100644
index 0000000..03c212e
--- /dev/null
+++ b/test/configs/ftrace_largebuffer.cfg
@@ -0,0 +1,38 @@
+buffers {
+ size_kb: 16000
+ fill_policy: RING_BUFFER
+}
+
+data_sources {
+ config {
+ name: "linux.ftrace"
+ target_buffer: 0
+ ftrace_config {
+ buffer_size_kb: 2048 # 4 (page size) * 128
+ drain_period_ms: 200
+ ftrace_events: "sched_wakeup"
+ ftrace_events: "sched_wakeup_new"
+ ftrace_events: "sched_switch"
+ ftrace_events: "sched_blocked_reason"
+ ftrace_events: "cpu_idle"
+ ftrace_events: "cpu_frequency"
+ ftrace_events: "cpu_frequency_limits"
+ ftrace_events: "suspend_resume"
+ ftrace_events: "clock_set_rate"
+ ftrace_events: "workqueue_activate_work"
+ ftrace_events: "workqueue_execute_end"
+ ftrace_events: "workqueue_execute_start"
+ ftrace_events: "workqueue_queue_work"
+ }
+ }
+}
+
+producers {
+ producer_name: "perfetto.traced_probes"
+ shm_size_kb: 4096
+ page_size_kb: 4
+}
+
+duration_ms: 7200000
+write_into_file: true
+max_file_size_bytes: 4000000000
diff --git a/tools/trace_to_text/main.cc b/tools/trace_to_text/main.cc
index 5f45af4..a0488c3 100644
--- a/tools/trace_to_text/main.cc
+++ b/tools/trace_to_text/main.cc
@@ -587,15 +587,15 @@
if (compact_output) {
sprintf(line, "ftrace duration,%" PRIu64 "\n", ftrace_duration);
} else {
- sprintf(line, "Ftrace Duration: %" PRIu64 "ms\n", ftrace_duration);
+ sprintf(line, "Ftrace duration: %" PRIu64 "ms\n", ftrace_duration);
}
*output << std::string(line);
uint64_t boottime_duration = (boottime_end - boottime_start) / (1000 * 1000);
if (compact_output) {
- sprintf(line, "total duration,%" PRIu64 "\n", boottime_duration);
+ sprintf(line, "boottime duration,%" PRIu64 "\n", boottime_duration);
} else {
- sprintf(line, "Total Duration: %" PRIu64 "ms\n", boottime_duration);
+ sprintf(line, "Boottime duration: %" PRIu64 "ms\n", boottime_duration);
}
*output << std::string(line);