126968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui/* 226968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui * Copyright (C) 2017 The Android Open Source Project 326968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui * 426968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui * Licensed under the Apache License, Version 2.0 (the "License"); 526968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui * you may not use this file except in compliance with the License. 626968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui * You may obtain a copy of the License at 726968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui * 826968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui * http://www.apache.org/licenses/LICENSE-2.0 926968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui * 1026968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui * Unless required by applicable law or agreed to in writing, software 1126968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui * distributed under the License is distributed on an "AS IS" BASIS, 1226968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1326968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui * See the License for the specific language governing permissions and 1426968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui * limitations under the License. 1526968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui */ 1626968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui 1726968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui#include "InplaceSamplerClient.h" 1826968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui 19b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include <algorithm> 2026968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui 2126968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui#include "environment.h" 22b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui#include "inplace_sampler_lib.h" 2326968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui#include "utils.h" 2426968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui 2526968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cuistatic constexpr uint64_t EVENT_ID_FOR_INPLACE_SAMPLER = ULONG_MAX; 2626968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui 2726968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cuistd::unique_ptr<InplaceSamplerClient> InplaceSamplerClient::Create(const perf_event_attr& attr, 2826968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui pid_t pid, 2926968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui const std::set<pid_t>& tids) { 3026968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui if (pid == -1) { 3126968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui LOG(ERROR) << "inplace-sampler can't monitor system wide events."; 3226968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui return nullptr; 3326968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui } 3426968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui std::unique_ptr<InplaceSamplerClient> sampler(new InplaceSamplerClient(attr, pid, tids)); 3526968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui if (!sampler->ConnectServer()) { 3626968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui return nullptr; 3726968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui } 3826968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui return sampler; 3926968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui} 4026968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui 4126968e6c48dea2eaa217991ade5a04e801f1be8fYabin CuiInplaceSamplerClient::InplaceSamplerClient(const perf_event_attr& attr, pid_t pid, 4226968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui const std::set<pid_t>& tids) 43b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui : attr_(attr), pid_(pid), tids_(tids), got_start_profiling_reply_msg_(false) { 44b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (attr_.freq) { 45b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui sample_freq_ = attr_.sample_freq; 46b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } else { 47b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui sample_freq_ = std::max(1u, static_cast<uint32_t>(1000000000 / attr_.sample_period)); 48b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 4926968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui} 5026968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui 5126968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cuiuint64_t InplaceSamplerClient::Id() const { 5226968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui return EVENT_ID_FOR_INPLACE_SAMPLER; 5326968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui} 5426968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui 5526968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cuibool InplaceSamplerClient::ConnectServer() { 56b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::string server_path = "inplace_sampler_server_" + std::to_string(pid_); 57b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui // Try to connect server in 1s. 58b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui uint64_t timeout = GetSystemClock() + 10000000000ull; 59b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui while (GetSystemClock() < timeout) { 60b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui conn_ = UnixSocketConnection::Connect(server_path, true); 61b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (conn_ != nullptr) { 62b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return true; 63b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 64b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui usleep(10); 65b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 66b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui LOG(ERROR) << "Can't find inplace_sampler_server for process " << pid_; 67b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return false; 6826968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui} 6926968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui 7026968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cuibool InplaceSamplerClient::StartPolling(IOEventLoop& loop, 7126968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui const std::function<bool(Record*)>& record_callback, 7226968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui const std::function<bool()>& close_callback) { 7326968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui record_callback_ = record_callback; 74b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui CHECK(conn_ != nullptr); 75b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui auto read_callback = [&](const UnixSocketMessage& msg) { 76b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return HandleMessage(msg); 77b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui }; 78b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!conn_->PrepareForIO(loop, read_callback, close_callback)) { 79b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return false; 80b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 81b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!SendStartProfilingMessage()) { 82b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return false; 83b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 84b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui // If the inplace sampler doesn't reply in 3 seconds, report the error. 85b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui timeval tv; 86b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui tv.tv_sec = 3; 87b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui tv.tv_usec = 0; 88b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui auto check_reply_callback = [this]() { 89b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!got_start_profiling_reply_msg_) { 90b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui LOG(ERROR) << "can't receive START_PROFILING_REPLY from process " << pid_; 91b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return false; 92b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 93b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return true; 94b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui }; 95b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return loop.AddPeriodicEvent(tv, check_reply_callback); 96b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} 97b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 98b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuibool InplaceSamplerClient::SendStartProfilingMessage() { 99b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::string options; 100b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui options += "freq=" + std::to_string(sample_freq_); 101b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (attr_.sample_type & PERF_SAMPLE_CALLCHAIN) { 102b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui options += " dump_callchain=1"; 103b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 104b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!tids_.empty()) { 105b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui options += " tids="; 106b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui bool first = true; 107b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui for (auto& tid : tids_) { 108b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (first) { 109b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui first = false; 110b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } else { 111b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui options.push_back(','); 112b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 113b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui options += std::to_string(tid); 114b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 115b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 116b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui size_t size = sizeof(UnixSocketMessage) + options.size() + 1; 117b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::unique_ptr<char[]> data(new char[size]); 118b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui UnixSocketMessage* msg = reinterpret_cast<UnixSocketMessage*>(data.get()); 119b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui msg->len = size; 120b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui msg->type = START_PROFILING; 121b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui strcpy(msg->data, options.c_str()); 122b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return conn_->SendMessage(*msg, true); 123b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} 124b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 125b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuibool InplaceSamplerClient::StopProfiling(IOEventLoop& loop, 126b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui const std::function<bool()>& close_callback) { 127b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui auto read_callback = [&](const UnixSocketMessage& msg) { 128b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return HandleMessage(msg); 129b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui }; 130b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!conn_->PrepareForIO(loop, read_callback, close_callback)) { 131b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return false; 132b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 133b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui // Notify inplace sampler to send buffered data and close the connection. 134b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui UnixSocketMessage msg; 135b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui msg.len = sizeof(UnixSocketMessage); 136b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui msg.type = END_PROFILING; 137b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return conn_->SendMessage(msg, true); 138b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui} 139b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui 140b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cuibool InplaceSamplerClient::HandleMessage(const UnixSocketMessage& msg) { 141b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui const char* p = msg.data; 142b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (msg.type == START_PROFILING_REPLY) { 143b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui got_start_profiling_reply_msg_ = true; 144b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (strcmp(p, "ok") != 0) { 145b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui LOG(ERROR) << "receive reply from inplace_sampler_server of " << pid_ << ": " << p; 146b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return false; 147b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 148b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } else if (msg.type == THREAD_INFO) { 149b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui uint64_t time; 150b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui uint32_t tid; 151b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveFromBinaryFormat(time, p); 152b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveFromBinaryFormat(tid, p); 153b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui CommRecord r(attr_, pid_, tid, p, Id(), time); 154b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!record_callback_(&r)) { 15526968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui return false; 15626968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui } 157b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } else if (msg.type == MAP_INFO) { 158b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui uint64_t time; 159b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui uint64_t start; 160b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui uint64_t len; 161b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui uint64_t pgoff; 162b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveFromBinaryFormat(time, p); 163b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveFromBinaryFormat(start, p); 164b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveFromBinaryFormat(len, p); 165b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveFromBinaryFormat(pgoff, p); 166b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MmapRecord r(attr_, false, pid_, pid_, start, len, pgoff, p, Id(), time); 167b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui if (!record_callback_(&r)) { 16826968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui return false; 16926968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui } 170b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } else if (msg.type == SAMPLE_INFO) { 171b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui uint64_t time; 172b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui uint32_t tid; 173b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui uint32_t period; 174b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui uint32_t ip_nr; 175b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveFromBinaryFormat(time, p); 176b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveFromBinaryFormat(tid, p); 177b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveFromBinaryFormat(period, p); 178b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveFromBinaryFormat(ip_nr, p); 179b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui std::vector<uint64_t> ips(ip_nr); 180b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui MoveFromBinaryFormat(ips.data(), ip_nr, p); 181b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui // Don't know which cpu tid is running on, use cpu 0. 182b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui SampleRecord r(attr_, Id(), ips[0], pid_, tid, time, 0, period, ips); 18326968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui if (!record_callback_(&r)) { 18426968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui return false; 18526968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui } 186b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } else { 187b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui LOG(ERROR) << "Unexpected msg type: " << msg.type; 188b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return false; 189b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui } 190b92bae84b27889b548214bee8d0730ef10da0c6dYabin Cui return true; 19126968e6c48dea2eaa217991ade5a04e801f1be8fYabin Cui} 192