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