1b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui/* 2b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui * Copyright (C) 2017 The Android Open Source Project 3b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui * 4b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui * Licensed under the Apache License, Version 2.0 (the "License"); 5b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui * you may not use this file except in compliance with the License. 6b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui * You may obtain a copy of the License at 7b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui * 8b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui * http://www.apache.org/licenses/LICENSE-2.0 9b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui * 10b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui * Unless required by applicable law or agreed to in writing, software 11b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui * distributed under the License is distributed on an "AS IS" BASIS, 12b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui * See the License for the specific language governing permissions and 14b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui * limitations under the License. 15b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui */ 16b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 17b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include "inplace_sampler_lib.h" 18b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 19b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <inttypes.h> 20b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <pthread.h> 21b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <signal.h> 22b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <stdio.h> 23b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <stdlib.h> 24b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <string.h> 25b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <sys/syscall.h> 26b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <sys/ucontext.h> 27b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <unistd.h> 28b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 29b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <map> 30b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <memory> 31b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <queue> 32b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <set> 33b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <string> 34b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <unordered_map> 35b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 36b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <android-base/logging.h> 37b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <android-base/macros.h> 38b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <backtrace/Backtrace.h> 39b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#define LOG_TAG "InplaceSampler" 40b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <log/log.h> 41b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 42b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include "environment.h" 43b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include "UnixSocket.h" 44b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include "utils.h" 45b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 46b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#define DEFAULT_SIGNO SIGRTMAX 47b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuistatic constexpr int DEFAULT_SAMPLE_FREQ = 4000; 48b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuistatic constexpr int CHECK_THREADS_INTERVAL_IN_MS = 200; 49b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 50b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuinamespace { 51b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 52b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuistruct ThreadInfo { 53b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::string name; 54b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui}; 55b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 56b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui// SampleManager controls the whole sampling process: 57b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui// Read commands from simpleperf 58b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui// Set up timers to send signals for each profiled thread regularly. 59b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui// Send thread info and map info to simpleperf. 60b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuiclass SampleManager { 61b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui public: 62b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui SampleManager(std::unique_ptr<UnixSocketConnection> conn) : conn_(std::move(conn)), 63b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui tid_(gettid()), signo_(DEFAULT_SIGNO), sample_freq_(DEFAULT_SAMPLE_FREQ), 64b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui sample_period_in_ns_(0), dump_callchain_(false), monitor_all_threads_(true) { 65b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 66b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui void Run(); 67b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 68b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui private: 69b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui bool HandleMessage(const UnixSocketMessage& msg); 70b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui bool ParseStartProfilingMessage(const UnixSocketMessage& msg); 71b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui bool SendStartProfilingReplyMessage(bool ok); 72b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui bool StartProfiling(); 73b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui bool InstallSignalHandler(); 74b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui bool CheckThreads(); 75b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui bool CheckThreadNameChange(uint64_t timestamp); 76b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui bool CheckMapChange(uint64_t timestamp); 77b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui void SendThreadMapInfo(); 78b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui void SendFakeSampleRecord(); 79b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 80b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::unique_ptr<UnixSocketConnection> conn_; 81b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 82b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui int tid_; 83b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui int signo_; 84b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui uint32_t sample_freq_; 85b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui uint32_t sample_period_in_ns_; 86b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui bool dump_callchain_; 87b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui bool monitor_all_threads_; 88b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::set<int> monitor_tid_filter_; 89b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::map<int, ThreadInfo> threads_; 90b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::map<uint64_t, ThreadMmap> maps_; 91b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::queue<std::unique_ptr<char[]>> thread_map_info_q_; 92b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 93b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui IOEventLoop loop_; 94b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui}; 95b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 96b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuivoid SampleManager::Run() { 97b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui auto read_callback = [&](const UnixSocketMessage& msg) { 98b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return HandleMessage(msg); 99b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui }; 100b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui auto close_callback = [&]() { 101b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return loop_.ExitLoop(); 102b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui }; 103b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!conn_->PrepareForIO(loop_, read_callback, close_callback)) { 104b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return; 105b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 106b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui loop_.RunLoop(); 107b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} 108b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 109b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuibool SampleManager::HandleMessage(const UnixSocketMessage& msg) { 110b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (msg.type == START_PROFILING) { 111b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!ParseStartProfilingMessage(msg)) { 112b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!SendStartProfilingReplyMessage(false)) { 113b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return false; 114b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 115b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return conn_->NoMoreMessage(); 116b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 117b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!SendStartProfilingReplyMessage(true)) { 118b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return false; 119b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 120b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return StartProfiling(); 121b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 122b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (msg.type == END_PROFILING) { 123b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui // Close connection after clearing send buffer. 124b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return conn_->NoMoreMessage(); 125b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 126b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui LOG(ERROR) << "Unexpected msg type: " << msg.type; 127b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return false; 128b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} 129b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 130b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuibool SampleManager::ParseStartProfilingMessage(const UnixSocketMessage& msg) { 131b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui char* option = const_cast<char*>(msg.data); 132b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui while (option != nullptr && *option != '\0') { 133b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui char* next_option = strchr(option, ' '); 134b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (next_option != nullptr) { 135b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui *next_option++ = '\0'; 136b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 137b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui char* equal_op = strchr(option, '='); 138b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (equal_op != nullptr) { 139b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui char* key = option; 140b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui *equal_op = '\0'; 141b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui char* value = equal_op + 1; 142b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (strcmp(key, "freq") == 0) { 143b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui sample_freq_ = atoi(value); 144b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } else if (strcmp(key, "signal") == 0) { 145b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui signo_ = atoi(value); 146b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } else if (strcmp(key, "tids") == 0) { 147b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui monitor_all_threads_ = false; 148b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui while (*value != '\0') { 149b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui int tid = static_cast<int>(strtol(value, &value, 10)); 150b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui monitor_tid_filter_.insert(tid); 151b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (*value == ',') { 152b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui ++value; 153b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 154b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 155b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } else if (strcmp(key, "dump_callchain") == 0) { 156b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui dump_callchain_ = (strcmp(value, "1") == 0); 157b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 158b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 159b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui option = next_option; 160b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 161b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (sample_freq_ == 0 || sample_freq_ > 1000000000) { 162b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui LOG(ERROR) << "Unexpected sample_freq: " << sample_freq_; 163b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return false; 164b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 165b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (sample_freq_ == 1) { 166b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui sample_period_in_ns_ = 999999999; 167b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } else { 168b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui sample_period_in_ns_ = 1000000000 / sample_freq_; 169b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 170b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return true; 171b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} 172b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 173b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuibool SampleManager::SendStartProfilingReplyMessage(bool ok) { 174b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui const char* s = ok ? "ok" : "error"; 175b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui size_t size = sizeof(UnixSocketMessage) + strlen(s) + 1; 176b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::unique_ptr<char[]> data(new char[size]); 177b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui UnixSocketMessage* msg = reinterpret_cast<UnixSocketMessage*>(data.get()); 178b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui msg->len = size; 179b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui msg->type = START_PROFILING_REPLY; 180b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui strcpy(msg->data, s); 181b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return conn_->SendMessage(*msg, true); 182b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} 183b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 184b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuibool SampleManager::StartProfiling() { 185b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!InstallSignalHandler()) { 186b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return false; 187b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 188b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!CheckThreads()) { 189b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return false; 190b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 191b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui timeval tv; 192b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui tv.tv_sec = CHECK_THREADS_INTERVAL_IN_MS / 1000; 193b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui tv.tv_usec = CHECK_THREADS_INTERVAL_IN_MS % 1000 * 1000; 194b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return loop_.AddPeriodicEvent(tv, [&]() { 195b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return CheckThreads(); 196b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui }); 197b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} 198b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 199b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuibool SampleManager::InstallSignalHandler() { 200b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return true; 201b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} 202b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 203b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuibool SampleManager::CheckThreads() { 204b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui uint64_t timestamp = GetSystemClock(); 205b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!CheckMapChange(timestamp)) { 206b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return false; 207b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 208b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!CheckThreadNameChange(timestamp)) { 209b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return false; 210b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 211b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui SendThreadMapInfo(); 212b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui // For testing. 213b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui SendFakeSampleRecord(); 214b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return true; 215b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} 216b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 217b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuibool SampleManager::CheckThreadNameChange(uint64_t timestamp) { 218b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::vector<pid_t> tids = GetThreadsInProcess(getpid()); 219b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::map<pid_t, std::string> current; 220b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui for (auto& tid : tids) { 221b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (tid == tid_) { 222b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui // Skip sample thread. 223b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui continue; 224b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 225b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (monitor_all_threads_ || monitor_tid_filter_.find(tid) != monitor_tid_filter_.end()) { 226b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::string name; 227b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (GetThreadName(tid, &name)) { 228b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui current[tid] = name; 229b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 230b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 231b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 232b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui // Check new threads or threads with new names. 233b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui for (auto& pair : current) { 234b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui pid_t tid = pair.first; 235b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui auto it = threads_.find(tid); 236b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (it == threads_.end() || it->second.name != pair.second) { 237b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui threads_[tid].name = pair.second; 238b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui size_t size = sizeof(UnixSocketMessage) + sizeof(uint64_t) + sizeof(uint32_t) + 239b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui pair.second.size() + 1; 240b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::unique_ptr<char[]> data(new char[size]); 241b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui UnixSocketMessage* msg = reinterpret_cast<UnixSocketMessage*>(data.get()); 242b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui msg->len = size; 243b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui msg->type = THREAD_INFO; 244b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui char* p = msg->data; 245b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveToBinaryFormat(timestamp, p); 246b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveToBinaryFormat(static_cast<uint32_t>(tid), p); 247b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveToBinaryFormat(pair.second.c_str(), pair.second.size() + 1, p); 248b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui thread_map_info_q_.push(std::move(data)); 249b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 250b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 251b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui // Check deleted threads. 252b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui for (auto it = threads_.begin(); it != threads_.end();) { 253b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui int tid = it->first; 254b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (current.find(tid) == current.end()) { 255b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui it = threads_.erase(it); 256b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } else { 257b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui ++it; 258b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 259b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 260b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return true; 261b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} 262b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 263b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuibool SampleManager::CheckMapChange(uint64_t timestamp) { 264b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::vector<ThreadMmap> maps; 265b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!GetThreadMmapsInProcess(getpid(), &maps)) { 266b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return false; 267b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 268b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui // Check new maps or changed maps. 269b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui for (auto& map : maps) { 270b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!map.executable) { 271b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui continue; 272b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 273b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui auto it = maps_.find(map.start_addr); 274b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (it == maps_.end() || it->second.len != map.len || it->second.pgoff != map.pgoff || 275b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui it->second.name != map.name) { 276b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui maps_[map.start_addr] = map; 277b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui size_t size = sizeof(UnixSocketMessage) + sizeof(uint64_t) * 4 + map.name.size() + 1; 278b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::unique_ptr<char[]> data(new char[size]); 279b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui UnixSocketMessage* msg = reinterpret_cast<UnixSocketMessage*>(data.get()); 280b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui msg->len = size; 281b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui msg->type = MAP_INFO; 282b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui char* p = msg->data; 283b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveToBinaryFormat(timestamp, p); 284b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveToBinaryFormat(map.start_addr, p); 285b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveToBinaryFormat(map.len, p); 286b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveToBinaryFormat(map.pgoff, p); 287b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveToBinaryFormat(map.name.c_str(), map.name.size() + 1, p); 288b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui thread_map_info_q_.push(std::move(data)); 289b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 290b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 291b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return true; 292b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} 293b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 294b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuivoid SampleManager::SendThreadMapInfo() { 295b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui while (!thread_map_info_q_.empty()) { 296b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui auto& data = thread_map_info_q_.front(); 297b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui UnixSocketMessage* msg = reinterpret_cast<UnixSocketMessage*>(data.get()); 298b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!conn_->SendMessage(*msg, false)) { 299b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui break; 300b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 301b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui thread_map_info_q_.pop(); 302b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 303b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} 304b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 305b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuistatic void FakeFunction() { 306b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} 307b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 308b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuivoid SampleManager::SendFakeSampleRecord() { 309b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui size_t size = sizeof(UnixSocketMessage) + sizeof(uint64_t) * 2 + sizeof(uint32_t) * 3; 310b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::unique_ptr<char[]> data(new char[size]); 311b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui UnixSocketMessage* msg = reinterpret_cast<UnixSocketMessage*>(data.get()); 312b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui uint64_t ip = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&FakeFunction)); 313b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui msg->len = size; 314b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui msg->type = SAMPLE_INFO; 315b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui char* p = msg->data; 316b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveToBinaryFormat(GetSystemClock(), p); 317b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveToBinaryFormat(static_cast<uint32_t>(tid_), p); 318b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveToBinaryFormat(1u, p); 319b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveToBinaryFormat(1u, p); 320b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveToBinaryFormat(ip, p); 321b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui conn_->SendMessage(*msg, false); 322b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} 323b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 324b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuistatic void* CommunicationThread(void*) { 325b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui pthread_setname_np(pthread_self(), "inplace_sampler"); 326b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::string server_path = "inplace_sampler_server_" + std::to_string(getpid()); 327b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::unique_ptr<UnixSocketServer> server = UnixSocketServer::Create(server_path, true); 328b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (server == nullptr) { 329b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui LOG(ERROR) << "failed to create server at path " << server_path; 330b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return nullptr; 331b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 332b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui LOG(INFO) << "Create inplace_sampler_server at " << server_path; 333b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui while (true) { 334b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::unique_ptr<UnixSocketConnection> conn = server->AcceptConnection(); 335b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (conn == nullptr) { 336b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui break; 337b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 338b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui SampleManager manager(std::move(conn)); 339b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui manager.Run(); 340b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 341b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return nullptr; 342b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} 343b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 344b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui__attribute__((constructor)) void InitSampler() { 345b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui pthread_attr_t attr; 346b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (pthread_attr_init(&attr) != 0) { 347b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui LOG(ERROR) << "pthread_attr_init failed"; 348b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return; 349b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 350b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0) { 351b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui LOG(ERROR) << "pthread_attr_setdetachstate failed"; 352b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return; 353b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 354b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui pthread_t thread; 355b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (pthread_create(&thread, &attr, CommunicationThread, nullptr) != 0) { 356b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui LOG(ERROR) << "pthread_create failed"; 357b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return; 358b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 359b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui pthread_attr_destroy(&attr); 360b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} 361b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 362b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} // namespace 363