diff options
Diffstat (limited to 'runtime/trace.h')
| -rw-r--r-- | runtime/trace.h | 82 |
1 files changed, 71 insertions, 11 deletions
diff --git a/runtime/trace.h b/runtime/trace.h index 86b8d00d515..b242d1596c4 100644 --- a/runtime/trace.h +++ b/runtime/trace.h @@ -33,6 +33,10 @@ #include "globals.h" #include "instrumentation.h" +namespace unix_file { +class FdFile; +} // namespace unix_file + namespace art { class ArtField; @@ -48,9 +52,10 @@ using ThreadIDBitSet = std::bitset<kMaxThreadIdNumber>; enum TracingMode { kTracingInactive, - kMethodTracingActive, - kSampleProfilingActive, + kMethodTracingActive, // Trace activity synchronous with method progress. + kSampleProfilingActive, // Trace activity captured by sampling thread. }; +std::ostream& operator<<(std::ostream& os, const TracingMode& rhs); // File format: // header @@ -94,6 +99,9 @@ enum TraceAction { kTraceMethodActionMask = 0x03, // two bits }; +// Class for recording event traces. Trace data is either collected +// synchronously during execution (TracingMode::kMethodTracingActive), +// or by a separate sampling thread (TracingMode::kSampleProfilingActive). class Trace FINAL : public instrumentation::InstrumentationListener { public: enum TraceFlag { @@ -115,10 +123,37 @@ class Trace FINAL : public instrumentation::InstrumentationListener { static void SetDefaultClockSource(TraceClockSource clock_source); - static void Start(const char* trace_filename, int trace_fd, size_t buffer_size, int flags, - TraceOutputMode output_mode, TraceMode trace_mode, int interval_us) + static void Start(const char* trace_filename, + size_t buffer_size, + int flags, + TraceOutputMode output_mode, + TraceMode trace_mode, + int interval_us) + REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_, + !Locks::trace_lock_); + static void Start(int trace_fd, + size_t buffer_size, + int flags, + TraceOutputMode output_mode, + TraceMode trace_mode, + int interval_us) + REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_, + !Locks::trace_lock_); + static void Start(std::unique_ptr<unix_file::FdFile>&& file, + size_t buffer_size, + int flags, + TraceOutputMode output_mode, + TraceMode trace_mode, + int interval_us) + REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_, + !Locks::trace_lock_); + static void StartDDMS(size_t buffer_size, + int flags, + TraceMode trace_mode, + int interval_us) REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_, !Locks::trace_lock_); + static void Pause() REQUIRES(!Locks::trace_lock_, !Locks::thread_list_lock_); static void Resume() REQUIRES(!Locks::trace_lock_); @@ -212,8 +247,11 @@ class Trace FINAL : public instrumentation::InstrumentationListener { static bool IsTracingEnabled() REQUIRES(!Locks::trace_lock_); private: - Trace(File* trace_file, const char* trace_name, size_t buffer_size, int flags, - TraceOutputMode output_mode, TraceMode trace_mode); + Trace(File* trace_file, + size_t buffer_size, + int flags, + TraceOutputMode output_mode, + TraceMode trace_mode); // The sampling interval in microseconds is passed as an argument. static void* RunSamplingThread(void* arg) REQUIRES(!Locks::trace_lock_); @@ -282,7 +320,10 @@ class Trace FINAL : public instrumentation::InstrumentationListener { // File to write trace data out to, null if direct to ddms. std::unique_ptr<File> trace_file_; - // Buffer to store trace data. + // Buffer to store trace data. In streaming mode, this is protected + // by the streaming_lock_. In non-streaming mode, reserved regions + // are atomically allocated (using cur_offset_) for log entries to + // be written. std::unique_ptr<uint8_t[]> buf_; // Flags enabling extra tracing of things such as alloc counts. @@ -305,7 +346,27 @@ class Trace FINAL : public instrumentation::InstrumentationListener { // Clock overhead. const uint32_t clock_overhead_ns_; - // Offset into buf_. + // Offset into buf_. The field is atomic to allow multiple writers + // to concurrently reserve space in the buffer. The newly written + // buffer contents are not read without some other form of thread + // synchronization, such as suspending all potential writers or + // acquiring *streaming_lock_. Reading cur_offset_ is thus never + // used to ensure visibility of any other objects, and all accesses + // are memory_order_relaxed. + // + // All accesses to buf_ in streaming mode occur whilst holding the + // streaming lock. In streaming mode, the buffer may be written out + // so cur_offset_ can move forwards and backwards. + // + // When not in streaming mode, the buf_ writes can come from + // multiple threads when the trace mode is kMethodTracing. When + // trace mode is kSampling, writes only come from the sampling + // thread. + // + // Reads to the buffer happen after the event sources writing to the + // buffer have been shutdown and all stores have completed. The + // stores are made visible in StopTracing() when execution leaves + // the ScopedSuspendAll block. AtomicInteger cur_offset_; // Did we overflow the buffer recording traces? @@ -318,10 +379,9 @@ class Trace FINAL : public instrumentation::InstrumentationListener { int interval_us_; // Streaming mode data. - std::string streaming_file_name_; Mutex* streaming_lock_; - std::map<const DexFile*, DexIndexBitSet*> seen_methods_; - std::unique_ptr<ThreadIDBitSet> seen_threads_; + std::map<const DexFile*, DexIndexBitSet*> seen_methods_ GUARDED_BY(streaming_lock_); + std::unique_ptr<ThreadIDBitSet> seen_threads_ GUARDED_BY(streaming_lock_); // Bijective map from ArtMethod* to index. // Map from ArtMethod* to index in unique_methods_; |
