123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- /*
- * 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.
- */
- #define SIMPLEPERF_EXPORT __attribute__((visibility("default")))
- #include "include/simpleperf.h"
- #include <memory>
- #include <set>
- #include <string>
- #include <vector>
- #include <android-base/logging.h>
- #include "environment.h"
- #include "event_attr.h"
- #include "event_fd.h"
- #include "event_selection_set.h"
- #include "event_type.h"
- namespace simpleperf {
- std::vector<std::string> GetAllEvents() {
- std::vector<std::string> result;
- if (!CheckPerfEventLimit()) {
- return result;
- }
- for (auto& type : GetAllEventTypes()) {
- perf_event_attr attr = CreateDefaultPerfEventAttr(type);
- if (IsEventAttrSupported(attr)) {
- result.push_back(type.name);
- }
- }
- return result;
- }
- bool IsEventSupported(const std::string& name) {
- if (!CheckPerfEventLimit()) {
- return false;
- }
- std::unique_ptr<EventTypeAndModifier> type = ParseEventType(name);
- if (type == nullptr) {
- return false;
- }
- perf_event_attr attr = CreateDefaultPerfEventAttr(type->event_type);
- return IsEventAttrSupported(attr);
- }
- class PerfEventSetImpl : public PerfEventSet {
- public:
- virtual ~PerfEventSetImpl() {}
- bool AddEvent(const std::string& name) override {
- if (!IsEventSupported(name)) {
- return false;
- }
- event_names_.push_back(name);
- return true;
- }
- bool MonitorCurrentProcess() override {
- whole_process_ = true;
- return true;
- }
- bool MonitorCurrentThread() override {
- whole_process_ = false;
- threads_.insert(gettid());
- return true;
- }
- bool MonitorThreadsInCurrentProcess(const std::vector<pid_t>& threads) override {
- whole_process_ = false;
- std::vector<pid_t> tids = GetThreadsInProcess(getpid());
- for (auto& tid : threads) {
- if (std::find(tids.begin(), tids.end(), tid) == tids.end()) {
- LOG(ERROR) << "Thread " << tid << " doesn't exist in current process.";
- return false;
- }
- }
- threads_.insert(threads.begin(), threads.end());
- return true;
- }
- protected:
- PerfEventSetImpl() : whole_process_(false) {}
- std::vector<std::string> event_names_;
- bool whole_process_;
- std::set<pid_t> threads_;
- };
- class PerfEventSetForCounting : public PerfEventSetImpl {
- public:
- PerfEventSetForCounting() : in_counting_state_(false) {}
- virtual ~PerfEventSetForCounting() {}
- bool StartCounters() override;
- bool StopCounters() override;
- bool ReadCounters(std::vector<Counter>* counters) override;
- private:
- bool CreateEventSelectionSet();
- void InitAccumulatedCounters();
- bool ReadRawCounters(std::vector<Counter>* counters);
- // Add counter b to a.
- void AddCounter(Counter& a, const Counter& b);
- // Sub counter b from a.
- void SubCounter(Counter& a, const Counter& b);
- bool in_counting_state_;
- std::unique_ptr<EventSelectionSet> event_selection_set_;
- // The counters at the last time calling StartCounting().
- std::vector<Counter> last_start_counters_;
- // The accumulated counters of counting periods, excluding
- // the last one.
- std::vector<Counter> accumulated_counters_;
- };
- bool PerfEventSetForCounting::CreateEventSelectionSet() {
- std::unique_ptr<EventSelectionSet> set(new EventSelectionSet(true));
- if (event_names_.empty()) {
- LOG(ERROR) << "No events.";
- return false;
- }
- for (const auto& name : event_names_) {
- if (!set->AddEventType(name)) {
- return false;
- }
- }
- if (whole_process_) {
- set->AddMonitoredProcesses({getpid()});
- } else {
- if (threads_.empty()) {
- LOG(ERROR) << "No monitored threads.";
- return false;
- }
- set->AddMonitoredThreads(threads_);
- }
- if (!set->OpenEventFiles({-1})) {
- return false;
- }
- event_selection_set_ = std::move(set);
- return true;
- }
- void PerfEventSetForCounting::InitAccumulatedCounters() {
- for (const auto& name : event_names_) {
- Counter counter;
- counter.event = name;
- counter.value = 0;
- counter.time_enabled_in_ns = 0;
- counter.time_running_in_ns = 0;
- accumulated_counters_.push_back(counter);
- }
- }
- bool PerfEventSetForCounting::ReadRawCounters(std::vector<Counter>* counters) {
- CHECK(event_selection_set_);
- std::vector<CountersInfo> s;
- if (!event_selection_set_->ReadCounters(&s)) {
- return false;
- }
- CHECK_EQ(s.size(), event_names_.size());
- counters->resize(s.size());
- for (size_t i = 0; i < s.size(); ++i) {
- CountersInfo& info = s[i];
- std::string name = info.event_modifier.empty() ? info.event_name :
- info.event_name + ":" + info.event_modifier;
- CHECK_EQ(name, event_names_[i]);
- Counter& sum = (*counters)[i];
- sum.event = name;
- sum.value = 0;
- sum.time_enabled_in_ns = 0;
- sum.time_running_in_ns = 0;
- for (CounterInfo& c : info.counters) {
- sum.value += c.counter.value;
- sum.time_enabled_in_ns += c.counter.time_enabled;
- sum.time_running_in_ns += c.counter.time_running;
- }
- }
- return true;
- }
- void PerfEventSetForCounting::AddCounter(Counter& a, const Counter& b) {
- a.value += b.value;
- a.time_enabled_in_ns += b.time_enabled_in_ns;
- a.time_running_in_ns += b.time_enabled_in_ns;
- }
- void PerfEventSetForCounting::SubCounter(Counter& a, const Counter& b) {
- a.value -= b.value;
- a.time_enabled_in_ns -= b.time_enabled_in_ns;
- a.time_running_in_ns -= b.time_running_in_ns;
- }
- bool PerfEventSetForCounting::StartCounters() {
- if (in_counting_state_) {
- return true;
- }
- if (event_selection_set_ == nullptr) {
- if (!CreateEventSelectionSet()) {
- return false;
- }
- InitAccumulatedCounters();
- }
- if (!ReadRawCounters(&last_start_counters_)) {
- return false;
- }
- in_counting_state_ = true;
- return true;
- }
- bool PerfEventSetForCounting::StopCounters() {
- if (!in_counting_state_) {
- return true;
- }
- std::vector<Counter> cur;
- if (!ReadRawCounters(&cur)) {
- return false;
- }
- for (size_t i = 0; i < event_names_.size(); ++i) {
- SubCounter(cur[i], last_start_counters_[i]);
- AddCounter(accumulated_counters_[i], cur[i]);
- }
- in_counting_state_ = false;
- return true;
- }
- bool PerfEventSetForCounting::ReadCounters(std::vector<Counter>* counters) {
- if (!in_counting_state_) {
- *counters = accumulated_counters_;
- return true;
- }
- if (!ReadRawCounters(counters)) {
- return false;
- }
- for (size_t i = 0; i < event_names_.size(); ++i) {
- SubCounter((*counters)[i], last_start_counters_[i]);
- AddCounter((*counters)[i], accumulated_counters_[i]);
- }
- return true;
- }
- PerfEventSet* PerfEventSet::CreateInstance(PerfEventSet::Type type) {
- if (!CheckPerfEventLimit()) {
- return nullptr;
- }
- if (type == Type::kPerfForCounting) {
- return new PerfEventSetForCounting;
- }
- return nullptr;
- }
- bool PerfEventSet::AddEvent(const std::string&) {
- return false;
- }
- bool PerfEventSet::MonitorCurrentProcess() {
- return false;
- }
- bool PerfEventSet::MonitorCurrentThread() {
- return false;
- }
- bool PerfEventSet::MonitorThreadsInCurrentProcess(const std::vector<pid_t>&) {
- return false;
- }
- bool PerfEventSet::StartCounters() {
- return false;
- }
- bool PerfEventSet::StopCounters() {
- return false;
- }
- bool PerfEventSet::ReadCounters(std::vector<Counter>*) {
- return false;
- }
- } // namespace simpleperf
|