• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 SRC_TRACED_PROBES_FTRACE_FTRACE_CONTROLLER_H_
18 #define SRC_TRACED_PROBES_FTRACE_FTRACE_CONTROLLER_H_
19 
20 #include <stdint.h>
21 #include <unistd.h>
22 
23 #include <map>
24 #include <memory>
25 #include <set>
26 #include <string>
27 
28 #include "perfetto/base/task_runner.h"
29 #include "perfetto/ext/base/paged_memory.h"
30 #include "perfetto/ext/base/utils.h"
31 #include "perfetto/ext/base/weak_ptr.h"
32 #include "perfetto/ext/tracing/core/basic_types.h"
33 #include "src/traced/probes/ftrace/cpu_reader.h"
34 #include "src/traced/probes/ftrace/ftrace_config_utils.h"
35 
36 namespace perfetto {
37 
38 class FtraceConfigMuxer;
39 class FtraceDataSource;
40 class FtraceProcfs;
41 class LazyKernelSymbolizer;
42 class ProtoTranslationTable;
43 struct FtraceStats;
44 
45 // Method of last resort to reset ftrace state.
46 bool HardResetFtraceState();
47 
48 // Stores the a snapshot of the timestamps from ftrace's trace clock
49 // and CLOCK_BOOTITME.
50 //
51 // This is used when the "boot" (i.e. CLOCK_BOOTITME) is not available
52 // for timestamping trace events (on Android O- and 3.x Linux kernels).
53 // Trace processor can use this data to sync clocks just as it would
54 // with ClockSnapshot packets.
55 struct FtraceClockSnapshot {
56   // The timestamp according to the ftrace clock.
57   int64_t ftrace_clock_ts = 0;
58 
59   // The timestamp according to CLOCK_BOOTTIME.
60   int64_t boot_clock_ts = 0;
61 };
62 
63 // Utility class for controlling ftrace.
64 class FtraceController {
65  public:
66   class Observer {
67    public:
68     virtual ~Observer();
69     virtual void OnFtraceDataWrittenIntoDataSourceBuffers() = 0;
70   };
71 
72   // The passed Observer must outlive the returned FtraceController instance.
73   static std::unique_ptr<FtraceController> Create(base::TaskRunner*, Observer*);
74   virtual ~FtraceController();
75 
76   bool AddDataSource(FtraceDataSource*) PERFETTO_WARN_UNUSED_RESULT;
77   bool StartDataSource(FtraceDataSource*);
78   void RemoveDataSource(FtraceDataSource*);
79 
80   // Force a read of the ftrace buffers. Will call OnFtraceFlushComplete() on
81   // all started data sources.
82   void Flush(FlushRequestID);
83 
84   void DumpFtraceStats(FtraceDataSource*, FtraceStats*);
85 
GetWeakPtr()86   base::WeakPtr<FtraceController> GetWeakPtr() {
87     return weak_factory_.GetWeakPtr();
88   }
89 
90   // public for testing
91   static std::optional<std::string> AbsolutePathForInstance(
92       const std::string& tracefs_root,
93       const std::string& raw_cfg_name);
94 
95  protected:
96   // Everything protected/virtual for testing:
97 
98   FtraceController(std::unique_ptr<FtraceProcfs>,
99                    std::unique_ptr<ProtoTranslationTable>,
100                    std::unique_ptr<FtraceConfigMuxer>,
101                    base::TaskRunner*,
102                    Observer*);
103 
104   struct FtraceInstanceState {
105     struct PerCpuState {
PerCpuStateFtraceInstanceState::PerCpuState106       PerCpuState(std::unique_ptr<CpuReader> _reader, size_t _period_page_quota)
107           : reader(std::move(_reader)), period_page_quota(_period_page_quota) {}
108       std::unique_ptr<CpuReader> reader;
109       size_t period_page_quota = 0;
110     };
111 
112     FtraceInstanceState(std::unique_ptr<FtraceProcfs>,
113                         std::unique_ptr<ProtoTranslationTable>,
114                         std::unique_ptr<FtraceConfigMuxer>);
115 
116     std::unique_ptr<FtraceProcfs> ftrace_procfs;
117     std::unique_ptr<ProtoTranslationTable> table;
118     std::unique_ptr<FtraceConfigMuxer> ftrace_config_muxer;
119     std::vector<PerCpuState> per_cpu;  // empty if no started data sources
120     std::set<FtraceDataSource*> started_data_sources;
121   };
122 
123   FtraceInstanceState* GetInstance(const std::string& instance_name);
124 
125   virtual uint64_t NowMs() const;
126 
127   // TODO(rsavitski): figure out a better testing shim.
128   virtual std::unique_ptr<FtraceInstanceState> CreateSecondaryInstance(
129       const std::string& instance_name);
130 
131  private:
132   friend class TestFtraceController;
133 
134   FtraceController(const FtraceController&) = delete;
135   FtraceController& operator=(const FtraceController&) = delete;
136 
137   // Periodic task that reads all per-cpu ftrace buffers.
138   void ReadTick(int generation);
139   bool ReadTickForInstance(FtraceInstanceState* instance);
140   uint32_t GetDrainPeriodMs();
141 
142   void FlushForInstance(FtraceInstanceState* instance);
143 
144   void StartIfNeeded(FtraceInstanceState* instance);
145   void StopIfNeeded(FtraceInstanceState* instance);
146 
147   FtraceInstanceState* GetOrCreateInstance(const std::string& instance_name);
148   void DestroyIfUnusedSeconaryInstance(FtraceInstanceState* instance);
149 
150   size_t GetStartedDataSourcesCount() const;
151   void MaybeSnapshotFtraceClock();  // valid only for primary_ tracefs instance
152 
153   base::TaskRunner* const task_runner_;
154   Observer* const observer_;
155   base::PagedMemory parsing_mem_;
156   std::unique_ptr<LazyKernelSymbolizer> symbolizer_;
157   FtraceConfigId next_cfg_id_ = 1;
158   int generation_ = 0;
159   bool retain_ksyms_on_stop_ = false;
160   std::set<FtraceDataSource*> data_sources_;
161   // Default tracefs instance (normally /sys/kernel/tracing) is valid for as
162   // long as the controller is valid.
163   // Secondary instances (i.e. /sys/kernel/tracing/instances/...) are created
164   // and destroyed as necessary between AddDataSource and RemoveDataSource:
165   FtraceInstanceState primary_;
166   std::map<std::string, std::unique_ptr<FtraceInstanceState>>
167       secondary_instances_;
168 
169   // Additional state for snapshotting non-boot ftrace clock, specific to the
170   // primary_ instance:
171   base::ScopedFile cpu_zero_stats_fd_;
172   std::unique_ptr<FtraceClockSnapshot> ftrace_clock_snapshot_;
173 
174   base::WeakPtrFactory<FtraceController> weak_factory_;  // Keep last.
175 };
176 
177 }  // namespace perfetto
178 
179 #endif  // SRC_TRACED_PROBES_FTRACE_FTRACE_CONTROLLER_H_
180