blob: 30423a47a7bcd03a0adb7d2ab307f5e41f865c4a [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Elliott Hughes11e45072011-08-16 17:40:46 -070016
Elliott Hughes42ee1422011-09-06 12:33:32 -070017#include "utils.h"
18
Christopher Ferris943af7d2014-01-16 12:41:46 -080019#include <inttypes.h>
Elliott Hughes92b3b562011-09-08 16:32:26 -070020#include <pthread.h>
Brian Carlstroma9f19782011-10-13 00:14:47 -070021#include <sys/stat.h>
Elliott Hughes42ee1422011-09-06 12:33:32 -070022#include <sys/types.h>
23#include <unistd.h>
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070024
Wei Li8991ad02018-09-13 16:43:39 +080025#include <fstream>
Ian Rogers700a4022014-05-19 16:49:03 -070026#include <memory>
Elliott Hughes42ee1422011-09-06 12:33:32 -070027
David Sehr013fd802018-01-11 22:55:24 -080028#include "android-base/file.h"
Andreas Gampe46ee31b2016-12-14 10:11:49 -080029#include "android-base/stringprintf.h"
Andreas Gampe9186ced2016-12-12 14:28:21 -080030#include "android-base/strings.h"
31
David Sehr1979c642018-04-26 14:41:18 -070032#include "os.h"
Elliott Hughes11e45072011-08-16 17:40:46 -070033
Elliott Hughes4ae722a2012-03-13 11:08:51 -070034#if defined(__APPLE__)
David Sehrfa442002016-08-22 18:42:08 -070035#include <crt_externs.h>
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070036#include <sys/syscall.h>
37#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED
Elliott Hughes4ae722a2012-03-13 11:08:51 -070038#endif
39
Orion Hodsonf2331362018-07-11 15:14:10 +010040#if defined(__BIONIC__)
41// membarrier(2) is only supported for target builds (b/111199492).
42#include <linux/membarrier.h>
43#include <sys/syscall.h>
44#endif
45
Elliott Hughes058a6de2012-05-24 19:13:02 -070046#if defined(__linux__)
Elliott Hughese1aee692012-01-17 16:40:10 -080047#include <linux/unistd.h>
David Sehr10db8fe2018-07-18 11:01:20 -070048#include <sys/syscall.h>
49#endif
50
51#if defined(_WIN32)
52#include <windows.h>
53// This include needs to be here due to our coding conventions. Unfortunately
54// it drags in the definition of the dread ERROR macro.
55#ifdef ERROR
56#undef ERROR
57#endif
Elliott Hughese1aee692012-01-17 16:40:10 -080058#endif
59
Elliott Hughes11e45072011-08-16 17:40:46 -070060namespace art {
61
David Sehr013fd802018-01-11 22:55:24 -080062using android::base::ReadFileToString;
Andreas Gampe46ee31b2016-12-14 10:11:49 -080063using android::base::StringPrintf;
64
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080065pid_t GetTid() {
Brian Carlstromf3a26412012-08-24 11:06:02 -070066#if defined(__APPLE__)
67 uint64_t owner;
Mathieu Chartier2cebb242015-04-21 16:50:40 -070068 CHECK_PTHREAD_CALL(pthread_threadid_np, (nullptr, &owner), __FUNCTION__); // Requires Mac OS 10.6
Brian Carlstromf3a26412012-08-24 11:06:02 -070069 return owner;
Elliott Hughes323aa862014-08-20 15:00:04 -070070#elif defined(__BIONIC__)
71 return gettid();
David Sehr10db8fe2018-07-18 11:01:20 -070072#elif defined(_WIN32)
73 return static_cast<pid_t>(::GetCurrentThreadId());
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080074#else
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080075 return syscall(__NR_gettid);
76#endif
77}
78
Elliott Hughes289be852012-06-12 13:57:20 -070079std::string GetThreadName(pid_t tid) {
80 std::string result;
David Sehr10db8fe2018-07-18 11:01:20 -070081#ifdef _WIN32
82 UNUSED(tid);
83 result = "<unknown>";
84#else
David Sehr013fd802018-01-11 22:55:24 -080085 // TODO: make this less Linux-specific.
Elliott Hughes289be852012-06-12 13:57:20 -070086 if (ReadFileToString(StringPrintf("/proc/self/task/%d/comm", tid), &result)) {
Brian Carlstrom7934ac22013-07-26 10:54:15 -070087 result.resize(result.size() - 1); // Lose the trailing '\n'.
Elliott Hughes289be852012-06-12 13:57:20 -070088 } else {
89 result = "<unknown>";
90 }
David Sehr10db8fe2018-07-18 11:01:20 -070091#endif
Elliott Hughes289be852012-06-12 13:57:20 -070092 return result;
93}
94
Mathieu Chartiere6da9af2013-12-16 11:54:42 -080095std::string PrettySize(int64_t byte_count) {
Elliott Hughesc967f782012-04-16 10:23:15 -070096 // The byte thresholds at which we display amounts. A byte count is displayed
97 // in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1].
Ian Rogersef7d42f2014-01-06 12:55:46 -080098 static const int64_t kUnitThresholds[] = {
David Srbeckyde6c7142019-01-09 11:27:40 +000099 0, // B up to...
100 10*KB, // KB up to...
101 10*MB, // MB up to...
102 10LL*GB // GB from here.
Elliott Hughesc967f782012-04-16 10:23:15 -0700103 };
Mathieu Chartiere6da9af2013-12-16 11:54:42 -0800104 static const int64_t kBytesPerUnit[] = { 1, KB, MB, GB };
Elliott Hughesc967f782012-04-16 10:23:15 -0700105 static const char* const kUnitStrings[] = { "B", "KB", "MB", "GB" };
Mathieu Chartiere6da9af2013-12-16 11:54:42 -0800106 const char* negative_str = "";
107 if (byte_count < 0) {
108 negative_str = "-";
109 byte_count = -byte_count;
110 }
Elliott Hughesc967f782012-04-16 10:23:15 -0700111 int i = arraysize(kUnitThresholds);
112 while (--i > 0) {
113 if (byte_count >= kUnitThresholds[i]) {
114 break;
115 }
Ian Rogers3bb17a62012-01-27 23:56:44 -0800116 }
Brian Carlstrom474cc792014-03-07 14:18:15 -0800117 return StringPrintf("%s%" PRId64 "%s",
118 negative_str, byte_count / kBytesPerUnit[i], kUnitStrings[i]);
Ian Rogers3bb17a62012-01-27 23:56:44 -0800119}
120
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700121void Split(const std::string& s, char separator, std::vector<std::string>* result) {
Elliott Hughes34023802011-08-30 12:06:17 -0700122 const char* p = s.data();
123 const char* end = p + s.size();
124 while (p != end) {
Elliott Hughes48436bb2012-02-07 15:23:28 -0800125 if (*p == separator) {
Elliott Hughes34023802011-08-30 12:06:17 -0700126 ++p;
127 } else {
128 const char* start = p;
Elliott Hughes48436bb2012-02-07 15:23:28 -0800129 while (++p != end && *p != separator) {
130 // Skip to the next occurrence of the separator.
Elliott Hughes34023802011-08-30 12:06:17 -0700131 }
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700132 result->push_back(std::string(start, p - start));
Elliott Hughes34023802011-08-30 12:06:17 -0700133 }
134 }
135}
136
Elliott Hughes22869a92012-03-27 14:08:24 -0700137void SetThreadName(const char* thread_name) {
Elliott Hughesdcc24742011-09-07 14:02:44 -0700138 int hasAt = 0;
139 int hasDot = 0;
Elliott Hughes22869a92012-03-27 14:08:24 -0700140 const char* s = thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -0700141 while (*s) {
142 if (*s == '.') {
143 hasDot = 1;
144 } else if (*s == '@') {
145 hasAt = 1;
146 }
147 s++;
148 }
Elliott Hughes22869a92012-03-27 14:08:24 -0700149 int len = s - thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -0700150 if (len < 15 || hasAt || !hasDot) {
Elliott Hughes22869a92012-03-27 14:08:24 -0700151 s = thread_name;
Elliott Hughesdcc24742011-09-07 14:02:44 -0700152 } else {
Elliott Hughes22869a92012-03-27 14:08:24 -0700153 s = thread_name + len - 15;
Elliott Hughesdcc24742011-09-07 14:02:44 -0700154 }
David Sehr10db8fe2018-07-18 11:01:20 -0700155#if defined(__linux__) || defined(_WIN32)
Elliott Hughes7c6a61e2012-03-12 18:01:41 -0700156 // pthread_setname_np fails rather than truncating long strings.
Elliott Hughes0a18df82015-01-09 15:16:16 -0800157 char buf[16]; // MAX_TASK_COMM_LEN=16 is hard-coded in the kernel.
Elliott Hughesdcc24742011-09-07 14:02:44 -0700158 strncpy(buf, s, sizeof(buf)-1);
159 buf[sizeof(buf)-1] = '\0';
160 errno = pthread_setname_np(pthread_self(), buf);
161 if (errno != 0) {
162 PLOG(WARNING) << "Unable to set the name of current thread to '" << buf << "'";
163 }
Elliott Hughes0a18df82015-01-09 15:16:16 -0800164#else // __APPLE__
Elliott Hughes22869a92012-03-27 14:08:24 -0700165 pthread_setname_np(thread_name);
Elliott Hughesdcc24742011-09-07 14:02:44 -0700166#endif
167}
168
Brian Carlstrom29212012013-09-12 22:18:30 -0700169void GetTaskStats(pid_t tid, char* state, int* utime, int* stime, int* task_cpu) {
170 *utime = *stime = *task_cpu = 0;
David Sehr10db8fe2018-07-18 11:01:20 -0700171#ifdef _WIN32
172 // TODO: implement this.
173 UNUSED(tid);
174 *state = 'S';
175#else
Elliott Hughesbfe487b2011-10-26 15:48:55 -0700176 std::string stats;
David Sehr013fd802018-01-11 22:55:24 -0800177 // TODO: make this less Linux-specific.
Elliott Hughes8a31b502012-04-30 19:36:11 -0700178 if (!ReadFileToString(StringPrintf("/proc/self/task/%d/stat", tid), &stats)) {
Elliott Hughesbfe487b2011-10-26 15:48:55 -0700179 return;
180 }
181 // Skip the command, which may contain spaces.
182 stats = stats.substr(stats.find(')') + 2);
183 // Extract the three fields we care about.
184 std::vector<std::string> fields;
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700185 Split(stats, ' ', &fields);
Brian Carlstrom29212012013-09-12 22:18:30 -0700186 *state = fields[0][0];
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700187 *utime = strtoull(fields[11].c_str(), nullptr, 10);
188 *stime = strtoull(fields[12].c_str(), nullptr, 10);
189 *task_cpu = strtoull(fields[36].c_str(), nullptr, 10);
David Sehr10db8fe2018-07-18 11:01:20 -0700190#endif
Elliott Hughesbfe487b2011-10-26 15:48:55 -0700191}
192
Mathieu Chartier4d87df62016-01-07 15:14:19 -0800193void SleepForever() {
194 while (true) {
195 usleep(1000000);
196 }
197}
198
Wei Li8991ad02018-09-13 16:43:39 +0800199std::string GetProcessStatus(const char* key) {
200 // Build search pattern of key and separator.
201 std::string pattern(key);
202 pattern.push_back(':');
203
204 // Search for status lines starting with pattern.
205 std::ifstream fs("/proc/self/status");
206 std::string line;
207 while (std::getline(fs, line)) {
208 if (strncmp(pattern.c_str(), line.c_str(), pattern.size()) == 0) {
209 // Skip whitespace in matching line (if any).
210 size_t pos = line.find_first_not_of(" \t", pattern.size());
211 if (UNLIKELY(pos == std::string::npos)) {
212 break;
213 }
214 return std::string(line, pos);
215 }
216 }
217 return "<unknown>";
218}
219
Elliott Hughes42ee1422011-09-06 12:33:32 -0700220} // namespace art