1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_RUNTIME_TRACE_H_
18 #define ART_RUNTIME_TRACE_H_
19 
20 #include <memory>
21 #include <ostream>
22 #include <set>
23 #include <string>
24 #include <vector>
25 
26 #include "atomic.h"
27 #include "base/macros.h"
28 #include "globals.h"
29 #include "instrumentation.h"
30 #include "os.h"
31 #include "safe_map.h"
32 
33 namespace art {
34 
35 namespace mirror {
36   class ArtField;
37   class ArtMethod;
38 }  // namespace mirror
39 
40 class Thread;
41 
42 enum TracingMode {
43   kTracingInactive,
44   kMethodTracingActive,
45   kSampleProfilingActive,
46 };
47 
48 class Trace FINAL : public instrumentation::InstrumentationListener {
49  public:
50   enum TraceFlag {
51     kTraceCountAllocs = 1,
52   };
53 
54   static void SetDefaultClockSource(TraceClockSource clock_source);
55 
56   static void Start(const char* trace_filename, int trace_fd, int buffer_size, int flags,
57                     bool direct_to_ddms, bool sampling_enabled, int interval_us)
58       LOCKS_EXCLUDED(Locks::mutator_lock_,
59                      Locks::thread_list_lock_,
60                      Locks::thread_suspend_count_lock_,
61                      Locks::trace_lock_);
62   static void Stop()
63       LOCKS_EXCLUDED(Locks::mutator_lock_,
64                      Locks::thread_list_lock_,
65                      Locks::trace_lock_);
66   static void Shutdown() LOCKS_EXCLUDED(Locks::trace_lock_);
67   static TracingMode GetMethodTracingMode() LOCKS_EXCLUDED(Locks::trace_lock_);
68 
69   bool UseWallClock();
70   bool UseThreadCpuClock();
71   void MeasureClockOverhead();
72   uint32_t GetClockOverheadNanoSeconds();
73 
74   void CompareAndUpdateStackTrace(Thread* thread, std::vector<mirror::ArtMethod*>* stack_trace)
75       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
76 
77   // InstrumentationListener implementation.
78   void MethodEntered(Thread* thread, mirror::Object* this_object,
79                      mirror::ArtMethod* method, uint32_t dex_pc)
80       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
81   void MethodExited(Thread* thread, mirror::Object* this_object,
82                     mirror::ArtMethod* method, uint32_t dex_pc,
83                     const JValue& return_value)
84       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
85   void MethodUnwind(Thread* thread, mirror::Object* this_object,
86                     mirror::ArtMethod* method, uint32_t dex_pc)
87       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
88   void DexPcMoved(Thread* thread, mirror::Object* this_object,
89                   mirror::ArtMethod* method, uint32_t new_dex_pc)
90       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
91   void FieldRead(Thread* thread, mirror::Object* this_object,
92                  mirror::ArtMethod* method, uint32_t dex_pc, mirror::ArtField* field)
93       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
94   void FieldWritten(Thread* thread, mirror::Object* this_object,
95                     mirror::ArtMethod* method, uint32_t dex_pc, mirror::ArtField* field,
96                     const JValue& field_value)
97       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
98   void ExceptionCaught(Thread* thread, const ThrowLocation& throw_location,
99                        mirror::ArtMethod* catch_method, uint32_t catch_dex_pc,
100                        mirror::Throwable* exception_object)
101       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
102 
103   // Reuse an old stack trace if it exists, otherwise allocate a new one.
104   static std::vector<mirror::ArtMethod*>* AllocStackTrace();
105   // Clear and store an old stack trace for later use.
106   static void FreeStackTrace(std::vector<mirror::ArtMethod*>* stack_trace);
107   // Save id and name of a thread before it exits.
108   static void StoreExitingThreadInfo(Thread* thread);
109 
110  private:
111   explicit Trace(File* trace_file, int buffer_size, int flags, bool sampling_enabled);
112 
113   // The sampling interval in microseconds is passed as an argument.
114   static void* RunSamplingThread(void* arg) LOCKS_EXCLUDED(Locks::trace_lock_);
115 
116   void FinishTracing() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
117 
118   void ReadClocks(Thread* thread, uint32_t* thread_clock_diff, uint32_t* wall_clock_diff);
119 
120   void LogMethodTraceEvent(Thread* thread, mirror::ArtMethod* method,
121                            instrumentation::Instrumentation::InstrumentationEvent event,
122                            uint32_t thread_clock_diff, uint32_t wall_clock_diff);
123 
124   // Methods to output traced methods and threads.
125   void GetVisitedMethods(size_t end_offset, std::set<mirror::ArtMethod*>* visited_methods);
126   void DumpMethodList(std::ostream& os, const std::set<mirror::ArtMethod*>& visited_methods)
127       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
128   void DumpThreadList(std::ostream& os) LOCKS_EXCLUDED(Locks::thread_list_lock_);
129 
130   // Singleton instance of the Trace or NULL when no method tracing is active.
131   static Trace* volatile the_trace_ GUARDED_BY(Locks::trace_lock_);
132 
133   // The default profiler clock source.
134   static TraceClockSource default_clock_source_;
135 
136   // Sampling thread, non-zero when sampling.
137   static pthread_t sampling_pthread_;
138 
139   // Used to remember an unused stack trace to avoid re-allocation during sampling.
140   static std::unique_ptr<std::vector<mirror::ArtMethod*>> temp_stack_trace_;
141 
142   // File to write trace data out to, NULL if direct to ddms.
143   std::unique_ptr<File> trace_file_;
144 
145   // Buffer to store trace data.
146   std::unique_ptr<uint8_t> buf_;
147 
148   // Flags enabling extra tracing of things such as alloc counts.
149   const int flags_;
150 
151   // True if traceview should sample instead of instrumenting method entry/exit.
152   const bool sampling_enabled_;
153 
154   const TraceClockSource clock_source_;
155 
156   // Size of buf_.
157   const int buffer_size_;
158 
159   // Time trace was created.
160   const uint64_t start_time_;
161 
162   // Clock overhead.
163   const uint32_t clock_overhead_ns_;
164 
165   // Offset into buf_.
166   AtomicInteger cur_offset_;
167 
168   // Did we overflow the buffer recording traces?
169   bool overflow_;
170 
171   // Map of thread ids and names that have already exited.
172   SafeMap<pid_t, std::string> exited_threads_;
173 
174   DISALLOW_COPY_AND_ASSIGN(Trace);
175 };
176 
177 }  // namespace art
178 
179 #endif  // ART_RUNTIME_TRACE_H_
180