Home | History | Annotate | Download | only in ftrace_reader
      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 INCLUDE_PERFETTO_FTRACE_READER_FTRACE_CONTROLLER_H_
     18 #define INCLUDE_PERFETTO_FTRACE_READER_FTRACE_CONTROLLER_H_
     19 
     20 #include <unistd.h>
     21 
     22 #include <sys/stat.h>
     23 #include <bitset>
     24 #include <condition_variable>
     25 #include <map>
     26 #include <memory>
     27 #include <mutex>
     28 #include <set>
     29 #include <string>
     30 #include <vector>
     31 
     32 #include "gtest/gtest_prod.h"
     33 #include "perfetto/base/scoped_file.h"
     34 #include "perfetto/base/task_runner.h"
     35 #include "perfetto/base/weak_ptr.h"
     36 #include "perfetto/ftrace_reader/ftrace_config.h"
     37 #include "perfetto/protozero/message_handle.h"
     38 #include "perfetto/traced/data_source_types.h"
     39 
     40 namespace perfetto {
     41 
     42 namespace protos {
     43 namespace pbzero {
     44 class FtraceEventBundle;
     45 class FtraceStats;
     46 class FtraceCpuStats;
     47 }  // namespace pbzero
     48 }  // namespace protos
     49 
     50 using BlockDeviceID = decltype(stat::st_dev);
     51 using Inode = decltype(stat::st_ino);
     52 
     53 struct FtraceCpuStats {
     54   uint64_t cpu;
     55   uint64_t entries;
     56   uint64_t overrun;
     57   uint64_t commit_overrun;
     58   uint64_t bytes_read;
     59   double oldest_event_ts;
     60   double now_ts;
     61   uint64_t dropped_events;
     62   uint64_t read_events;
     63 
     64   void Write(protos::pbzero::FtraceCpuStats*) const;
     65 };
     66 
     67 struct FtraceStats {
     68   std::vector<FtraceCpuStats> cpu_stats;
     69 
     70   void Write(protos::pbzero::FtraceStats*) const;
     71 };
     72 
     73 struct FtraceMetadata {
     74   FtraceMetadata();
     75 
     76   uint32_t overwrite_count;
     77   BlockDeviceID last_seen_device_id = 0;
     78 #if PERFETTO_DCHECK_IS_ON()
     79   bool seen_device_id = false;
     80 #endif
     81   int32_t last_seen_common_pid = 0;
     82 
     83   // A vector not a set to keep the writer_fast.
     84   std::vector<std::pair<Inode, BlockDeviceID>> inode_and_device;
     85   std::vector<int32_t> pids;
     86 
     87   void AddDevice(BlockDeviceID);
     88   void AddInode(Inode);
     89   void AddPid(int32_t);
     90   void AddCommonPid(int32_t);
     91   void Clear();
     92   void FinishEvent();
     93 };
     94 
     95 constexpr size_t kMaxSinks = 32;
     96 constexpr size_t kMaxCpus = 64;
     97 
     98 // Method of last resort to reset ftrace state.
     99 void HardResetFtraceState();
    100 
    101 class CpuReader;
    102 class EventFilter;
    103 class FtraceController;
    104 class FtraceConfigMuxer;
    105 class FtraceProcfs;
    106 class ProtoTranslationTable;
    107 
    108 // To consume ftrace data clients implement a |FtraceSink::Delegate| and use it
    109 // to create a |FtraceSink|. While the FtraceSink lives FtraceController will
    110 // call |GetBundleForCpu|, write data into the bundle then call
    111 // |OnBundleComplete| allowing the client to perform finalization.
    112 class FtraceSink {
    113  public:
    114   using FtraceEventBundle = protos::pbzero::FtraceEventBundle;
    115   class Delegate {
    116    public:
    117     virtual void OnCreate(FtraceSink*) {}
    118     virtual protozero::MessageHandle<FtraceEventBundle> GetBundleForCpu(
    119         size_t) = 0;
    120     virtual void OnBundleComplete(size_t,
    121                                   protozero::MessageHandle<FtraceEventBundle>,
    122                                   const FtraceMetadata&) = 0;
    123     virtual ~Delegate();
    124   };
    125 
    126   FtraceSink(base::WeakPtr<FtraceController>,
    127              FtraceConfigId id,
    128              FtraceConfig config,
    129              std::unique_ptr<EventFilter>,
    130              Delegate*);
    131   ~FtraceSink();
    132 
    133   void DumpFtraceStats(FtraceStats*);
    134 
    135   const FtraceConfig& config() const { return config_; }
    136 
    137  private:
    138   friend FtraceController;
    139 
    140   FtraceSink(const FtraceSink&) = delete;
    141   FtraceSink& operator=(const FtraceSink&) = delete;
    142 
    143   EventFilter* event_filter() { return filter_.get(); }
    144   FtraceMetadata* metadata_mutable() { return &metadata_; }
    145 
    146   protozero::MessageHandle<FtraceEventBundle> GetBundleForCpu(size_t cpu) {
    147     return delegate_->GetBundleForCpu(cpu);
    148   }
    149   void OnBundleComplete(size_t cpu,
    150                         protozero::MessageHandle<FtraceEventBundle> bundle) {
    151     delegate_->OnBundleComplete(cpu, std::move(bundle), metadata_);
    152     metadata_.Clear();
    153   }
    154 
    155   const std::set<std::string>& enabled_events();
    156 
    157   base::WeakPtr<FtraceController> controller_weak_;
    158   const FtraceConfigId id_;
    159   const FtraceConfig config_;
    160   std::unique_ptr<EventFilter> filter_;
    161   FtraceMetadata metadata_;
    162   FtraceSink::Delegate* delegate_;
    163 };
    164 
    165 // Utility class for controlling ftrace.
    166 class FtraceController {
    167  public:
    168   static std::unique_ptr<FtraceController> Create(base::TaskRunner*);
    169   virtual ~FtraceController();
    170 
    171   std::unique_ptr<FtraceSink> CreateSink(FtraceConfig, FtraceSink::Delegate*);
    172 
    173   void DisableAllEvents();
    174   void WriteTraceMarker(const std::string& s);
    175   void ClearTrace();
    176 
    177  protected:
    178   // Protected for testing.
    179   FtraceController(std::unique_ptr<FtraceProcfs>,
    180                    std::unique_ptr<ProtoTranslationTable>,
    181                    std::unique_ptr<FtraceConfigMuxer>,
    182                    base::TaskRunner*);
    183 
    184   // Write
    185   void DumpFtraceStats(FtraceStats*);
    186 
    187   // Called to read data from the staging pipe for the given |cpu| and parse it
    188   // into the sinks. Protected and virtual for testing.
    189   virtual void OnRawFtraceDataAvailable(size_t cpu);
    190 
    191   // Protected and virtual for testing.
    192   virtual uint64_t NowMs() const;
    193 
    194  private:
    195   friend FtraceSink;
    196   friend class TestFtraceController;
    197   FRIEND_TEST(FtraceControllerIntegrationTest, EnableDisableEvent);
    198 
    199   FtraceController(const FtraceController&) = delete;
    200   FtraceController& operator=(const FtraceController&) = delete;
    201 
    202   // Called on a worker thread when |cpu| has at least one page of data
    203   // available for reading.
    204   void OnDataAvailable(base::WeakPtr<FtraceController>,
    205                        size_t generation,
    206                        size_t cpu,
    207                        uint32_t drain_period_ms);
    208 
    209   static void DrainCPUs(base::WeakPtr<FtraceController>, size_t generation);
    210   static void UnblockReaders(const base::WeakPtr<FtraceController>&);
    211 
    212   uint32_t GetDrainPeriodMs();
    213 
    214   void Register(FtraceSink*);
    215   void Unregister(FtraceSink*);
    216 
    217   void StartIfNeeded();
    218   void StopIfNeeded();
    219 
    220   // Begin lock-protected members.
    221   std::mutex lock_;
    222   std::condition_variable data_drained_;
    223   std::bitset<kMaxCpus> cpus_to_drain_;
    224   bool listening_for_raw_trace_data_ = false;
    225   // End lock-protected members.
    226 
    227   std::unique_ptr<FtraceProcfs> ftrace_procfs_;
    228   std::unique_ptr<ProtoTranslationTable> table_;
    229   std::unique_ptr<FtraceConfigMuxer> ftrace_config_muxer_;
    230   size_t generation_ = 0;
    231   bool atrace_running_ = false;
    232   base::TaskRunner* task_runner_ = nullptr;
    233   std::map<size_t, std::unique_ptr<CpuReader>> readers_;
    234   std::set<FtraceSink*> sinks_;
    235   base::WeakPtrFactory<FtraceController> weak_factory_;
    236   PERFETTO_THREAD_CHECKER(thread_checker_)
    237 };
    238 
    239 }  // namespace perfetto
    240 
    241 #endif  // INCLUDE_PERFETTO_FTRACE_READER_FTRACE_CONTROLLER_H_
    242