blob: 4d5665795837bdbcc41a8515f28ee07352301576 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FTRACE_READER_FTRACE_CONTROLLER_H_
#define FTRACE_READER_FTRACE_CONTROLLER_H_
#include <unistd.h>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "base/scoped_file.h"
#include "base/task_runner.h"
#include "base/weak_ptr.h"
#include "gtest/gtest_prod.h"
#include "protozero/protozero_message_handle.h"
namespace perfetto {
namespace protos {
namespace pbzero {
class FtraceEventBundle;
} // namespace pbzero
} // namespace protos
const size_t kMaxSinks = 32;
class FtraceController;
class ProtoTranslationTable;
class CpuReader;
class FtraceProcfs;
class EventFilter;
class FtraceConfig {
public:
FtraceConfig();
explicit FtraceConfig(std::set<std::string> events);
~FtraceConfig();
void AddEvent(const std::string&);
const std::set<std::string>& events() const { return events_; }
private:
std::set<std::string> events_;
};
// To consume ftrace data clients implement a |FtraceSink::Delegate| and use it
// to create a |FtraceSink|. While the FtraceSink lives FtraceController will
// call |GetBundleForCpu|, write data into the bundle then call
// |OnBundleComplete| allowing the client to perform finalization.
class FtraceSink {
public:
using FtraceEventBundle = protos::pbzero::FtraceEventBundle;
class Delegate {
public:
virtual protozero::ProtoZeroMessageHandle<FtraceEventBundle>
GetBundleForCpu(size_t) = 0;
virtual void OnBundleComplete(
size_t,
protozero::ProtoZeroMessageHandle<FtraceEventBundle>) = 0;
virtual ~Delegate() = default;
};
FtraceSink(base::WeakPtr<FtraceController>,
std::unique_ptr<EventFilter>,
Delegate*);
~FtraceSink();
private:
friend FtraceController;
EventFilter* get_event_filter() { return filter_.get(); }
protozero::ProtoZeroMessageHandle<FtraceEventBundle> GetBundleForCpu(
size_t cpu) {
return delegate_->GetBundleForCpu(cpu);
}
void OnBundleComplete(
size_t cpu,
protozero::ProtoZeroMessageHandle<FtraceEventBundle> bundle) {
delegate_->OnBundleComplete(cpu, std::move(bundle));
}
const std::set<std::string>& enabled_events();
base::WeakPtr<FtraceController> controller_weak_;
std::unique_ptr<EventFilter> filter_;
FtraceSink::Delegate* delegate_;
};
// Utility class for controlling ftrace.
class FtraceController {
public:
static std::unique_ptr<FtraceController> Create(base::TaskRunner*);
virtual ~FtraceController();
std::unique_ptr<FtraceSink> CreateSink(FtraceConfig, FtraceSink::Delegate*);
void Start();
void Stop();
protected:
// Protected for testing.
FtraceController(std::unique_ptr<FtraceProcfs>,
base::TaskRunner*,
std::unique_ptr<ProtoTranslationTable>);
private:
friend FtraceSink;
FRIEND_TEST(FtraceControllerIntegrationTest, EnableDisableEvent);
FtraceController(const FtraceController&) = delete;
FtraceController& operator=(const FtraceController&) = delete;
void Register(FtraceSink*);
void Unregister(FtraceSink*);
void RegisterForEvent(const std::string& event_name);
void UnregisterForEvent(const std::string& event_name);
// Called when we know there is data for the raw pipe
// for the given |cpu|. Kicks off the reading/parsing
// of the pipe.
void OnRawFtraceDataAvailable(size_t cpu);
// Returns a cached CpuReader for |cpu|.
// CpuReaders are constructed lazily and owned by the controller.
CpuReader* GetCpuReader(size_t cpu);
std::unique_ptr<FtraceProcfs> ftrace_procfs_;
bool listening_for_raw_trace_data_ = false;
base::TaskRunner* task_runner_ = nullptr;
base::WeakPtrFactory<FtraceController> weak_factory_;
std::vector<size_t> enabled_count_;
std::unique_ptr<ProtoTranslationTable> table_;
std::map<size_t, std::unique_ptr<CpuReader>> readers_;
std::set<FtraceSink*> sinks_;
PERFETTO_THREAD_CHECKER(thread_checker_)
};
} // namespace perfetto
#endif // FTRACE_READER_FTRACE_CONTROLLER_H_