17ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe/* 27ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe * 37ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe * Copyright 2017, The Android Open Source Project 47ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe * 57ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe * Licensed under the Apache License, Version 2.0 (the "License"); 67ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe * you may not use this file except in compliance with the License. 77ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe * You may obtain a copy of the License at 87ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe * 97ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe * http://www.apache.org/licenses/LICENSE-2.0 107ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe * 117ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe * Unless required by applicable law or agreed to in writing, software 127ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe * distributed under the License is distributed on an "AS IS" BASIS, 137ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 147ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe * See the License for the specific language governing permissions and 157ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe * limitations under the License. 167ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe */ 177ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 187ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#ifndef SYSTEM_EXTRAS_PERFPROFD_PERFPROFD_THREADED_HANDLER_H_ 197ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#define SYSTEM_EXTRAS_PERFPROFD_PERFPROFD_THREADED_HANDLER_H_ 207ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 217ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include <chrono> 227ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include <condition_variable> 237ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include <cstdio> 247ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include <cstdlib> 257ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include <memory> 267ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include <mutex> 277ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include <string> 287ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include <thread> 297ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include <functional> 307ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 317ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include <inttypes.h> 327ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include <unistd.h> 337ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 347ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include <android-base/logging.h> 357ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include <android-base/stringprintf.h> 367ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 377ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include "perfprofd_record.pb.h" 387ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 397ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include "config.h" 407ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include "dropbox.h" 417ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include "perfprofdcore.h" 427ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#include "perfprofd_io.h" 437ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 447ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampenamespace android { 457ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampenamespace perfprofd { 467ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 477ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampeclass ThreadedConfig : public Config { 487ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe public: 497ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe void Sleep(size_t seconds) override { 507ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe if (seconds == 0) { 517ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe return; 527ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 537ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe std::unique_lock<std::mutex> guard(mutex_); 547ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe using namespace std::chrono_literals; 557ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe cv_.wait_for(guard, seconds * 1s, [&]() { return interrupted_; }); 567ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 577ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe bool ShouldStopProfiling() override { 587ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe std::unique_lock<std::mutex> guard(mutex_); 597ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe return interrupted_; 607ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 617ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 627ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe void ResetStopProfiling() { 637ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe std::unique_lock<std::mutex> guard(mutex_); 647ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe interrupted_ = false; 657ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 667ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe void StopProfiling() { 677ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe std::unique_lock<std::mutex> guard(mutex_); 687ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe interrupted_ = true; 697ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe cv_.notify_all(); 707ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 717ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 727ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe bool IsProfilingEnabled() const override { 737ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe return true; 747ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 757ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 767ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe // Operator= to simplify setting the config values. This will retain the 777ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe // original mutex, condition-variable etc. 787ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe ThreadedConfig& operator=(const ThreadedConfig& rhs) { 797ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe // Copy base fields. 807ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe *static_cast<Config*>(this) = static_cast<const Config&>(rhs); 817ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 827ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe return *this; 837ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 847ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 857ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe private: 867ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe bool is_profiling = false; 877ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe std::mutex mutex_; 887ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe std::condition_variable cv_; 897ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe bool interrupted_ = false; 907ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 917ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe friend class ThreadedHandler; 927ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe}; 937ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 947ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampeclass ThreadedHandler { 957ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe public: 967ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe ThreadedHandler() : cur_config_(new ThreadedConfig()) {} 977ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe explicit ThreadedHandler(ThreadedConfig* in) : cur_config_(in) { 987ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe CHECK(cur_config_ != nullptr); 997ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 1007ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1017ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe virtual ~ThreadedHandler() {} 1027ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1037ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe template <typename ConfigFn> bool StartProfiling(ConfigFn fn, std::string* error_msg) { 1047ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe std::lock_guard<std::mutex> guard(lock_); 1057ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1067ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe if (cur_config_->is_profiling) { 1077ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe *error_msg = "Already profiling"; 1087ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe return false; 1097ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 1107ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe cur_config_->is_profiling = true; 1117ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe cur_config_->ResetStopProfiling(); 1127ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1137ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe fn(*cur_config_); 1147ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1157ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe HandlerFn handler = GetResultHandler(); 1167ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe auto profile_runner = [handler](ThreadedHandler* service) { 1177ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe ProfilingLoop(*service->cur_config_, handler); 1187ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1197ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe // This thread is done. 1207ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe std::lock_guard<std::mutex> unset_guard(service->lock_); 1217ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe service->cur_config_->is_profiling = false; 1227ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe }; 1237ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe std::thread profiling_thread(profile_runner, this); 1247ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe profiling_thread.detach(); // Let it go. 1257ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1267ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe return true; 1277ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 1287ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1297ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe bool StopProfiling(std::string* error_msg) { 1307ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe std::lock_guard<std::mutex> guard(lock_); 1317ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe if (!cur_config_->is_profiling) { 1327ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe *error_msg = "Not profiling"; 1337ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe return false; 1347ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 1357ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1367ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe cur_config_->StopProfiling(); 1377ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1387ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe return true; 1397ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 1407ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1417ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe protected: 1427ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe // Handler for ProfilingLoop. 1437ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe virtual bool ResultHandler(android::perfprofd::PerfprofdRecord* encodedProfile, 1447ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe Config* config) { 1457ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe CHECK(config != nullptr); 1467ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe if (encodedProfile == nullptr) { 1477ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe return false; 1487ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 1497ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1507ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe if (static_cast<ThreadedConfig*>(config)->send_to_dropbox) { 1517ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe std::string error_msg; 1527ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe if (!dropbox::SendToDropbox(encodedProfile, config->destination_directory, &error_msg)) { 1537ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe LOG(WARNING) << "Failed dropbox submission: " << error_msg; 1547ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe return false; 1557ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 1567ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe return true; 1577ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 1587ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1597ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe if (encodedProfile == nullptr) { 1607ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe return false; 1617ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 1627ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe std::string data_file_path(config->destination_directory); 1637ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe data_file_path += "/perf.data"; 1647ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe std::string path = android::base::StringPrintf("%s.encoded.%d", data_file_path.c_str(), seq_); 1657ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe if (!SerializeProtobuf(encodedProfile, path.c_str(), config->compress)) { 1667ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe return false; 1677ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 1687ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1697ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe seq_++; 1707ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe return true; 1717ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 1727ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1737ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe private: 1747ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe // Helper for the handler. 1757ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe HandlerFn GetResultHandler() { 1767ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe return HandlerFn(std::bind(&ThreadedHandler::ResultHandler, 1777ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe this, 1787ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe std::placeholders::_1, 1797ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe std::placeholders::_2)); 1807ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe } 1817ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1827ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe std::mutex lock_; 1837ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1847ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe std::unique_ptr<ThreadedConfig> cur_config_; 1857ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1867ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe int seq_ = 0; 1877ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe}; 1887ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1897ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe} // namespace perfprofd 1907ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe} // namespace android 1917ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe 1927ecfbe85850996b10463bedbfa2745cf3761182cAndreas Gampe#endif // SYSTEM_EXTRAS_PERFPROFD_PERFPROFD_THREADED_HANDLER_H_ 193